<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Evans Library]]></title><description><![CDATA[개발자의 집필 공간. 표상에서 그치는 것이 아닌, 본질을 탐구하고 사유하는 삶.]]></description><link>https://evan-moon.github.io</link><generator>GatsbyJS</generator><lastBuildDate>Sat, 21 Feb 2026 00:56:50 GMT</lastBuildDate><item><title><![CDATA[When AI Writes the Code, a Developer's Real Skills Show]]></title><description><![CDATA[This post is about how the developer role is changing in the AI era, and what to do about it. It’s something I hear a lot at work lately - and honestly, it’s not just developers. Most knowledge workers seem to be sitting with the same anxiety.]]></description><link>https://evan-moon.github.io/2026/02/10/developer-in-ai-era/en/</link><guid isPermaLink="false">20260210-developer-in-ai-era-en</guid><pubDate>Tue, 10 Feb 2026 09:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This post is about how the developer role is changing in the AI era, and what to do about it. It’s something I hear a lot at work lately - and honestly, it’s not just developers. Most knowledge workers seem to be sitting with the same anxiety.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;The feeling tends to be equal parts excitement about what AI can do for productivity, and unease about what it might do to jobs.&lt;/p&gt;
&lt;p&gt;Nobody knows how this actually plays out, and I’m no exception. But doing nothing feels worse. So here’s how I’ve been thinking about it.&lt;/p&gt;
&lt;h2 id=&quot;three-years-since-chatgpt&quot; style=&quot;position:relative;&quot;&gt;Three years since ChatGPT&lt;a href=&quot;#three-years-since-chatgpt&quot; aria-label=&quot;three years since chatgpt permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When ChatGPT launched in late 2022, I genuinely didn’t expect it to move this fast. There were constant hallucination problems, and the output quality wasn’t particularly impressive.&lt;/p&gt;
&lt;p&gt;Three years later, a significant chunk of how I spend my day has changed.&lt;/p&gt;
&lt;p&gt;The job used to be something like: understand what people need, design a solution, write code until it exists. You’d take requirements written in natural language, think through the design, and translate all of it into code by hand.&lt;/p&gt;
&lt;p&gt;Not long ago, my morning started with opening an editor and placing the cursor in a blank file. Now it’s more like: explain the context to an AI, read what comes back, ask again, adjust, repeat.&lt;/p&gt;
&lt;p&gt;I’ve been through the shift from feature phones to smartphones - that already felt fast. This is faster.&lt;/p&gt;
&lt;p&gt;AI coding agents have been well past “basic autocomplete” for a while now. Give them a clear prompt and they’ll produce a function or module that’s hard to distinguish from what a developer would write. In this environment, writing every line yourself is becoming inefficient for at least some categories of work.&lt;/p&gt;
&lt;p&gt;Things will probably keep accelerating. How the developer role reshapes itself will depend on the team and the context. The question is what to focus on now.&lt;/p&gt;
&lt;h2 id=&quot;from-code-writer-to-decision-maker&quot; style=&quot;position:relative;&quot;&gt;From code writer to decision-maker&lt;a href=&quot;#from-code-writer-to-decision-maker&quot; aria-label=&quot;from code writer to decision maker permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To answer that, it helps to look at where the time goes. Time used to go into typing. Now it goes into prompting, reading generated output, adjusting, and prompting again.&lt;/p&gt;
&lt;p&gt;Building software is shifting from direct code authorship toward something more like judgment - not just checking whether the AI did what you asked, but verifying that the business intent actually made it through to the technical implementation.&lt;/p&gt;
&lt;p&gt;You could argue that as AI improves, even code review will be automated away. I don’t think so, and the reason isn’t about technical capability.&lt;/p&gt;
&lt;h3 id=&quot;someone-has-to-be-accountable-for-the-code&quot; style=&quot;position:relative;&quot;&gt;Someone has to be accountable for the code&lt;a href=&quot;#someone-has-to-be-accountable-for-the-code&quot; aria-label=&quot;someone has to be accountable for the code permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A lot of developers are already using AI for code review - it reads the PR and leaves comments. Honestly, some of those comments are pretty sharp. It catches things I’d miss.&lt;/p&gt;
&lt;p&gt;But I think there’ll always be a human who needs to put the final stamp on “this is okay to ship.” The reason comes down to one question.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When the code causes a problem, who is responsible?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AI is not a legal entity. It cannot be held accountable. So when AI-generated code breaks something, the question of who answers for it becomes urgent.&lt;/p&gt;
&lt;p&gt;Say AI-written code has a bug in the payment logic that charges customers the wrong amount. What happens if the company responds like this:&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 268px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6d88ccc76e457cfbd94e60f058a4d6cf/6b6e1/dontknow.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 70%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIBBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe7lSWD/xAAXEAADAQAAAAAAAAAAAAAAAAAAAREg/9oACAEBAAEFAqLP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGhAAAQUBAAAAAAAAAAAAAAAAAQAQESFBYf/aAAgBAQABPyGmIyTbYEBE8b//2gAMAwEAAgADAAAAEAMP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGhAAAwEBAQEAAAAAAAAAAAAAAREhADEQUf/aAAgBAQABPxAoAYzdYSrUPjh9wgIEuO4Ub//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;dontknow&quot; title=&quot;&quot; src=&quot;/static/6d88ccc76e457cfbd94e60f058a4d6cf/6b6e1/dontknow.jpg&quot; srcset=&quot;/static/6d88ccc76e457cfbd94e60f058a4d6cf/0913d/dontknow.jpg 160w,
/static/6d88ccc76e457cfbd94e60f058a4d6cf/6b6e1/dontknow.jpg 268w&quot; sizes=&quot;(max-width: 268px) 100vw, 268px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;&quot;It was written by AI, so honestly, I have no idea why this happened.&quot;&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;No customer is going to accept that. Put yourself on the receiving end and it’s infuriating.&lt;/p&gt;
&lt;p&gt;No matter who wrote the code, someone is accountable. The way I see it, that’s the developer who reviewed and approved it, and the organization they work for.&lt;/p&gt;
&lt;p&gt;This isn’t just speculation - it’s already showing up in regulation.&lt;/p&gt;
&lt;p&gt;The EU AI Act, which took effect in 2024, mandates human oversight of AI systems in high-risk areas like healthcare, finance, and infrastructure. The principle is clear: even when AI makes the call, humans must be able to review the process. It’s now law.&lt;/p&gt;
&lt;p&gt;There are also ongoing discussions in the EU about extending product liability frameworks to digital products and software. “AI made it, not us” is becoming a harder argument to make legally.&lt;/p&gt;
&lt;p&gt;Real-world precedents outside software point the same direction. When autonomous vehicles crash, liability goes to the manufacturer and driver. FDA-approved AI diagnostic tools still require a physician to make the final call. The 2010 Flash Crash, where algorithmic trading caused a cascading market collapse, showed that whoever runs the automated system is who the regulators come after.&lt;/p&gt;
&lt;p&gt;The more automation you add, the sharper the line gets between the human in the loop and the consequences of what that loop produces.&lt;/p&gt;
&lt;p&gt;So I don’t think the developer role disappears. It shifts from writing code to reviewing and approving it. The method of producing code has changed. What hasn’t changed is that the quality of the final product depends on whoever reviews it. So what does that actually require?&lt;/p&gt;
&lt;h2 id=&quot;what-ai-era-development-actually-demands&quot; style=&quot;position:relative;&quot;&gt;What AI-era development actually demands&lt;a href=&quot;#what-ai-era-development-actually-demands&quot; aria-label=&quot;what ai era development actually demands permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The obvious guess is that prompt engineering or AI tool fluency becomes the key skill. I think that’s wrong.&lt;/p&gt;
&lt;p&gt;You can now tell an AI “write this like Martin Fowler would” and get something that looks reasonable. But so can everyone else who types that sentence. What’s the edge there?&lt;/p&gt;
&lt;p&gt;The real skill is knowing when the output doesn’t meet the bar - even when the prompt was supposedly good. Good prompts don’t guarantee good code.&lt;/p&gt;
&lt;p&gt;Ironically, the skills that matter in the AI era aren’t that different from what has always separated good developers from average ones.&lt;/p&gt;
&lt;p&gt;Because review still requires checking: will this break at runtime? Is it maintainable six months from now? Are there missing error cases? Does it violate any policies? And as long as a human is the one signing off, code still needs to be readable by humans.&lt;/p&gt;
&lt;p&gt;If humans never needed to read code, we could ship bytecode. But you’re the one who has to answer when something breaks. Can you really approve a deploy without reading what you’re shipping?&lt;/p&gt;
&lt;p&gt;As long as that accountability constraint holds, the questions developers think about today - what makes code readable, what makes it maintainable - will remain relevant.&lt;/p&gt;
&lt;h3 id=&quot;predicting-the-long-term-cost-of-change&quot; style=&quot;position:relative;&quot;&gt;Predicting the long-term cost of change&lt;a href=&quot;#predicting-the-long-term-cost-of-change&quot; aria-label=&quot;predicting the long term cost of change permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Scroll through LinkedIn lately and you see a pattern. A year ago it was “look what I built with AI in a weekend.” Now it’s occasionally “hired developers because we couldn’t maintain it” or “shut it down because we couldn’t add features.” Both kinds of posts are real.&lt;/p&gt;
&lt;p&gt;This happens because AI is optimized for working code. It reproduces the patterns that appear most often in training data. Those patterns are, by definition, code that runs. Code that runs and code that’s easy to maintain six months later are two different things.&lt;/p&gt;
&lt;p&gt;Newer models are getting better at factoring in maintainability. But that’s not quite the point. Output quality and predicting the long-term cost of change are separate problems.&lt;/p&gt;
&lt;p&gt;Software quality doesn’t reveal itself immediately. The cost of a bad design shows up when you have to change the code, not when you write it.&lt;/p&gt;
&lt;h3 id=&quot;evaluating-code-from-multiple-angles&quot; style=&quot;position:relative;&quot;&gt;Evaluating code from multiple angles&lt;a href=&quot;#evaluating-code-from-multiple-angles&quot; aria-label=&quot;evaluating code from multiple angles permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This was true before AI too. The difference now is that generation speed has increased, so deferred costs accumulate faster.&lt;/p&gt;
&lt;p&gt;Review covers multiple dimensions. Functional correctness - does it do the right thing - is the part tests can catch. The harder part is structural quality.&lt;/p&gt;
&lt;p&gt;Is this module’s responsibility scoped correctly? Is the dependency direction right? Is this interface flexible enough for future changes? Tests don’t answer these. Then there’s performance: the code works, but does it hold up when data volume is 10x? And security: is input validation sufficient, or is there a missing authorization check somewhere?&lt;/p&gt;
&lt;p&gt;Evaluating code across all of these dimensions at once is a different skill from just reading code.&lt;/p&gt;
&lt;p&gt;And as generation speed increases, this gets harder.&lt;/p&gt;
&lt;p&gt;When developers wrote everything by hand, there was a physical ceiling on output. A developer can only type so much in a day, so the volume of code the team needed to review was naturally paced. Writing slowly doesn’t make code better - but it does mean production couldn’t easily outpace review capacity.&lt;/p&gt;
&lt;p&gt;When AI can generate hundreds of lines in seconds, that balance breaks easily. Without solid review standards, parallel review processes, and automated gates, you can double or triple code volume while review capacity stays flat. Things start slipping through. Technical debt accumulates faster. The production line sped up but the quality control process didn’t.&lt;/p&gt;
&lt;p&gt;My guess is this explains why many companies adopt AI and still don’t feel more productive. Code production got faster; review became the bottleneck.&lt;/p&gt;
&lt;p&gt;In this structure, developers who can review code well and quickly become more valuable. The more code AI generates, the more you need someone who can filter out the hidden risks and bad abstractions mixed into that output.&lt;/p&gt;
&lt;h3 id=&quot;abstraction&quot; style=&quot;position:relative;&quot;&gt;Abstraction&lt;a href=&quot;#abstraction&quot; aria-label=&quot;abstraction permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Abstraction is another one. At its core, abstraction means deciding what to hide and what to expose in a complex system - where to draw the lines.&lt;/p&gt;
&lt;p&gt;AI can do abstraction. It defines interfaces, divides classes, separates modules. Formally speaking, it sometimes does this better than I would. But there’s a key difference between AI abstraction and what an experienced developer produces.&lt;/p&gt;
&lt;p&gt;AI abstraction is based on statistical averages from training data. It takes patterns that looked plausible across thousands of projects and applies whichever one fits closest. But real software design isn’t a multiple-choice test. It’s a series of tradeoff decisions made under resource constraints and uncertainty about the future.&lt;/p&gt;
&lt;p&gt;AI can maintain internal consistency in code. What it struggles with is factoring in external context - the stuff that lives outside the codebase - when deciding where to draw the lines. Code that’s optimal for a specific situation requires strategic judgment that goes beyond statistical norms.&lt;/p&gt;
&lt;p&gt;This isn’t really a flaw in AI - it’s a structural limit of statistical learning. You can produce code that’s good on average. Code that’s optimal for your specific situation is a different problem.&lt;/p&gt;
&lt;p&gt;The dangerous thing about AI-generated code is that it looks fine. Files are properly separated, naming follows convention, patterns are familiar. It passes review easily.&lt;/p&gt;
&lt;p&gt;The problem shows up later. You try to add a payment method and realize the “cleanly separated” structure requires changes in five different places simultaneously. This kind of defect doesn’t appear when you write the code. It appears when you try to change it.&lt;/p&gt;
&lt;p&gt;AI-generated code shows this pattern fairly often. The structure follows common conventions perfectly, but it doesn’t quite fit the actual requirements.&lt;/p&gt;
&lt;p&gt;A frontend example: ask AI to build a dashboard component and it typically produces one giant component with data fetching, state management, and UI rendering all mixed together. Or it over-applies best practices from training data and builds three custom hooks and a context provider just to render a single chart.&lt;/p&gt;
&lt;p&gt;One is under-abstracted, one is over-abstracted. Both are wrong in the same way: neither fits the actual complexity level of the project. Good abstraction means creating exactly as much structure as the current situation requires. Knowing how much that is requires knowing the context.&lt;/p&gt;
&lt;p&gt;An experienced developer reads this code, recognizes that the boundaries were drawn without understanding the domain, and redraws them. What that takes isn’t coding skill. It’s understanding of the system and a sense of design.&lt;/p&gt;
&lt;p&gt;The same standard applies whether a human or AI wrote the code: is this abstraction actually reducing complexity, or just adding more indirection to track? Being able to ask that question is already a skill.&lt;/p&gt;
&lt;h3 id=&quot;articulating-tacit-knowledge&quot; style=&quot;position:relative;&quot;&gt;Articulating tacit knowledge&lt;a href=&quot;#articulating-tacit-knowledge&quot; aria-label=&quot;articulating tacit knowledge permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If abstraction is knowing where to draw the lines, articulating tacit knowledge is being able to explain why the lines go there. Related, but different. In practice they work together.&lt;/p&gt;
&lt;p&gt;The instinct for recognizing bad code builds up gradually through reading and writing a lot of code. It usually starts as “something feels off” - tacit knowledge that’s genuinely hard to put into words.&lt;/p&gt;
&lt;p&gt;Translating that instinct into language matters more now. “Something feels off” needs to become “this function has two responsibilities” or “this interface will break under change” - concrete enough to actually direct an AI.&lt;/p&gt;
&lt;p&gt;This isn’t about prompt tricks like few-shot examples or chain-of-thought formatting. Those get absorbed into the model as it improves. What I’m talking about is the underlying ability: clearly defining what needs to be built, and knowing which context matters enough to include.&lt;/p&gt;
&lt;p&gt;Anyone can say “build me this thing.” What matters is being able to identify exactly what’s wrong with what comes back, and explain specifically why it should be built differently.&lt;/p&gt;
&lt;p&gt;Seeing “something wrong” code and knowing concretely what that something is - that’s design competence. The deeper your understanding of the system, the more precise your instructions to AI can be.&lt;/p&gt;
&lt;p&gt;You don’t manipulate memory directly anymore, but you still need to understand the memory model to debug performance problems. You may not write every line of code, but you still need to understand abstraction to catch design problems. There’s an extra layer of indirection; the underlying need hasn’t gone away.&lt;/p&gt;
&lt;p&gt;These skills have a longer shelf life than tool fluency. Tool fluency expires when the tool does. jQuery gave way to React. Webpack gave way to Vite. Design judgment and the ability to articulate tacit knowledge are valid as long as software has essential complexity - which is to say, indefinitely.&lt;/p&gt;
&lt;p&gt;That complexity doesn’t disappear when the tools change. Payment systems are complicated because payments are complicated, not because of the framework. The instinct for handling that complexity doesn’t belong to any particular tool.&lt;/p&gt;
&lt;h2 id=&quot;the-need-for-deliberate-practice&quot; style=&quot;position:relative;&quot;&gt;The need for deliberate practice&lt;a href=&quot;#the-need-for-deliberate-practice&quot; aria-label=&quot;the need for deliberate practice permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A reasonable question at this point: if you’re writing less code, how do you build abstraction sense and design instinct?&lt;/p&gt;
&lt;p&gt;There’s a real tension here. You’re told to focus on what AI can’t do, while AI is quietly reducing the opportunities to practice those exact things.&lt;/p&gt;
&lt;p&gt;The answer has two parts. One is protecting two specific points in your daily workflow from AI. The other is deliberately maintaining design instinct outside of work. And there’s a single attitude that runs through both.&lt;/p&gt;
&lt;h3 id=&quot;two-points-to-keep-for-yourself-design-and-review&quot; style=&quot;position:relative;&quot;&gt;Two points to keep for yourself: design and review&lt;a href=&quot;#two-points-to-keep-for-yourself-design-and-review&quot; aria-label=&quot;two points to keep for yourself design and review permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In a normal workday, there are two points not to hand off to AI: design before writing code, and review after.&lt;/p&gt;
&lt;p&gt;Doing design yourself isn’t just a habit thing. If you define “what interface does this module expose?” and “where do the responsibilities end?” before you prompt, you can compare what AI produces against your own design decision.&lt;/p&gt;
&lt;p&gt;If AI chose a different structure, you end up analyzing why. Did it catch something you missed? Or did it get it wrong? Without this step, you’re likely just consuming output. Consuming output and evaluating output against your own judgment are completely different experiences.&lt;/p&gt;
&lt;p&gt;Review is the other one - and unlike deliberate practice, it shows up automatically in your workflow. Which is exactly why letting it slip is so dangerous.&lt;/p&gt;
&lt;p&gt;Delegating PR review to AI and approving with no objections is like going to PE class and sitting on the bench for the whole period. The work gets done somehow, but several years of this and your skills haven’t moved.&lt;/p&gt;
&lt;p&gt;Code review means reading code while holding requirements, design intent, and business context in your head at the same time. That process is the training.&lt;/p&gt;
&lt;h3 id=&quot;time-to-build-things-yourself&quot; style=&quot;position:relative;&quot;&gt;Time to build things yourself&lt;a href=&quot;#time-to-build-things-yourself&quot; aria-label=&quot;time to build things yourself permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Doing your own design and review at work isn’t enough on its own. Design instinct requires knowing the pain of implementation.&lt;/p&gt;
&lt;p&gt;You need to have personally experienced a structure falling apart under change before you can feel “this abstraction is wrong.” Pain you haven’t felt doesn’t become instinct.&lt;/p&gt;
&lt;p&gt;Junior developers especially. Reviewing AI-generated code without much experience is a bit like asking someone still learning to drive to evaluate a self-driving car’s decisions. You get a feel for the road by gripping the wheel. You get a feel for structure by writing the code.&lt;/p&gt;
&lt;p&gt;My guess is that for future developers, coding directly won’t be a daily job requirement - it’ll be more like ongoing training to maintain your judgment. &lt;small&gt;(Maybe the painful grind of building things from scratch as a junior becomes less of a job requirement and more of a certification process - how you earn the right to be trusted as a reviewer.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;So in side projects and personal learning, I think it’s worth deliberately putting AI aside and building things end-to-end yourself. The more convenient AI gets, the more annoying that friction feels. But the friction is the point.&lt;/p&gt;
&lt;p&gt;The moments where you get stuck, or where you realize you need to refactor - those are where the learning actually happens.&lt;/p&gt;
&lt;h3 id=&quot;the-attitude-that-runs-through-both-putting-why-into-words&quot; style=&quot;position:relative;&quot;&gt;The attitude that runs through both: putting “why” into words&lt;a href=&quot;#the-attitude-that-runs-through-both-putting-why-into-words&quot; aria-label=&quot;the attitude that runs through both putting why into words permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Whether you’re doing design and review at work, or building things alone in your own time, one attitude needs to run through both.&lt;/p&gt;
&lt;p&gt;When “something feels off” shows up, don’t let it slide. Stay with it until you can say clearly what’s actually wrong.&lt;/p&gt;
&lt;p&gt;Stopping at “feels off” is just a feeling. Getting to “this function has two responsibilities” is language. A feeling only you know. Language is usable. Once it’s language, you can direct AI precisely, explain it to teammates, and recognize the pattern when you see it again.&lt;/p&gt;
&lt;p&gt;When AI produces code that works, don’t stop there. Ask yourself: why did it choose this structure? What tradeoffs would a different approach have had?&lt;/p&gt;
&lt;p&gt;The gap between developers who ask this and developers who don’t will keep widening.&lt;/p&gt;
&lt;h2 id=&quot;the-fundamentals-havent-changed&quot; style=&quot;position:relative;&quot;&gt;The fundamentals haven’t changed&lt;a href=&quot;#the-fundamentals-havent-changed&quot; aria-label=&quot;the fundamentals havent changed permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AI is moving the developer role from code author to reviewer. We’re moving from humans doing both production and quality control, to AI handling production and humans handling quality control.&lt;/p&gt;
&lt;p&gt;Understanding that this shift is driven by accountability - a social and legal constraint, not a technical one - makes the role change clearer.&lt;/p&gt;
&lt;p&gt;Stamping “approved” well requires an eye for the difference between working code and durable code, the design sense to evaluate abstraction in context, and the ability to put that sense into words and steer accordingly.&lt;/p&gt;
&lt;p&gt;The edge in the AI era isn’t about who generates more. It’s about who understands context well enough to approve responsibly. Developers are still accountable for code quality. That hasn’t changed.&lt;/p&gt;
&lt;p&gt;AI is genuinely different from previous tools. Unlike a plow or a compiler, it reasons and generates. “It’s just another tool” isn’t a convincing argument anymore. So why would the required skills stay the same?&lt;/p&gt;
&lt;p&gt;Start with accountability. Being accountable means making judgments. The quality of those judgments comes from being able to read structural health in code, distinguish abstraction that fits the domain from abstraction that doesn’t, and anticipate the long-term cost of change. These are the things that have always separated good developers from average ones.&lt;/p&gt;
&lt;p&gt;Fred Brooks, in 1986, separated software complexity into two types: accidental complexity, which comes from the limits of tools, and essential complexity, which is inherent to the problem itself. AI addresses accidental complexity - boilerplate, repeated patterns, syntax errors. But essential complexity - the ambiguity in business requirements, the balance between competing design goals, the uncertainty about what will need to change next year - doesn’t disappear no matter how good the AI gets. That complexity comes from the nature of the problem, not the limits of the tools.&lt;/p&gt;
&lt;p&gt;So even though AI is different from previous tools, as long as humans remain the accountable parties, the skills required for that judgment don’t change. If anything, automating production makes the judgment in quality control more visible, not less.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 567px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/cfed549021f0c0b30f757fa171543e0e/a7172/buffett.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 64.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAgADBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAeYyjCUf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAhEBAwAQEjL/2gAIAQEAAQUC5WGtCcs7FNnv/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAABARITH/2gAIAQEABj8CtwYv/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARIUExYf/aAAgBAQABPyE467sWTrE+ysYV5LIIWp//2gAMAwEAAgADAAAAEKQP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHRABAAICAgMAAAAAAAAAAAAAAQARIUExUaGx8P/aAAgBAQABPxDEcgNGGLqrkx1qJeFUEoYj7cYsU4WvVRSnYPif/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;buffett&quot; title=&quot;&quot; src=&quot;/static/cfed549021f0c0b30f757fa171543e0e/a7172/buffett.jpg&quot; srcset=&quot;/static/cfed549021f0c0b30f757fa171543e0e/0913d/buffett.jpg 160w,
/static/cfed549021f0c0b30f757fa171543e0e/cb69c/buffett.jpg 320w,
/static/cfed549021f0c0b30f757fa171543e0e/a7172/buffett.jpg 567w&quot; sizes=&quot;(max-width: 567px) 100vw, 567px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;A coach I work with compared this situation to Buffett&apos;s line:&lt;br&gt;
  &quot;Only when the tide goes out do you discover who&apos;s been swimming naked.&quot;&lt;br&gt;
  I can&apos;t think of a better analogy.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;This is why it feels slightly off when I see so many developers focused on getting better at using AI.&lt;/p&gt;
&lt;p&gt;A year ago, prompt engineering was the big topic. Now it’s skills, parallel agents, AI teams. Six months from now those keywords will probably be gone too.&lt;/p&gt;
&lt;p&gt;AI is going to reach a point where a kid typing casually gets good output. Optimizing for tool usage as a competitive advantage in that environment seems like the wrong bet. Focusing only on how to use the tool better might actually be how you fall behind.&lt;/p&gt;
&lt;p&gt;I could be wrong about how this unfolds. Nobody knows exactly how fast AI will develop or in what direction, and I’m not an exception. This post is just one developer thinking through the uncertainty.&lt;/p&gt;
&lt;p&gt;There’s no right answer. But the tide is going out faster. I hope you find yours before it does.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[AI가 코드를 쓰는 시대, 개발자의 진짜 역량이 드러난다]]></title><description><![CDATA[이번 포스팅에서는 AI 시대에 개발자의 역할이 어떻게 달라지고 있는지, 그리고 무엇을 준비해야 하는지 이야기해보려 한다. 최근 필자가 재직 중인 직장에서도 많은 개발자들이 이 주제에 대해 고민을 하고 있는데, 비단 이 주제는 필자 같은 개발자뿐 아니라 다양한 직군이 함께 고민하는 문제일 것이다.]]></description><link>https://evan-moon.github.io/2026/02/10/developer-in-ai-era/</link><guid isPermaLink="false">20260210-developer-in-ai-era</guid><pubDate>Tue, 10 Feb 2026 09:00:00 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 AI 시대에 개발자의 역할이 어떻게 달라지고 있는지, 그리고 무엇을 준비해야 하는지 이야기해보려 한다. 최근 필자가 재직 중인 직장에서도 많은 개발자들이 이 주제에 대해 고민을 하고 있는데, 비단 이 주제는 필자 같은 개발자뿐 아니라 다양한 직군이 함께 고민하는 문제일 것이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;공통적으로는 AI로 인한 생산성 향상에 대한 기대와 함께, 대체 가능성에 대한 불안도 동시에 느끼는 것 같다.&lt;/p&gt;
&lt;p&gt;물론 AI로 인해 앞으로의 먼 미래가 어떻게 달라질 것인지에 대해서는 아무도 알지 못할테고, 필자 또한 마찬가지이다. 그래도 아무것도 안할 수는 없으니 필자가 그리는 미래의 개발자의 역할과 모습에 대해서 한번 가볍게 이야기해보려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;chatgpt-이후-3년&quot; style=&quot;position:relative;&quot;&gt;ChatGPT 이후 3년&lt;a href=&quot;#chatgpt-%EC%9D%B4%ED%9B%84-3%EB%85%84&quot; aria-label=&quot;chatgpt 이후 3년 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;처음 ChatGPT가 등장한 2022년 말, 사실 필자는 AI가 이렇게 빠르게 발전할 것이라고는 상상하지 못 했다. 당시에는 할루시네이션 이슈도 많았고 무엇보다 출력의 퀄리티 자체가 그리 좋지 않았기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 이제 겨우 3년 정도가 지났음에도 불구하고 우리 개발자의 하루는 상당히 많은 부분이 변화했다.&lt;/p&gt;
&lt;p&gt;지금까지의 개발자라는 직업의 정의는 “프로그래밍이라는 행위를 통해 세상의 문제를 해결하는 사람” 정도였던 것 같다. 자연어로 된 요구사항을 분석하고, 설계에 대해 고민하고, 직접 키보드를 타이핑해 구현체를 만들어내는 일련의 과정을 직접 수행했다.&lt;/p&gt;
&lt;p&gt;그래서 불과 몇 년 전까지만 해도 아침에 출근하면 에디터를 열고 빈 파일에 커서를 놓는 것으로 하루를 시작했지만, 최근에는 직접 코딩을 하기보다는 AI에게 맥락을 전달하고, 생성된 코드를 읽고, 고치고, 다시 요청하는 것이 하루의 많은 부분을 차지한다.&lt;/p&gt;
&lt;p&gt;ChatGPT가 처음 등장한 지 3년 남짓한 시간 동안 변화가 워낙 빨랐기에, 나름 휴대폰과 스마트폰의 등장을 모두 겪어본 아재인 필자도 이렇게 빨리 세상이 바뀔 줄은 상상하지 못했다.&lt;/p&gt;
&lt;p&gt;이미 AI 코딩 에이전트의 성능은 단순 보조 수준을 넘어선지 오래다. 프롬프트만 잘 제공하면 함수 하나, 모듈 하나 정도는 사람이 작성한 것과 쉽게 구별하기 어려운 코드를 내놓는다. 이런 환경에서 개발자가 모든 코드를 직접 한 줄씩 작성하는 방식은, 최소한 일부 업무에서는 점점 비효율이 되어가고 있다.&lt;/p&gt;
&lt;p&gt;앞으로 변화 속도는 더 빨라질 가능성이 높다. 그리고 이 과정에서 개발자의 역할도 팀과 조직의 맥락에 따라 다르게 재편될 것이다. 그렇다면 지금 우리는 어떤 방향으로 미래를 준비해야 할까?&lt;/p&gt;
&lt;h2 id=&quot;작성자에서-의사결정권자로&quot; style=&quot;position:relative;&quot;&gt;작성자에서 의사결정권자로&lt;a href=&quot;#%EC%9E%91%EC%84%B1%EC%9E%90%EC%97%90%EC%84%9C-%EC%9D%98%EC%82%AC%EA%B2%B0%EC%A0%95%EA%B6%8C%EC%9E%90%EB%A1%9C&quot; aria-label=&quot;작성자에서 의사결정권자로 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이 질문에 답하려면 먼저 개발 과정에서 우리가 사용하는 시간이 어디에 주로 투자되고 있는지부터 봐야 한다. 예전에는 구현을 위해 직접 타이핑하는 시간이 길었다면 지금은 AI에게 프롬프트로 맥락을 전달하고, 생성된 코드를 읽고 고치고 다시 요청하는 시간이 빠르게 늘어나고 있다.&lt;/p&gt;
&lt;p&gt;즉, 코드를 통해 제품을 생산하는 행위는 직접적인 코드 작성에서 점점 “코드에 대한 판단”으로 이동하고 있다. 여기서 판단이란 단순히 AI 출력이 의도대로 됐는지 확인하는 것이 아니라 비즈니스 의도가 기술적 구현으로 올바르게 번역됐는지 검증하는 과정을 의미한다.&lt;/p&gt;
&lt;p&gt;물론 AI가 계속 발전하면 코드 리뷰조차 인간이 할 필요가 없어질 수 있다고 생각할 수 있겠지만, 필자 생각은 다르다. 그 이유는 기술적 가능성이 아닌 훨씬 더 근본적인 곳에 있다.&lt;/p&gt;
&lt;h3 id=&quot;코드에-대한-책임을-질-사람이-필요하다&quot; style=&quot;position:relative;&quot;&gt;코드에 대한 책임을 질 사람이 필요하다&lt;a href=&quot;#%EC%BD%94%EB%93%9C%EC%97%90-%EB%8C%80%ED%95%9C-%EC%B1%85%EC%9E%84%EC%9D%84-%EC%A7%88-%EC%82%AC%EB%9E%8C%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%98%EB%8B%A4&quot; aria-label=&quot;코드에 대한 책임을 질 사람이 필요하다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;최근 많은 개발자들이 코드 리뷰에도 AI를 활용하고 있다. 보통 Pull Request에 AI가 코드를 읽어보고 코멘트를 남겨주는 방식으로 작동하는데, 의외로 예리한 부분을 지적하는 경우도 있어서 필자도 가끔 놀란다.&lt;/p&gt;
&lt;p&gt;하지만 필자는 기술이 얼마나 발전하든 결국 최종적인 “문제 없음”이라는 승인 도장을 찍는 인간의 역할은 여전히 존재할 것이라 생각한다.&lt;/p&gt;
&lt;p&gt;그 이유는 바로 이 질문 때문이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;과연 코드로 인해 문제가 발생했을 때 누가 책임을 지는가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AI는 법적으로 인격체가 아니기 때문에 책임을 질 수 없다. 그렇다면 AI가 생성한 코드로 인해 문제가 발생했다면 과연 누가 책임을 져야하는 것인지에 대한 질문을 던져볼 필요가 있다.&lt;/p&gt;
&lt;p&gt;만약 AI가 작성한 코드로 인해 결제 로직에 버그가 생겨 고객에게 잘못된 금액이 청구됐을 때 서비스 운영자가 이렇게 답변하면 어떻게 될까?&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 268px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6d88ccc76e457cfbd94e60f058a4d6cf/6b6e1/dontknow.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 70%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIBBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe7lSWD/xAAXEAADAQAAAAAAAAAAAAAAAAAAAREg/9oACAEBAAEFAqLP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGhAAAQUBAAAAAAAAAAAAAAAAAQAQESFBYf/aAAgBAQABPyGmIyTbYEBE8b//2gAMAwEAAgADAAAAEAMP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGhAAAwEBAQEAAAAAAAAAAAAAAREhADEQUf/aAAgBAQABPxAoAYzdYSrUPjh9wgIEuO4Ub//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;dontknow&quot; title=&quot;&quot; src=&quot;/static/6d88ccc76e457cfbd94e60f058a4d6cf/6b6e1/dontknow.jpg&quot; srcset=&quot;/static/6d88ccc76e457cfbd94e60f058a4d6cf/0913d/dontknow.jpg 160w,
/static/6d88ccc76e457cfbd94e60f058a4d6cf/6b6e1/dontknow.jpg 268w&quot; sizes=&quot;(max-width: 268px) 100vw, 268px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;AI가 작성한거라 전 왜 이렇게 됐는지 모르겠는디요&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이딴 답변을 고객이 받아줄리가 없다. 입장바꿔서 생각해보면 아주 복장터지는 일이다.&lt;/p&gt;
&lt;p&gt;아무리 AI가 작성한 코드라고 해도 결국 누군가는 “책임”을 져야한다. 그리고 필자가 생각하기에 그 책임을 져야하는 사람은 바로 그 코드를 리뷰하고 승인한 개발자, 그리고 그 개발자가 속한 조직이다.&lt;/p&gt;
&lt;p&gt;이러한 방향성은 필자의 뇌피셜이 아니라 이미 여러 규제로 나타나고 있다.&lt;/p&gt;
&lt;p&gt;2024년 발효된 EU AI Act는 의료, 금융, 인프라 같은 고위험 영역에서 AI 시스템에 인간 감독을 의무화했다. 시행 자체는 단계적으로 진행 중이지만 방향성 자체는 분명하다. AI가 판단을 내리더라도 이 과정을 인간이 리뷰 가능하도록 만들어야 한다는 원칙을 법으로 못 박은 것이다.&lt;/p&gt;
&lt;p&gt;또한 EU 쪽에서는 제품책임 체계를 디지털 제품/소프트웨어까지 포괄하려는 논의도 이어지고 있다. “AI가 만들었으니 우리 책임이 아니다”는 주장이 법적으로 점점 통하기 어려워지는 방향으로 가고 있는 것이다.&lt;/p&gt;
&lt;p&gt;규제 뿐 아니라 다른 분야에서 나타난 실제 사례들도 보여지고 있다. 자율주행차는 사고가 나면 책임이 제조사와 운전자에게 돌아간다. FDA 승인을 받은 의료 AI 진단 도구도 최종 판단은 의사가 내려야 한다. 2010년 미국 주식시장에서 알고리즘 트레이딩이 연쇄 폭락을 일으킨 Flash Crash 사건에서도 알고리즘을 포함한 자동화 시스템을 운영하는 주체가 규제/집행의 대상이 된다는 걸 보여준다.&lt;/p&gt;
&lt;p&gt;자동화가 고도화될수록 책임 구조는 희미해지는 게 아니라 오히려 더 선명하게 인간 쪽으로 귀속되는 경향이 존재하는 것이다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 앞으로 개발자의 역할이 사라지기보다는 코드를 작성하는 사람에서 “코드를 리뷰하고 승인 도장을 찍는 사람”으로 변화하게 될 것이라 생각한다.&lt;/p&gt;
&lt;p&gt;결국 개발자의 역할이 사라지는 것이 아니라 무게 중심이 이동하는 것에 가깝다. 코드를 생산하는 방법이 달라졌을 뿐, 최종 코드의 품질이 그것을 리뷰하는 개발자의 역량에 달려 있다는 사실은 변하지 않는다. 그렇다면 이 새로운 구조에서 개발자에게 구체적으로 어떤 역량이 필요해지는 걸까?&lt;/p&gt;
&lt;h2 id=&quot;ai-시대에-개발자에게-요구되는-역량&quot; style=&quot;position:relative;&quot;&gt;AI 시대에 개발자에게 요구되는 역량&lt;a href=&quot;#ai-%EC%8B%9C%EB%8C%80%EC%97%90-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%97%90%EA%B2%8C-%EC%9A%94%EA%B5%AC%EB%90%98%EB%8A%94-%EC%97%AD%EB%9F%89&quot; aria-label=&quot;ai 시대에 개발자에게 요구되는 역량 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;아무래도 AI 시대이니 프롬프트를 잘 다루거나 AI 도구에 능숙한 것이 핵심 역량이 될 것 같지만, 필자 생각은 조금 다르다.&lt;/p&gt;
&lt;p&gt;뭐 요즘에는 “유명한 개발자 누구처럼 짜줘”라고 하면 알아서 해준다고는 하는데, 반대로 생각해보면 그 프롬프트를 작성할 수 있는 누구나 그렇게 짤 수 있다는 말이다. 거기에 어떤 경쟁력이 있는 것일까.&lt;/p&gt;
&lt;p&gt;중요한 것은 그런 프롬프트를 작성하는 것이 아니라, 혹여나 그런 프롬프트를 넣었음에도 불구하고 퀄리티 기준을 충족하지 않는 코드가 출력됐을 경우 문제를 감지할 수 있는 능력이다. 그 프롬프트 넣는다고 무조건 결과물의 퀄리티가 좋은 것은 아닐테니 말이다.&lt;/p&gt;
&lt;p&gt;아이러니하게도, 필자는 AI 시대에 개발자에게 요구되는 역량 또한 지금 좋은 개발자에게 요구되는 역량과 크게 다르지 않을 것이라 생각한다.&lt;/p&gt;
&lt;p&gt;왜냐하면 리뷰 과정 속에서 인간은 이 코드가 런타임에서 큰 문제가 없을지, 장기적인 변화에 대비할 수 있는 코드인지, 빠진 예외처리는 없을지, 정책에 위반되는 코드는 없는지와 같은 고맥락의 체크 리스트를 확인해야하기 때문이다. 그리고 결정적으로 코드에 대해서 최종적으로 승인 도장을 찍는 사람이 존재한다는 것은 여전히 “인간이 이해하기 쉬운 코드”를 작성해야한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;만약 인간이 코드를 읽을 필요가 없다면 모든 코드는 기계어로 작성해도 된다. 하지만 만약 이 코드에서 문제가 생기면 여러분이 책임을 져야하는데, 아무리 시대가 발전한다고 해도 그 코드를 읽지도 않고 라이브에 배포할 수 있겠는가?&lt;/p&gt;
&lt;p&gt;이 벽을 넘지 못하는 이상, 결국 인간이 코드를 읽고 이해해야하는 상황은 여전히 발생하기 때문에 인간이 이해하기 쉬운 코드란 무엇일지, 어떻게 하면 그런 코드를 작성할 수 있을지와 같은 지금 시대에 개발자들이 고민하고 있는 내용은 AI 시대에도 반복될 가능성이 높다.&lt;/p&gt;
&lt;h3 id=&quot;장기-변경-비용을-예측하는-역량&quot; style=&quot;position:relative;&quot;&gt;장기 변경 비용을 예측하는 역량&lt;a href=&quot;#%EC%9E%A5%EA%B8%B0-%EB%B3%80%EA%B2%BD-%EB%B9%84%EC%9A%A9%EC%9D%84-%EC%98%88%EC%B8%A1%ED%95%98%EB%8A%94-%EC%97%AD%EB%9F%89&quot; aria-label=&quot;장기 변경 비용을 예측하는 역량 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;최근 링크드인에 올라오는 게시물을 보면, 처음에는 “AI로 이런 거 만들었어요”라는 포스팅만 올라오더니, 요즘에는 간간히 “유지보수가 어려워서 개발자를 고용했습니다”, “기능을 도저히 못 붙히겠어서 접었습니다”와 같은 슬픈 엔딩도 보인다.&lt;/p&gt;
&lt;p&gt;이런 일이 발생하는 이유는 AI가 “작동하는 코드”를 만드는데 최적화되어있기 때문이다. 결국 학습 데이터에서 가장 빈번하게 등장하는 패턴을 재현하는 것이 AI의 동작 방식인데, 그 패턴들은 당연히 정상적으로 실행되는 코드들이다. 하지만 지금 당장 작동하는 코드와 6개월 뒤에도 유지보수가 쉬운 코드는 전혀 다른 기준이다.&lt;/p&gt;
&lt;p&gt;물론 최근 모델은 유지보수성까지 고려한 답을 제시하는 경우도 늘고 있다. 하지만 필자가 말하고자 하는 핵심은 단일 산출물의 품질과 장기 변경 비용 예측이 다른 문제라는 점이다.&lt;/p&gt;
&lt;p&gt;소프트웨어의 품질이라는 건 원래 즉시 드러나지 않는 성질의 것이다. 나쁜 설계의 비용은 코드를 작성한 시점이 아니라, 그 코드를 변경해야 하는 시점에 발생하기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;코드를-다각도로-평가하는-역량&quot; style=&quot;position:relative;&quot;&gt;코드를 다각도로 평가하는 역량&lt;a href=&quot;#%EC%BD%94%EB%93%9C%EB%A5%BC-%EB%8B%A4%EA%B0%81%EB%8F%84%EB%A1%9C-%ED%8F%89%EA%B0%80%ED%95%98%EB%8A%94-%EC%97%AD%EB%9F%89&quot; aria-label=&quot;코드를 다각도로 평가하는 역량 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;나쁜 설계의 비용이 작성 시점이 아닌 변경 시점에 드러난다는 건 AI 등장 이전에도 마찬가지였지만, 코드 생성 속도가 빨라지면서 이 “지연된 비용”이 쌓이는 속도도 함께 빨라졌다는 게 차이점이다.&lt;/p&gt;
&lt;p&gt;검수의 대상도 다양하다. 단순히 “이 코드가 맞느냐 틀리느냐”와 같은 기능적 정확성은 테스트로 어느 정도 검증할 수 있다. 더 까다로운 건 구조적 품질이다.&lt;/p&gt;
&lt;p&gt;과연 이 모듈의 책임 범위가 적절한가? 이 의존성 방향이 맞는가? 이 인터페이스가 변경에 유연한가? 이런 질문들은 자동화된 테스트로는 잡기 어렵다. 그 너머에는 성능적 함의도 있다. AI가 생성한 코드가 작동은 하지만, 데이터가 10배 늘었을 때도 괜찮을까? 그리고 보안적 측면도 있다. 입력 검증이 충분한가, 권한 확인이 빠져 있지는 않은가. 이 모든 차원을 동시에 고려하면서 코드를 평가하는 건, 단순히 “코드를 읽을 줄 아는 것”과는 다른 수준의 역량이다.&lt;/p&gt;
&lt;p&gt;그리고 AI의 생성 속도가 빨라질수록 이 문제는 더 심각해진다.&lt;/p&gt;
&lt;p&gt;사람이 직접 코드를 작성하던 시절, 코드 생산량에는 물리적 상한이 있었다. 한 개발자가 하루에 만들어낼 수 있는 코드의 양이 제한되어 있었기 때문에, 팀 전체가 검토해야 할 코드의 규모도 그 속도에 맞춰 조절됐다. 생산 속도와 리뷰 역량 사이에 어느 정도의 균형이 자연스럽게 유지됐던 것이다. 물론 느리게 작성한다고 코드가 더 좋아지는 건 아니지만 생산량이 리뷰 역량을 크게 앞지르기 어려운 구조이기는 했다.&lt;/p&gt;
&lt;p&gt;하지만 AI가 수 초 만에 수백 줄의 코드를 생성할 수 있는 환경에서는 코드 생산 속도와 리뷰 역량 사이의 균형이 쉽게 깨질 수 있다.&lt;/p&gt;
&lt;p&gt;특히 리뷰 기준, 병렬 리뷰 체계, 자동화 게이트가 충분하지 않다면 코드 양이 두세 배 늘어도 리뷰 인력과 시간은 그대로라 검증 누락이 생기기 쉽다. 그 결과 기술 부채가 더 빠르게 쌓일 가능성이 커진다. 공장의 생산 라인이 빨라졌는데 품질 검사 체계가 그대로인 상황인 것이다.&lt;/p&gt;
&lt;p&gt;필자는 아마 많은 회사들이 AI를 도입했음에도 생산성 증가를 못 느끼는 이유가 이것이 아닐까 생각한다. 코드 생산은 빨라졌을지 몰라도 AI가 뱉은 코드를 리뷰하는 과정이 제일 병목이다.&lt;/p&gt;
&lt;p&gt;이 구조에서 코드를 제대로 빠르게 검수할 수 있는 개발자의 가치는 자연스럽게 올라간다. AI가 쏟아내는 코드의 양이 많아질수록 그 코드에 섞인 잠재적 위험과 기술 부채를 선별할 수 있는 사람의 필요성이 커지기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;추상화-역량&quot; style=&quot;position:relative;&quot;&gt;추상화 역량&lt;a href=&quot;#%EC%B6%94%EC%83%81%ED%99%94-%EC%97%AD%EB%9F%89&quot; aria-label=&quot;추상화 역량 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자는 추상화 역량도 중요한 포인트 중 하나라고 생각한다. 결국 추상화란 복잡한 시스템에서 무엇을 감추고 무엇을 드러낼지, 그리고 어디에 경계를 그을지 결정하는 능력이다.&lt;/p&gt;
&lt;p&gt;AI가 추상화를 못하느냐고 물으면 솔직히 그건 아니다. AI도 인터페이스를 정의하고 클래스를 나누고 모듈을 분리할 수 있다. 사실 형식적인 측면에서는 필자보다 잘 하는 경우도 있다. 하지만 AI가 만드는 추상화와 숙련된 개발자가 만드는 추상화 사이에는 결정적인 차이가 하나 있다.&lt;/p&gt;
&lt;p&gt;AI의 추상화는 학습 데이터의 통계적 평균에 기반한다. 수많은 프로젝트에서 본 “그럴듯한 패턴”을 현재 상황에 적용하는 방식이다. 하지만 실제 소프트웨어 설계는 정답을 맞히는 게임이 아니라, 한정된 자원과 불확실한 미래 속에서 무엇을 포기할지 결정하는 트레이드오프의 영역이다.&lt;/p&gt;
&lt;p&gt;AI는 코드 내부의 정합성을 맞추는 데 능숙할지 몰라도 코드 외부의 맥락까지 고려하여 “어디에 경계를 그을지” 결정하는 것은 어려워한다. 특정 맥락에서 최적인 코드는 통계적 평균 너머의 전략적 판단이 개입될 때 비로소 완성되기 때문이다.&lt;/p&gt;
&lt;p&gt;이건 AI의 결함이라기보다는 통계적 학습이라는 방식 자체가 가진 구조적 한계에 가깝다. 평균적으로 좋은 코드를 만들 수는 있지만, 특정 맥락에서 최적인 코드를 만드는 건 다른 문제다.&lt;/p&gt;
&lt;p&gt;AI가 출력한 코드의 위험한 점은 겉보기에 좋아 보인다는 것이다. 코드 리뷰에서도 쉽게 통과할 수 있다. 파일이 적절히 나뉘어 있고, 네이밍도 관례를 따르고, 패턴도 익숙하기 때문이다. 문제는 실제로 변경이 필요한 시점에 발견된다. 결제 수단을 하나 추가하려고 하는데, “깔끔하게 나뉘어 있던” 구조의 여기저기를 동시에 수정해야 한다는 걸 그제야 깨닫게 되는 것이다. 이런 종류의 결함은 코드를 쓸 때가 아니라 코드를 고칠 때 드러난다.&lt;/p&gt;
&lt;p&gt;AI가 만든 코드에서 이런 패턴은 꽤 자주 발견된다. 통계적으로 가장 흔한 구조를 따랐기 때문에 표면적으로는 나무랄 데가 없지만, 실제 요구사항과 어긋나 있는 경우가 적지 않다.&lt;/p&gt;
&lt;p&gt;또 다른 예로, 프론트엔드에서 흔히 보이는 상황을 생각해보자. AI에게 대시보드 컴포넌트를 만들어달라고 하면, 보통은 하나의 거대한 컴포넌트 안에 데이터 페칭, 상태 관리, UI 렌더링을 모두 담은 구조를 내놓는다. 혹은 반대로 학습 데이터에서 본 모범 사례를 과하게 적용해서, 간단한 차트 하나를 그리기 위해 커스텀 훅 세 개와 컨텍스트 프로바이더를 만들어놓기도 한다.&lt;/p&gt;
&lt;p&gt;전자는 추상화가 부족한 것이고, 후자는 추상화가 과잉인 것이다. 둘 다 현재 프로젝트의 복잡도 수준에 맞지 않는다는 점에서는 같은 문제다. 적절한 추상화란 결국 현재 상황에서 딱 필요한 만큼의 구조를 만드는 것이고, 이 “만큼”을 판단하는 건 맥락을 아는 사람만 할 수 있다.&lt;/p&gt;
&lt;p&gt;숙련된 개발자는 이런 코드를 읽을 때 “여기서 이렇게 나눈 건 이 도메인의 특성을 모르고 한 거구나”라는 걸 알아채고 도메인에 맞는 경계를 다시 긋는다. 이 과정에서 동원되는 건 코딩 스킬이 아니라 시스템에 대한 이해와 설계에 대한 감각이다.&lt;/p&gt;
&lt;p&gt;즉, AI가 만든 코드를 평가할 때도 사람이 만든 코드를 평가할 때와 동일한 기준이 적용된다. “이 추상화가 실제로 복잡도를 줄이고 있는가, 아니면 추적해야 할 간접 경로만 늘리고 있는가?” 이 질문을 던질 수 있는 것 자체가 이미 하나의 역량이다.&lt;/p&gt;
&lt;h3 id=&quot;암묵지를-명시화할-수-있는-역량&quot; style=&quot;position:relative;&quot;&gt;암묵지를 명시화할 수 있는 역량&lt;a href=&quot;#%EC%95%94%EB%AC%B5%EC%A7%80%EB%A5%BC-%EB%AA%85%EC%8B%9C%ED%99%94%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%97%AD%EB%9F%89&quot; aria-label=&quot;암묵지를 명시화할 수 있는 역량 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;추상화 역량이 “어디에 경계를 그을지 아는 것”이라면, 암묵지를 명시화하는 역량은 “왜 거기에 경계를 그어야 하는지 설명할 수 있는 것”이다. 서로 다른 능력이지만 실제로는 함께 작동한다.&lt;/p&gt;
&lt;p&gt;좋은 코드와 나쁜 코드를 구분하는 감각은 코드를 많이 읽고 쓰면서 자연스럽게 체득하게된다. 보통 “뭔가 이상한데”라는 직감으로 시작되는 암묵지는 언어로 명확하게 설명하기가 꽤나 어렵다.&lt;/p&gt;
&lt;p&gt;그런데 이 암묵지를 언어로 만드는 능력이 AI 시대에 특히 중요해진다. “뭔가 이상한데”라는 직감을 “이 함수는 두 가지 책임을 가지고 있다”, “이 인터페이스가 변경에 취약하다”는 구체적인 언어로 바꿀 수 있어야 AI에게 올바른 명령을 내릴 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;다만 여기서 말하는 건 few-shot 예시나 chain-of-thought 같은 형식적인 프롬프트 기법이 아니다. 어차피 그런 것들은 모델이 발전하면서 자연스럽게 희석된다.&lt;/p&gt;
&lt;p&gt;필자가 이야기하고 싶은 건 그 아래에 있는 능력, 즉 무엇을 만들어야 하는지 명확하게 정의하고, 어떤 맥락이 중요한지 판단해서 전달하는 것이다.&lt;/p&gt;
&lt;p&gt;대충 “이걸 만들어줘”라고 말할 수 있는 사람은 많다. 하지만 개발자는 AI가 뱉은 코드의 문제점을 정확하게 파악하고 “이걸 이런 방식이 아니라 저런 방식으로 만들어야 하는 이유”를 설명할 수 있는 사람이 되어야한다.&lt;/p&gt;
&lt;p&gt;“뭔가 이상한 코드”를 보고 그 이유를 구체적으로 알고 말할 수 있는 것이 곧 개발자의 설계 역량이 될 것이다. 즉, 시스템과 코드에 대한 이해가 깊을수록, AI에게 더 구체적이고 더 정확한 지시를 내릴 수 있다.&lt;/p&gt;
&lt;p&gt;메모리를 직접 다루지 않아도 메모리 모델을 이해해야 성능 문제를 해결할 수 있듯이, 코드를 직접 작성하지 않아도 추상화를 이해해야 설계 문제를 잡아낼 수 있다. 추상화의 계층이 하나 더 생겼을 뿐, 추상화를 다루는 능력의 필요성 자체는 사라지지 않았다.&lt;/p&gt;
&lt;p&gt;이 역량들의 유효기간은 도구 숙련도보다 훨씬 길다. 도구 숙련도의 수명은 도구의 교체 주기에 묶여 있다. jQuery가 React에 밀리는 데 몇 년이 걸렸고, Webpack이 Vite에 밀리는 데 또 몇 년이 걸렸다. 반면 설계 판단과 암묵지 언어화 역량의 수명은 소프트웨어의 본질적 복잡성이 존재하는 한 유효하다.&lt;/p&gt;
&lt;p&gt;이 복잡성은 도구가 바뀌어도 사라지지 않는다. 결제 시스템이 복잡한 이유는 프레임워크 때문이 아니라 결제 도메인 자체가 복잡하기 때문이고, 그 복잡성을 다루는 감각은 특정 도구에 종속되지 않는다.&lt;/p&gt;
&lt;h2 id=&quot;의도적-수련-설계의-필요성&quot; style=&quot;position:relative;&quot;&gt;의도적 수련 설계의 필요성&lt;a href=&quot;#%EC%9D%98%EB%8F%84%EC%A0%81-%EC%88%98%EB%A0%A8-%EC%84%A4%EA%B3%84%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1&quot; aria-label=&quot;의도적 수련 설계의 필요성 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;여기까지 읽으면 자연스럽게 떠오르는 질문이 하나 있다. 코드를 직접 작성하는 시간이 줄어드는데, 도대체 추상화나 설계 감각은 어떻게 기르라는 걸까?&lt;/p&gt;
&lt;p&gt;이건 “도구가 할 수 없는 것에 집중하라”고 말하면서 정작 그것을 기를 기회가 줄어드는 모순적인 상황이다.&lt;/p&gt;
&lt;p&gt;해법은 두 층으로 나뉜다. 하나는 업무 흐름 안에서 AI에게 넘기지 말아야 할 두 지점을 지키는 것이고, 다른 하나는 그 판단력의 바탕이 되는 설계 감각을 업무 밖에서 의도적으로 유지하는 것이다. 그리고 이 두 가지를 관통하는 태도가 하나 있다.&lt;/p&gt;
&lt;h3 id=&quot;ai에게-넘기지-말아야-할-두-지점-설계와-리뷰&quot; style=&quot;position:relative;&quot;&gt;AI에게 넘기지 말아야 할 두 지점: 설계와 리뷰&lt;a href=&quot;#ai%EC%97%90%EA%B2%8C-%EB%84%98%EA%B8%B0%EC%A7%80-%EB%A7%90%EC%95%84%EC%95%BC-%ED%95%A0-%EB%91%90-%EC%A7%80%EC%A0%90-%EC%84%A4%EA%B3%84%EC%99%80-%EB%A6%AC%EB%B7%B0&quot; aria-label=&quot;ai에게 넘기지 말아야 할 두 지점 설계와 리뷰 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;평소 업무 흐름 안에서 AI에게 넘기지 말아야 할 지점이 두 군데 있다. 바로 코드 작성 앞단의 설계와 뒷단의 리뷰다.&lt;/p&gt;
&lt;p&gt;설계를 직접 하는 것은 단순한 습관의 문제가 아니다. 프롬프트를 치기 전에 “이 모듈이 외부에 노출할 인터페이스는 무엇인가”, “책임의 경계는 어디에 그을 것인가”를 먼저 정의하는 과정을 거치고 구현을 AI에게 위임하면, AI가 만들어낸 결과물을 자신의 설계 결정과 비교할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;AI가 다른 구조를 선택했다면 왜 그랬는지 분석하게 되고, 내가 놓친 것은 없는지, AI가 틀린 것은 아닌지 다시 생각하게 된다. 만약 이 과정이 부재한다면 단순히 AI가 출력한 코드를 소비하게 될 가능성이 높은데, 단순히 출력을 소비하는 것과 자신의 판단을 기준으로 출력을 평가하는 것은 완전히 다른 경험이다.&lt;/p&gt;
&lt;p&gt;또한 리뷰는 의도적으로 시간을 따로 내지 않아도 업무 흐름 안에서 자동으로 주어지는 역량 성장 기회다. 그렇기 때문에 이 기회를 그냥 흘려보내는 것이 가장 위험하다.&lt;/p&gt;
&lt;p&gt;AI에게 PR 리뷰를 맡기고 별다른 문제가 없으면 그냥 승인해버리는 습관은 마치 체육 시간에 운동장에 나가서 벤치에만 앉아 있다가 들어오는 것과 같다. 업무 자체는 어찌어찌 진행할 수 있겠지만, 그렇게 몇 년을 일을 해도 실력은 그대로일 가능성인 높다.&lt;/p&gt;
&lt;p&gt;코드 리뷰는 요구사항, 설계 의도, 비즈니스 맥락을 동시에 고려하면서 코드를 읽는 과정이고, 이 과정 자체가 설계 감각을 유지하는 훈련이라고 생각해야한다.&lt;/p&gt;
&lt;h3 id=&quot;의도적으로-직접-짜보는-시간&quot; style=&quot;position:relative;&quot;&gt;의도적으로 직접 짜보는 시간&lt;a href=&quot;#%EC%9D%98%EB%8F%84%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%A7%81%EC%A0%91-%EC%A7%9C%EB%B3%B4%EB%8A%94-%EC%8B%9C%EA%B0%84&quot; aria-label=&quot;의도적으로 직접 짜보는 시간 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;업무 안에서 설계와 리뷰를 직접 한다고 해서 충분한 건 아니다. 설계 감각 자체가 구현의 고통을 알아야 생기기 때문이다. 어떤 구조가 변경에 취약한지를 직접 손으로 겪어봐야 “이 추상화가 잘못됐다”는 직감이 생긴다. 겪어보지 못한 고통은 감각으로 남지 않는다.&lt;/p&gt;
&lt;p&gt;주니어 개발자의 경우 특히 그렇다. 경험이 적은 상태에서 AI가 생성한 코드를 리뷰하는 건, 아직 운전을 배우는 중인 사람에게 자율주행차의 판단을 평가하라고 하는 것과 비슷한 면이 있다. 직접 핸들을 잡아봐야 도로 위의 감각이 생기는 것처럼 직접 코드를 짜봐야 구조에 대한 감각이 생긴다.&lt;/p&gt;
&lt;p&gt;미래의 개발자에게 코딩하는 역량은 매일 하는 업무가 아니라 판단력을 유지하기 위한 훈련이 될 가능성이 높다고 본다. &lt;small&gt;(아마 주니어 시절의 고통스러운 직접 구현 경험은 선택이 아니라 리뷰어로서 면허를 따는 과정 정도가 되지는 않을까.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그래서 사이드 프로젝트나 개인 학습에서는 의도적으로 AI를 내려놓고 처음부터 끝까지 직접 구현해보는 시간을 만드는 게 좋다.&lt;/p&gt;
&lt;p&gt;AI가 편리할수록 그 마찰이 귀찮게 느껴지지만 그 마찰과 고통을 겪어야 빠른 실력 향상이 생길 것이라고 생각한다. 그리고 구현이 막히는 지점이나 리팩토링을 해야 하는 순간이 깨달음을 얻을 수 있는 순간이다.&lt;/p&gt;
&lt;h3 id=&quot;두-가지를-관통하는-태도-왜를-언어화하는-연습&quot; style=&quot;position:relative;&quot;&gt;두 가지를 관통하는 태도: “왜”를 언어화하는 연습&lt;a href=&quot;#%EB%91%90-%EA%B0%80%EC%A7%80%EB%A5%BC-%EA%B4%80%ED%86%B5%ED%95%98%EB%8A%94-%ED%83%9C%EB%8F%84-%EC%99%9C%EB%A5%BC-%EC%96%B8%EC%96%B4%ED%99%94%ED%95%98%EB%8A%94-%EC%97%B0%EC%8A%B5&quot; aria-label=&quot;두 가지를 관통하는 태도 왜를 언어화하는 연습 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;업무에서 설계와 리뷰를 직접 하든, 따로 시간을 내서 직접 짜든 이 두 가지 모두에서 작동해야 하는 태도가 있다. 바로 “뭔가 이상한데”라는 직감이 드는 순간 그 감각을 그냥 넘기지 않고 왜 그렇게 느꼈는지 명확한 말로 표현할 수 있을 때까지 다듬는 것이다.&lt;/p&gt;
&lt;p&gt;“이상한데”에서 멈추면 그냥 직감에서 끝나버리지만, “이 함수가 두 가지 책임을 가지고 있다”까지 가면 언어가 된다. 직감은 나만 아는 것이고 언어는 쓸 수 있는 것이다. 언어가 되어야 AI에게 정확한 지시를 내릴 수 있고, 팀원에게 설명할 수 있고, 다음에 비슷한 패턴을 만났을 때 알아챌 수 있다.&lt;/p&gt;
&lt;p&gt;AI가 만들어낸 코드가 작동한다고 해서 거기서 멈추지 않고, “왜 이 구조를 선택했을까”, “다른 구조였다면 어떤 트레이드오프가 있었을까”를 스스로에게 물어보는 것. 이 습관이 있는 개발자와 없는 개발자 사이의 격차는 시간이 갈수록 벌어질 것이다.&lt;/p&gt;
&lt;h2 id=&quot;결국-본질은-변하지-않았다&quot; style=&quot;position:relative;&quot;&gt;결국 본질은 변하지 않았다&lt;a href=&quot;#%EA%B2%B0%EA%B5%AD-%EB%B3%B8%EC%A7%88%EC%9D%80-%EB%B3%80%ED%95%98%EC%A7%80-%EC%95%8A%EC%95%98%EB%8B%A4&quot; aria-label=&quot;결국 본질은 변하지 않았다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AI의 등장으로 개발자의 역할이 코드 작성자에서 리뷰어로 이동하고 있다. 생산과 검수를 모두 인간이 하던 시대에서 생산은 AI가 하고 검수는 인간이 담당하는 시대로 변화하고 있는 것이다.&lt;/p&gt;
&lt;p&gt;그리고 이러한 변화가 기술적 한계가 아닌 책임 소재라는 사회적 문제에서 비롯된다는 걸 이해하면 역할 전환의 의미가 더 명확해진다.&lt;/p&gt;
&lt;p&gt;결국 필자는 리뷰 승인이라는 도장을 잘 찍으려면 작동하는 코드와 오래 살아남는 코드를 구분하는 눈, 맥락에 맞는 추상화를 판단하는 설계 감각, 그 감각을 언어로 만들어 정확한 방향을 잡는 역량이 필요해질 것이라 생각한다.&lt;/p&gt;
&lt;p&gt;즉, AI 시대의 차이는 생산량이 아니라 누가 맥락을 이해하고 책임 있게 승인하느냐에서 난다. 시대는 변화했지만 결국 개발자라는 사람이 책임져야하는 영역이 코드의 퀄리티라는 사실은 변하지 않는 것이다.&lt;/p&gt;
&lt;p&gt;AI가 이전 도구들과 근본적으로 다른 것은 사실이다. 농기구나 기계와 달리 AI는 스스로 추론하고 생성한다. “AI도 그냥 또 하나의 도구야”라는 식의 주장이 설득력을 잃는 건 당연하다. 그렇다면 왜 요구되는 역량이 바뀌지 않는다고 할 수 있을까.&lt;/p&gt;
&lt;p&gt;논리는 책임에서 시작한다. 책임을 진다는 건 판단을 한다는 뜻이고, 판단의 질은 코드의 구조적 건강함을 알아보는 눈, 도메인에 맞는 추상화를 구분하는 감각, 장기 변경 비용을 예측하는 능력에서 온다. 이것들이 항상 좋은 개발자와 평범한 개발자를 갈랐던 것들이다.&lt;/p&gt;
&lt;p&gt;프레드 브룩스(Fred Brooks)는 1986년에 소프트웨어의 복잡성을 두 가지로 나눴다. 우발적 복잡성은 도구의 한계에서 오는 것이고, 본질적 복잡성은 문제 자체에 내재된 것이다. AI가 해결하는 건 우발적 복잡성이다. 보일러플레이트, 반복 패턴, 문법 오류 같은 것들. 하지만 비즈니스 요구사항의 모호함, 상충하는 설계 목표 사이의 균형, 미래 변경 방향에 대한 불확실성 같은 본질적 복잡성은 AI가 아무리 발전해도 사라지지 않는다. 이 복잡성은 도구의 수준이 아니라 문제 자체의 성격에서 온다.&lt;/p&gt;
&lt;p&gt;그래서 AI의 성격이 이전 도구들과 달라도 인간이 판단과 책임의 주체로 남아 있는 한 그 판단에 필요한 역량의 본질은 바뀌지 않는다. 필자는 오히려 코드 생산이 자동화될수록 그 생산물을 검수하는 판단력의 비중이 오히려 부각될 것이라 생각한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 567px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/cfed549021f0c0b30f757fa171543e0e/a7172/buffett.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 64.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAgADBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAeYyjCUf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAhEBAwAQEjL/2gAIAQEAAQUC5WGtCcs7FNnv/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAABARITH/2gAIAQEABj8CtwYv/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARIUExYf/aAAgBAQABPyE467sWTrE+ysYV5LIIWp//2gAMAwEAAgADAAAAEKQP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHRABAAICAgMAAAAAAAAAAAAAAQARIUExUaGx8P/aAAgBAQABPxDEcgNGGLqrkx1qJeFUEoYj7cYsU4WvVRSnYPif/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;buffett&quot; title=&quot;&quot; src=&quot;/static/cfed549021f0c0b30f757fa171543e0e/a7172/buffett.jpg&quot; srcset=&quot;/static/cfed549021f0c0b30f757fa171543e0e/0913d/buffett.jpg 160w,
/static/cfed549021f0c0b30f757fa171543e0e/cb69c/buffett.jpg 320w,
/static/cfed549021f0c0b30f757fa171543e0e/a7172/buffett.jpg 567w&quot; sizes=&quot;(max-width: 567px) 100vw, 567px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;필자와 함께 일하는 코치 중 한 분은 이 상황을 빗대어&lt;br&gt;
  &quot;물이 빠지면 비로소 누가 발가벗고 수영을 하고 있었는지 알 수 있을 것&quot;이라고 했는데&lt;br&gt;
  아주 찰떡인 비유인 것 같다.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그래서 필자는 최근 많은 사람들이 AI라는 도구를 잘 깎는 것에 집중하는 것을 보면서 뭔가 조금 이상하다는 생각을 했었다.&lt;/p&gt;
&lt;p&gt;불과 1년 전만해도 프롬프트 엔지니어링이 굉장히 중요한 화두였지만 지금은 그 얘기는 쏙 들어가고 스킬, 병렬 에이전트, 팀과 같은 기능들에 대한 이야기가 오간다. 아마 6개월만 지나도 이 키워드들도 쏙 들어갈 것이다.&lt;/p&gt;
&lt;p&gt;어차피 AI는 길가는 초등학생이 프롬프트를 갈겨도 제대로된 출력을 낼 수 있는 수준까지 발전할텐데, 지금 도구를 잘 사용하는 방법에 집중하는 것이 정말 옳은 방향일까? 오히려 필자는 도구를 잘 깎는 것에만 집중하면 도태되기 쉬워지지는 않을까 하는 생각을 가지고 있다.&lt;/p&gt;
&lt;p&gt;물론 필자가 그리는 미래가 실제로 그렇게 펼쳐질지는 모른다. AI가 어느 방향으로 얼마나 빠르게 발전할지 정확히 아는 사람은 없고, 필자도 예외가 아니다. 이 글도 결국 불확실한 미래를 앞에 두고 한 명의 개발자가 지금 할 수 있는 생각을 정리해본 것일 뿐이다.&lt;/p&gt;
&lt;p&gt;정답은 없지만, 물이 빠지는 속도 만큼은 분명히 빨라지고 있다. 이 글을 읽는 독자 분들도 물이 빠졌을 때 발가벗고 수영을 하고 있는 사람이 되지 않도록 최선을 다해 각자만의 답을 찾아보기를 바란다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Beyond Functors, All the Way to Monads]]></title><description><![CDATA[In this post, I’ll continue from the concept of functors I covered previously and move on to explaining monads. When people hear “monad,” the first thing that usually comes to mind is the infamous explanation: “A monad is a monoid in the category of endofunctors, blah blah blah.” While this is technically the most accurate description of a monad, it’s also the most unhelpful one. There’s even a well-known meme called the “monad curse” — the idea that the moment you understand monads, you lose the ability to explain them. For those of us who aren’t deeply versed in mathematics, monads are indeed a notoriously elusive concept. With that in mind, I’m going to take my own ambitious crack at explaining monads. (Of course, I might fail…)]]></description><link>https://evan-moon.github.io/2026/02/07/monads-in-typescript/en/</link><guid isPermaLink="false">20260207-monads-in-typescript-en</guid><pubDate>Sat, 07 Feb 2026 21:25:09 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I’ll continue from the concept of functors I covered previously and move on to explaining monads.&lt;/p&gt;
&lt;p&gt;When people hear “monad,” the first thing that usually comes to mind is the infamous explanation: “A monad is a monoid in the category of endofunctors, blah blah blah.” While this is technically the most accurate description of a monad, it’s also the most unhelpful one.&lt;/p&gt;
&lt;p&gt;There’s even a well-known meme called the “monad curse” — the idea that the moment you understand monads, you lose the ability to explain them. For those of us who aren’t deeply versed in mathematics, monads are indeed a notoriously elusive concept.&lt;/p&gt;
&lt;p&gt;With that in mind, I’m going to take my own ambitious crack at explaining monads. &lt;small&gt;(Of course, I might fail…)&lt;/small&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;what-we-covered-in-the-previous-post&quot; style=&quot;position:relative;&quot;&gt;What We Covered in the Previous Post&lt;a href=&quot;#what-we-covered-in-the-previous-post&quot; aria-label=&quot;what we covered in the previous post permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since the previous post was written a full six years ago, let me briefly recap its content before moving on. For the full details, refer to the &lt;a href=&quot;/2020/01/27/safety-function-composition/&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Despite all the complexity and lengthy explanations, the core idea is simple. In the world of functional programming, to compose functions, the output type of the first function must match the input type of the next function.&lt;/p&gt;
&lt;p&gt;The problem is that the programming world is full of uncertainties and side effects — &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;, errors, and so on — making it difficult to follow this rule.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getStringLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Since getFirstLetter&apos;s codomain is string | undefined,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// it can&apos;t be directly composed with getStringLength&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;getStringLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To solve this problem, we introduced the concept of wrapping values and side effects in a container, and that container was the functor.&lt;/p&gt;
&lt;p&gt;A functor is a structure that can safely transform the value inside a container without extracting it, through an operation called &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;map: F&amp;lt;A&gt; → (A → B) → F&amp;lt;B&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This type signature means that if you pass a computation &lt;code class=&quot;language-text&quot;&gt;(A → B)&lt;/code&gt; that transforms the internal value to the &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; operation of a functor &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;A&gt;&lt;/code&gt;, the result is &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;B&gt;&lt;/code&gt; — the internal value has been transformed.&lt;/p&gt;
&lt;p&gt;Here, even though the internal value of &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;A&gt;&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;B&gt;&lt;/code&gt; may differ, the structure itself must not change, which is why a functor must satisfy the following two laws:&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;Identity law: &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F(\text{id}) = \text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Composition law: &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F(g \circ f) = F(g) \circ F(f)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;id&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is the identity function that returns its argument unchanged. The identity law says that applying &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; with this identity function should result in nothing happening.&lt;/p&gt;
&lt;p&gt;The composition law means that mapping a composed function should produce the same result as mapping each function separately and then composing.&lt;/p&gt;
&lt;p&gt;These laws exist because they guarantee that a functor is “a mapping that preserves structure.” It’s not mathematical obsession — there are real practical reasons.&lt;/p&gt;
&lt;p&gt;If the identity law holds, we can trust that &lt;code class=&quot;language-text&quot;&gt;a.map(x =&gt; x)&lt;/code&gt; truly does nothing. But if the internal structure — like the order of a list or the height of a tree — were altered in the process, that’s no longer mapping; it’s “reconstruction.” The identity law is what lets you trust that a functor only touches the contents, never the wrapper.&lt;/p&gt;
&lt;p&gt;And if the composition law holds, we’re guaranteed that &lt;code class=&quot;language-text&quot;&gt;a.map(f).map(g)&lt;/code&gt; produces the same result as &lt;code class=&quot;language-text&quot;&gt;a.map(x =&gt; g(f(x)))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This guarantees that &lt;code class=&quot;language-text&quot;&gt;a.map(f).map(g)&lt;/code&gt;, which loops twice, can be collapsed into &lt;code class=&quot;language-text&quot;&gt;a.map(x =&gt; g(f(x)))&lt;/code&gt; with a single loop and produce the same behavior. Conversely, it also means it’s safe to split complex logic into multiple &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; calls for readability.&lt;/p&gt;
&lt;p&gt;But even functors have their limits. It’s precisely these limitations that lead us to the monad we’ll explore today.&lt;/p&gt;
&lt;h2 id=&quot;the-limits-of-functors&quot; style=&quot;position:relative;&quot;&gt;The Limits of Functors&lt;a href=&quot;#the-limits-of-functors&quot; aria-label=&quot;the limits of functors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 1988, computer scientist Eugenio Moggi at the University of Edinburgh was wrestling with a thorny problem. While working on denotational semantics — the study of defining the meaning of programs mathematically — he was pondering how to bridge the gap between pure lambda calculus and real-world programs.&lt;/p&gt;
&lt;p&gt;In pure lambda calculus, the type &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; means “a total function that takes input A and returns B.” Mathematically clean, but real programs don’t work that way.&lt;/p&gt;
&lt;p&gt;Programs can fall into infinite loops, throw exceptions, modify state, or read files. Treating programs that produce these “effects” as pure functions &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; distorts their meaning.&lt;/p&gt;
&lt;p&gt;So Moggi’s starting point was to view programs not as &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; but as &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Here, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is a structure that captures the “notion of computation,” and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; means “a computation that produces a value of type B.” It represents not the value itself, but a computation that produces the value, as a type.&lt;/p&gt;
&lt;p&gt;This is easier to understand with concrete examples. Familiar computations include:&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;Maybe&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to \text{Maybe}(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Maybe&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: a computation that might fail&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;IO&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to \text{IO}(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;IO&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: a computation that interacts with the outside world&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;State&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to \text{State}(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;State&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: a computation that modifies state&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;But this approach introduced another problem: composing functions of the form &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; became tricky. If the first function is &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, then the second would be &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B \to T(C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, but the output of the first function, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, doesn’t match the input of the second, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Moggi discovered that a structure solving this composition problem had already been studied in category theory — and that’s how monads entered functional programming.&lt;/p&gt;
&lt;p&gt;The word “monad,” borrowed from mathematics, became one of the most feared words in computer science.&lt;/p&gt;
&lt;h4 id=&quot;why-cant-functors-solve-this&quot; style=&quot;position:relative;&quot;&gt;Why Can’t Functors Solve This?&lt;a href=&quot;#why-cant-functors-solve-this&quot; aria-label=&quot;why cant functors solve this permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;So why couldn’t Moggi’s problem be solved with functors alone? We encounter two critical bottlenecks that the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; cannot resolve.&lt;/p&gt;
&lt;p&gt;First, consider the case where a function gets trapped inside the computational context &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. A typical example that produces this situation is currying.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Can we use the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; to apply the &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; operation to &lt;code class=&quot;language-text&quot;&gt;maybeA&lt;/code&gt; and produce a function waiting for the next argument? The answer is no. Because the result of applying the operation through the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; isn’t just a plain function.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; addA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Substituting into map&apos;s type signature...&lt;/span&gt;
map&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  maybeNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Normally, with a curried function, &lt;code class=&quot;language-text&quot;&gt;addA&lt;/code&gt; should have the type &lt;code class=&quot;language-text&quot;&gt;(b: number) =&gt; number&lt;/code&gt;. But here, since we applied the operation through &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, the result is &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;(b: number) =&gt; number&gt;&lt;/code&gt;. The function is trapped inside the computational context.&lt;/p&gt;
&lt;p&gt;The problem is that once this happens, we can’t continue composing with the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, which only accepts bare functions. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; can apply a function from outside the context to a value inside the context, but it has no way to take a function trapped inside a context and apply it to a value inside another context.&lt;/p&gt;
&lt;p&gt;This is fundamentally because the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; only operates on the outermost function when given a curried function. When a function returns another function, &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; can’t reach the inner one.&lt;/p&gt;
&lt;p&gt;The other problem arises when composing two functions that each return a functor. Let’s look at another example using the &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; functor, which represents “a value that may or may not exist.”&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; findUser&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; findTeam&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These are functions of the form Moggi envisioned — taking an input &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and returning a computation &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;findUser&lt;/code&gt; takes a user ID and returns a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;. We use the &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; functor because if an invalid ID is provided, there may be no matching user. And &lt;code class=&quot;language-text&quot;&gt;findTeam&lt;/code&gt; takes a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; and returns their team. We want to compose these two functions to create a function that finds a user’s team.&lt;/p&gt;
&lt;p&gt;The problem is that &lt;code class=&quot;language-text&quot;&gt;findTeam&lt;/code&gt; can’t directly accept the &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;User&gt;&lt;/code&gt; returned by &lt;code class=&quot;language-text&quot;&gt;findUser&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But we can try composing them using the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;. Let’s give it a shot.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; findTeam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Substituting into map&apos;s type signature...&lt;/span&gt;
&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We managed to compose them, but the resulting type is &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;Team&gt;&gt;&lt;/code&gt; — a rather sad outcome. If we were to add one more step to find the team leader from the team information, the type would become &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;Maybe&amp;lt;Manager&gt;&gt;&gt;&lt;/code&gt;, nesting infinitely.&lt;/p&gt;
&lt;h4 id=&quot;lets-take-stock&quot; style=&quot;position:relative;&quot;&gt;Let’s Take Stock&lt;a href=&quot;#lets-take-stock&quot; aria-label=&quot;lets take stock permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Following Moggi’s problem, we’ve encountered two issues that functors can’t solve.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;What’s Needed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Applying a function inside a context&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; only accepts functions from outside&lt;/td&gt;
&lt;td&gt;An operation that applies an inner function to an inner value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context nesting&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; only peels one layer&lt;/td&gt;
&lt;td&gt;An operation that flattens double context into single context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;center&gt;
 &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4142324907ddfda791bb342ea64416ec/65f94/head.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 73.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGZmVRLsCg//8QAGhAAAgIDAAAAAAAAAAAAAAAAAQIAAxIhI//aAAgBAQABBQI2rK06FZtSLSsR81//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGn/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABsQAAICAwEAAAAAAAAAAAAAAAABESECECJR/9oACAEBAAY/AqYoc+6g5oWR/8QAGRAAAgMBAAAAAAAAAAAAAAAAASEAEUEx/9oACAEBAAE/Ib+mKBBSo19ggUZR5dHYRBdTvYnHs//aAAwDAQACAAMAAAAQp9//xAAXEQADAQAAAAAAAAAAAAAAAAAAASEx/9oACAEDAQE/EM0TP//EABYRAQEBAAAAAAAAAAAAAAAAAAABYf/aAAgBAgEBPxDKx//EABwQAQADAAIDAAAAAAAAAAAAAAEAESExQVGB0f/aAAgBAQABPxB1FVie0GUWWTs+zQoJdVcWYCVwSPO4Mk9IxgEUPCOz/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;head&quot; title=&quot;&quot; src=&quot;/static/4142324907ddfda791bb342ea64416ec/65f94/head.jpg&quot; srcset=&quot;/static/4142324907ddfda791bb342ea64416ec/0913d/head.jpg 160w,
/static/4142324907ddfda791bb342ea64416ec/cb69c/head.jpg 320w,
/static/4142324907ddfda791bb342ea64416ec/65f94/head.jpg 420w&quot; sizes=&quot;(max-width: 420px) 100vw, 420px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
 &lt;small&gt;I thought functors could solve everything, but that turned out to be far from true&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Problems are meant to be solved. Now we’re going to sketch out the design for these, step by step.&lt;/p&gt;
&lt;p&gt;The first problem — a function trapped inside a context — can be solved by an Applicative Functor. And the problem of contexts nesting every time we compose functions — that’s what the Monad solves.&lt;/p&gt;
&lt;h2 id=&quot;designing-the-solution-applicative-functors-and-monads&quot; style=&quot;position:relative;&quot;&gt;Designing the Solution: Applicative Functors and Monads&lt;a href=&quot;#designing-the-solution-applicative-functors-and-monads&quot; aria-label=&quot;designing the solution applicative functors and monads permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now we need to invent a new operation to solve the first problem. From here on, the phrase “computational context” is too long, so let’s simply call it a “container.”&lt;/p&gt;
&lt;p&gt;The first problem was a function being trapped inside a container, so we need an operation that can apply this function to a value inside another container.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Apply a function inside a container to a value inside another container
apply: T&amp;lt;(A → B)&gt; → T&amp;lt;A&gt; → T&amp;lt;B&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The only difference between this operation and the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; is whether the function being applied is outside or inside the container. We call this operation &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We also need an operation that puts a value back into a container after applying the function. This is called the &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; operation.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Put a pure value into a container
pure: A → T&amp;lt;A&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A functor equipped with both &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; is called an Applicative Functor. Let’s express these operations as TypeScript type signatures using the familiar &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; container as an example.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apply&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pure&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let’s use this applicative functor to compose the curried function from our earlier problem.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeAddA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;(b: number) =&gt; number&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maybeAddA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;number&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Substituting into apply&apos;s type signature...&lt;/span&gt;
&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  f&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the applicative functor’s &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; operation, the problem of working with multiple containers like &lt;code class=&quot;language-text&quot;&gt;maybeA&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;maybeB&lt;/code&gt; just… solves itself.&lt;/p&gt;
&lt;h3 id=&quot;the-limits-of-applicative-functors&quot; style=&quot;position:relative;&quot;&gt;The Limits of Applicative Functors&lt;a href=&quot;#the-limits-of-applicative-functors&quot; aria-label=&quot;the limits of applicative functors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;But the problem we solved comes with an important premise: which containers to compose must be known in advance.&lt;/p&gt;
&lt;p&gt;Think back to the applicative functor’s &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; operation. &lt;code class=&quot;language-text&quot;&gt;maybeA&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;maybeB&lt;/code&gt; are independent containers that are already in our hands before computation begins. In other words, the structure of the computation is fixed regardless of the values.&lt;/p&gt;
&lt;p&gt;But real-world programs are far more dynamic. More often than not, you need to look at the result of the previous computation before deciding which container to fetch next — or whether to fetch one at all.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Find a user, then find their team based on user information.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// The team-finding function produces different results depending on who the user is.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findTeam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;teamId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here’s where another problem arises. The &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; container returned by &lt;code class=&quot;language-text&quot;&gt;findTeam&lt;/code&gt; is created depending on the value &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt;. In other words, the result of the previous computation determines the context of the next.&lt;/p&gt;
&lt;p&gt;Applicative functors can only facilitate communication between containers that already exist, so they can’t express sequential dependencies that are dynamically created at runtime.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Static&lt;/th&gt;
&lt;th&gt;Dynamic&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Fetch A and B separately and combine them”&lt;/td&gt;
&lt;td&gt;“Fetch A, then decide whether to do B based on the result”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;To handle dynamically created sequential dependencies, you have to use the result of the previous computation to create the next one. And in that process, containers will inevitably nest.&lt;/p&gt;
&lt;center&gt;
 &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 282px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/298c3198f4c789d26495cbde7800fa25/822fd/oh.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 136.24999999999997%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAwADAAAAAAAAAAAAAAAAAAQFAQID/8QAFwEBAAMAAAAAAAAAAAAAAAAAAgADBf/aAAwDAQACEAMQAAABszaKIdUwMRJriVWjsciL/8QAGxABAQADAAMAAAAAAAAAAAAAAQIAAwQQETH/2gAIAQEAAQUC2qQe4vNtARQoidFrOF1OdP3x/8QAGBEAAgMAAAAAAAAAAAAAAAAAARADITL/2gAIAQMBAT8BApQ5X//EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAECAQE/AWP/xAAeEAABBAIDAQAAAAAAAAAAAAABAAIQESEiMVFhgf/aAAgBAQAGPwLHKBD3Hu4ytjqrBtH0xhxC+z//xAAeEAACAgICAwAAAAAAAAAAAAABEQAhEEExYVFxsf/aAAgBAQABPyE7dFTlt4QhUsIxrfqN4tohAPInOAqA6jKTqBEI6M+rP//aAAwDAQACAAMAAAAQvwTy/8QAGBEBAAMBAAAAAAAAAAAAAAAAAQARIRD/2gAIAQMBAT8QvtXCaiDqT//EABgRAAMBAQAAAAAAAAAAAAAAAAABIRAR/9oACAECAQE/EGsxs6f/xAAfEAEBAAICAQUAAAAAAAAAAAABEQAhMUGhEGFxkfH/2gAIAQEAAT8Qa6AEWV2/WS094knfpCgRqdDnAN7uxl6rhpR4SmLy00ah/POPNPZdY0cGxAuJSLxDzjxh385//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;oh&quot; title=&quot;&quot; src=&quot;/static/298c3198f4c789d26495cbde7800fa25/822fd/oh.jpg&quot; srcset=&quot;/static/298c3198f4c789d26495cbde7800fa25/0913d/oh.jpg 160w,
/static/298c3198f4c789d26495cbde7800fa25/822fd/oh.jpg 282w&quot; sizes=&quot;(max-width: 282px) 100vw, 282px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
 &lt;small&gt;Oh, what if we had an operation that flattens nested containers?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Applicative functors used a new operation called &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; to execute functions inside containers. But if we had a tool that flattens nesting, we wouldn’t need the cumbersome step of executing a function inside a new container — we could solve the problem without it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// If we have something that flattens nesting, we can solve it with just map!&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 1. Mapping a curried function produces a function inside a container&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybePartialFn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Result: Maybe&amp;lt;(b: number) =&gt; number&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 2. Use map to access the function inside the container and perform computation&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nested &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybePartialFn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fn &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Result: Maybe&amp;lt;Maybe&amp;lt;number&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 3. Then flatten the nesting?&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flattener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nested&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Result: Maybe&amp;lt;number&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just compose and let things nest, then flatten afterward.&lt;/p&gt;
&lt;h3 id=&quot;monads-inventing-the-flatten-operation&quot; style=&quot;position:relative;&quot;&gt;Monads: Inventing the Flatten Operation&lt;a href=&quot;#monads-inventing-the-flatten-operation&quot; aria-label=&quot;monads inventing the flatten operation permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;And that’s exactly what monads are for. A monad is something that has an operation for flattening nested containers.&lt;/p&gt;
&lt;p&gt;This flattening operation is called &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;flatten&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;join: T&amp;lt;T&amp;lt;A&gt;&gt; → T&amp;lt;A&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; join&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; operation turns &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;A&gt;&gt;&lt;/code&gt; into &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;A&gt;&lt;/code&gt;. Mathematically, it “reduces two applications of &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; down to one.”&lt;/p&gt;
&lt;p&gt;This kind of operation is actually easy to find in our daily work — JavaScript’s &lt;code class=&quot;language-text&quot;&gt;Array.prototype.flat&lt;/code&gt; does exactly this.&lt;/p&gt;
&lt;p&gt;And just like the applicative functor, we also need an operation that puts a pure value into a container. As with applicative functors, this is called &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;, or sometimes &lt;code class=&quot;language-text&quot;&gt;of&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pure: A → T&amp;lt;A&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pure&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But in practice, you rarely use &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; directly. As we saw in the earlier example, the monad works as a set: use &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; to access something inside the container and compose, then use &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; to flatten the nesting.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;1. You want to apply a function to the value inside a container = use map
2. But that function returns its result wrapped in a container = double wrapping occurs
3. You need to unwrap the double wrapping = use join&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So we want to combine these two operations into one for convenience.&lt;/p&gt;
&lt;h4 id=&quot;flatmap--map--join&quot; style=&quot;position:relative;&quot;&gt;flatMap = map + join&lt;a href=&quot;#flatmap--map--join&quot; aria-label=&quot;flatmap  map  join permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Since calling &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; followed by &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; every time is tedious, we combine these two steps into &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;. Let’s see what the type signature looks like for a &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; that takes our familiar &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; container.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;map:     T&amp;lt;A&gt; → (A → B)    → T&amp;lt;B&gt;     // Apply a regular function
flatMap: T&amp;lt;A&gt; → (A → T&amp;lt;B&gt;) → T&amp;lt;B&gt;     // Apply a container-returning function + flatten&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flatMap&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The difference between &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; is in the second argument. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; takes a simple &lt;code class=&quot;language-text&quot;&gt;A =&gt; B&lt;/code&gt; function, while &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; takes an &lt;code class=&quot;language-text&quot;&gt;(A =&gt; Maybe&amp;lt;B&gt;)&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Although it’s not visible in the type signature, &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; internally performs the role of &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; as well, so the result type isn’t the sad &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;B&gt;&gt;&lt;/code&gt; but simply &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;B&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now we can use &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; to express sequential dependencies between computations.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Using map results in a nested type&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findDepartment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deptId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;Maybe&amp;lt;Department&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Using flatMap solves it&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findDepartment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deptId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;Department&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So far, we’ve covered the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, the applicative functor’s &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, and the monad’s &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;. There was a lot of ground to cover, so let’s recap before moving on.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Functor&apos;s map&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Applicative Functor&apos;s apply&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apply&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Monad&apos;s flatMap&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flatMap&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; is the one that applies a regular function to a value inside a container. But this alone can’t handle functions trapped inside the container.&lt;/p&gt;
&lt;p&gt;So &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; appeared. &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; makes it possible to access functions inside a container, enabling composition even in these situations. But when performing dynamic computations with sequential dependencies, containers kept nesting.&lt;/p&gt;
&lt;p&gt;To solve this, &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; — which flattens nested structures — was combined with the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; to create &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;. Through this operation, we can now freely compose computations with sequential dependencies, where each result determines the next computation.&lt;/p&gt;
&lt;h2 id=&quot;laws-are-proofs-about-refactoring&quot; style=&quot;position:relative;&quot;&gt;Laws Are Proofs About Refactoring&lt;a href=&quot;#laws-are-proofs-about-refactoring&quot; aria-label=&quot;laws are proofs about refactoring permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So is &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; really the magic that lets us safely compose functions? Well, to claim this with confidence, &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; must satisfy a few laws.&lt;/p&gt;
&lt;h3 id=&quot;the-three-laws&quot; style=&quot;position:relative;&quot;&gt;The Three Laws&lt;a href=&quot;#the-three-laws&quot; aria-label=&quot;the three laws permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To use &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; freely, we need the guarantee that this operation upholds the following laws.&lt;/p&gt;
&lt;h4 id=&quot;associativity-it-shouldnt-matter-which-layer-you-flatten-first&quot; style=&quot;position:relative;&quot;&gt;Associativity: It Shouldn’t Matter Which Layer You Flatten First&lt;a href=&quot;#associativity-it-shouldnt-matter-which-layer-you-flatten-first&quot; aria-label=&quot;associativity it shouldnt matter which layer you flatten first permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;First is the associativity law. It means that when flattening nesting, the result should be the same regardless of which side you flatten first. Imagine a container wrapped in three layers, like &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;Maybe&amp;lt;A&gt;&gt;&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We need to flatten this container down to the &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; form.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(T(A))) \to T(T(A)) \to T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;There are two ways to flatten this to a single layer. The first is to merge the inner two &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;s first, then peel off the remaining outer &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to get &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. The second is to merge the outer two &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;s first, then peel off the remaining inner &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Regardless of which order you perform the operations, the final result &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; must be the same. That’s the associativity law.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\mu = \mu \circ \mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the formula above, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (mu) represents &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; means “merge the inner two layers,” and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; means “merge the outer two layers.” Think of it like a three-layered matryoshka doll being reduced to two layers — it shouldn’t matter whether you merge the inner dolls first or the outer dolls first.&lt;/p&gt;
&lt;h4 id=&quot;left-identity-dont-mess-with-the-entry-point&quot; style=&quot;position:relative;&quot;&gt;Left Identity: Don’t Mess with the Entry Point&lt;a href=&quot;#left-identity-dont-mess-with-the-entry-point&quot; aria-label=&quot;left identity dont mess with the entry point permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Second is the left identity law. This means that putting something in and immediately taking it out should be the same as doing nothing.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\eta = \text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token function&quot;&gt;pure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the formula above, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (eta) represents &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pay special attention to the &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in front of &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) — it means applying &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; not outside the container but to a value already inside one.&lt;/p&gt;
&lt;p&gt;In other words, given a container &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, if you wrap the inner value &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; to create a double structure &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and then flatten it back with &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;), you should arrive back at the original state (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;).&lt;/p&gt;
&lt;p&gt;This law must hold for us to trust &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; as the minimal unit of computation inside a container. If the left identity law were broken, it would mean &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; is doing more than simply wrapping a value — it would be transforming the internal logic.&lt;/p&gt;
&lt;h4 id=&quot;right-identity-if-you-only-changed-the-wrapping-the-contents-should-stay-the-same&quot; style=&quot;position:relative;&quot;&gt;Right Identity: If You Only Changed the Wrapping, the Contents Should Stay the Same&lt;a href=&quot;#right-identity-if-you-only-changed-the-wrapping-the-contents-should-stay-the-same&quot; aria-label=&quot;right identity if you only changed the wrapping the contents should stay the same permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Third is the right identity law. It’s similar to the left identity law, but the order of wrapping is reversed.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ \eta T = \text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; m&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; means treating the existing container &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; as a single value and wrapping its outside with &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) one more time. The result is &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, creating a double structure &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;What the right identity law says is straightforward. If you wrap the outside of a container with one more layer of &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) and then peel that outer layer back off with &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;), you should end up right back where you started (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;).&lt;/p&gt;
&lt;p&gt;As mentioned earlier, these identity laws are important because they guarantee that &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; is a neutral identity element that doesn’t distort the context.&lt;/p&gt;
&lt;p&gt;Just as adding &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to a number doesn’t change the value, wrapping a container with &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; and then flattening it should have no effect whatsoever on the original information or state of that container.&lt;/p&gt;
&lt;h2 id=&quot;back-to-a-monoid-in-the-category-of-endofunctors&quot; style=&quot;position:relative;&quot;&gt;Back to “A Monoid in the Category of Endofunctors”&lt;a href=&quot;#back-to-a-monoid-in-the-category-of-endofunctors&quot; aria-label=&quot;back to a monoid in the category of endofunctors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So how does all this relate to the Wikipedia definition of a monad as “a monoid in the category of endofunctors”?&lt;/p&gt;
&lt;p&gt;From here on, the discussion gets more abstract and mathematical, so readers who are satisfied with a practical-level understanding of monads can skip ahead.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9e58e5b0f155e0d74c064038ab30b02d/10fd8/hard.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 54.37499999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABAAF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAFmfoFNBm0//8QAGhAAAgMBAQAAAAAAAAAAAAAAAQIDESEAMv/aAAgBAQABBQLB3uUrIDevjBjX/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEREv/aAAgBAwEBPwFKmD//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEv/aAAgBAgEBPwFT/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAEQIRH/2gAIAQEABj8CHwxzJ//EABoQAQACAwEAAAAAAAAAAAAAAAEAETFBcSH/2gAIAQEAAT8hHaG455pvXkRCByWTbDfhyZhn/9oADAMBAAIAAwAAABCDD//EABcRAQADAAAAAAAAAAAAAAAAAAABESH/2gAIAQMBAT8Qiyu//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFyP/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFBUWGR/9oACAEBAAE/EChAOWeXcQBa1HEVv7LKs4tfsBiJ1xqF1PxF2se0Gf/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;hard&quot; title=&quot;&quot; src=&quot;/static/9e58e5b0f155e0d74c064038ab30b02d/c08c5/hard.jpg&quot; srcset=&quot;/static/9e58e5b0f155e0d74c064038ab30b02d/0913d/hard.jpg 160w,
/static/9e58e5b0f155e0d74c064038ab30b02d/cb69c/hard.jpg 320w,
/static/9e58e5b0f155e0d74c064038ab30b02d/c08c5/hard.jpg 640w,
/static/9e58e5b0f155e0d74c064038ab30b02d/10fd8/hard.jpg 942w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;But it&apos;s great exercise for the brain, so I still recommend reading through it&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Monads weren’t handed down from mathematicians with the instruction “use this.” Engineers needed a safe way to compose functions, so they invented these tools out of necessity.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Invention&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;A type constructor that takes a type and creates a new type&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;A&gt;&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;A&gt;&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (eta)&lt;/td&gt;
&lt;td&gt;An operation that puts a value into a container&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Promise.resolve&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (mu)&lt;/td&gt;
&lt;td&gt;An operation that flattens nested containers into a single container&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;flatten&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;And to use these operations safely, we said they must satisfy the three laws we examined (associativity, left identity, right identity). Now, analyzing this structure mathematically leads us to a very interesting destination.&lt;/p&gt;
&lt;h3 id=&quot;category-a-world-of-objects-and-arrows&quot; style=&quot;position:relative;&quot;&gt;Category: A World of Objects and Arrows&lt;a href=&quot;#category-a-world-of-objects-and-arrows&quot; aria-label=&quot;category a world of objects and arrows permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A category is a structure composed of objects and morphisms (arrows) between them. Personally, I find the word “category” more natural than the Korean translation, so I’ll stick with “category” going forward.&lt;/p&gt;
&lt;p&gt;From a TypeScript perspective, the most familiar category is the category of types. In this category, the objects are types like &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;, and the morphisms are functions like &lt;code class=&quot;language-text&quot;&gt;(a: number) =&gt; string&lt;/code&gt; — computations that go from one object to another.&lt;/p&gt;
&lt;p&gt;For a detailed treatment of categories and functors, see the &lt;a href=&quot;/2020/01/27/safety-function-composition/&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;endofunctor-a-functor-that-stays-within-the-same-world&quot; style=&quot;position:relative;&quot;&gt;Endofunctor: A Functor That Stays Within the Same World&lt;a href=&quot;#endofunctor-a-functor-that-stays-within-the-same-world&quot; aria-label=&quot;endofunctor a functor that stays within the same world permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The “category of endofunctors” in the definition of a monad refers to a category made up of endofunctors.&lt;/p&gt;
&lt;p&gt;As I briefly noted in the previous post, a functor is a mapping that takes one category to another. A general functor maps from category &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to a different category &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, but an endofunctor maps from &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T: C \to C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; — meaning the source and destination are the same category.&lt;/p&gt;
&lt;p&gt;Why is a monad an object in the “endofunctor category”? Because the functors we use in programming ultimately stay within the programming world. Consider the functor’s &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; operation, for example.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at this type signature, &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; takes &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt; and produces &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt;. The key point is that &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt; is a type in TypeScript’s type system, and the result type &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;B&gt;&lt;/code&gt; is also a type in TypeScript’s type system.&lt;/p&gt;
&lt;p&gt;It goes from the world of types to the world of types. That’s why functors in programming are endofunctors. They don’t go to another world — they transform within the same one.&lt;/p&gt;
&lt;h3 id=&quot;the-endofunctor-category-a-world-where-functors-themselves-are-objects&quot; style=&quot;position:relative;&quot;&gt;The Endofunctor Category: A World Where Functors Themselves Are Objects&lt;a href=&quot;#the-endofunctor-category-a-world-where-functors-themselves-are-objects&quot; aria-label=&quot;the endofunctor category a world where functors themselves are objects permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now let’s step up one level of abstraction. If we know that functors used in programming are endofunctors, we can conceive of a new category where endofunctors themselves are the objects.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Regular Type Category&lt;/th&gt;
&lt;th&gt;Endofunctor Category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Objects&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;, …&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Morphisms&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;(a: A) =&gt; B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Functor → Functor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Since morphisms in a category go from one object to another, morphisms in the endofunctor category go from one functor to another.&lt;/p&gt;
&lt;p&gt;A morphism that transforms one functor into another is called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_transformation&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Natural Transformation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;monoid-object-the-algebra-of-combining&quot; style=&quot;position:relative;&quot;&gt;Monoid Object: The Algebra of Combining&lt;a href=&quot;#monoid-object-the-algebra-of-combining&quot; aria-label=&quot;monoid object the algebra of combining permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that we’ve covered the “category of endofunctors” part of the definition, let’s look at what it means to be a “monoid object.”&lt;/p&gt;
&lt;p&gt;In mathematics, a monoid is a structure equipped with the following three things:&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;A set or collection of objects&lt;/li&gt;
&lt;li&gt;A binary operation: combines two elements to produce an element within the same set. Must satisfy associativity.&lt;/li&gt;
&lt;li&gt;An identity element: a special element that, when combined with any other element, returns that element unchanged.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;The concept is abstract enough to feel intimidating, but the examples aren’t that complicated. The most classic monoid is the relationship between integers and addition.&lt;/p&gt;
&lt;p&gt;With integers and addition, the addition operation takes two elements from the set of integers and returns another integer. Just like &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1 + 2 = 3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. And as you already know, addition satisfies the associativity law. Finally, the identity element — the number that returns any integer unchanged when added — is &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;This is why the set of integers paired with addition can be called a “monoid,” and mathematically it’s denoted as &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;Z&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(\mathbb{Z}, +)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;Z&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. &lt;small&gt;(Strictly speaking, integers under addition also have inverses, making it a group, but that’s not important for this explanation.)&lt;/small&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-connection-a-monad-is-a-monoid-object-in-the-category-of-endofunctors&quot; style=&quot;position:relative;&quot;&gt;The Connection: A Monad Is a Monoid Object in the Category of Endofunctors&lt;a href=&quot;#the-connection-a-monad-is-a-monoid-object-in-the-category-of-endofunctors&quot; aria-label=&quot;the connection a monad is a monoid object in the category of endofunctors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that we understand what a monoid is, we can finally understand what “a monoid object in the category of endofunctors” means.&lt;/p&gt;
&lt;p&gt;The endofunctor category is a category composed of programming functors like &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;, so we just need to check whether these objects form a monoid structure.&lt;/p&gt;
&lt;p&gt;Let’s compare the relationship between integers and addition — our representative monoid — with the relationship between endofunctors and their composition operation.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monoid Element&lt;/th&gt;
&lt;th&gt;Integer Addition&lt;/th&gt;
&lt;th&gt;Endofunctor Category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Binary operation&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;+&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1 + 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Composition &lt;code class=&quot;language-text&quot;&gt;∘&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Result of operation&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;Endofunctor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity element&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identity functor &lt;code class=&quot;language-text&quot;&gt;Id&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The comparison looks roughly similar. But there’s one problem: the result of the endofunctor binary operation &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; isn’t &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; but &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; — a nested result. In other words, it’s not an element within the same set.&lt;/p&gt;
&lt;p&gt;This is exactly where the monad’s &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) and &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) that we defined earlier come in.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Expression&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;A natural transformation that merges two layers of T into one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;Id&lt;/mtext&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{Id} \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;A natural transformation from the identity functor to T&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A natural transformation is a “structure-preserving transformation between functors.” It’s important that &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; isn’t simply “putting a value in a container” but a natural transformation. This means &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; must behave consistently for any type &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; — it cannot behave differently depending on the type.&lt;/p&gt;
&lt;p&gt;And if we revisit the monad laws from earlier, we can see that they satisfy the associativity and identity element laws that a monoid requires.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Law&lt;/th&gt;
&lt;th&gt;Expression&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Associativity&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\mu = \mu \circ \mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Same result regardless of merge order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity law&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\eta = id = \mu \circ \eta T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Wrapping and unwrapping returns the original. i.e., &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is the identity element.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The laws we established for programming turn out to be exactly what a monoid requires.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Monoid of Integers&lt;/th&gt;
&lt;th&gt;Monoid in Endofunctor Category (= Monad)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;td&gt;Endofunctor (&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;, …)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary operation&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;+&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity element&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;Id&lt;/mtext&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{Id} \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Associativity&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(a+b)+c = a+(b+c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\mu = \mu \circ \mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity law&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0+n = n = n+0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ \eta T = \text{id} = \mu \circ T\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is why we can call the monads we use in programming “a monoid object in the category of endofunctors.”&lt;/p&gt;
&lt;p&gt;But as I mentioned, this definition isn’t &lt;em&gt;why&lt;/em&gt; we started using monads in programming. We just needed to compose computations with effects sequentially, invented &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; to do it, and then noticed that what we’d built happened to match “monoid” — a structure mathematicians had known about for centuries.&lt;/p&gt;
&lt;h2 id=&quot;actually-monads-arent-boxes&quot; style=&quot;position:relative;&quot;&gt;Actually, Monads Aren’t Boxes&lt;a href=&quot;#actually-monads-arent-boxes&quot; aria-label=&quot;actually monads arent boxes permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far, we’ve used &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; as a concrete example to dissect how monads work. But in practice, what matters more than just implementing the code is understanding the context these tools carry and recognizing how they differ from existing tools.&lt;/p&gt;
&lt;p&gt;Many monad tutorials, including my own earlier ones, have explained functors and monads using the “box” metaphor. While intuitive, this metaphor only tells half the story.&lt;/p&gt;
&lt;p&gt;If you think of &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt; as merely “a box containing a future value,” it’s hard to explain why &lt;code class=&quot;language-text&quot;&gt;then&lt;/code&gt; must execute sequentially. So rather than calling functors and monads simple boxes, it’s more accurate to describe them as “the context of a computation accompanied by a particular effect.”&lt;/p&gt;
&lt;p&gt;Therefore, what &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; does isn’t simply “open the box and flatten it” — it’s closer to “safely chaining computations with different contexts.”&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monad&lt;/th&gt;
&lt;th&gt;Context (Effect)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The context of a value that might not exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The context that includes the reason for failure (error)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The context of an asynchronous computation that takes time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A nondeterministic context where multiple results may exist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;One more thing worth noting: we need to reconsider &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;. In code, &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt; behaves in a very monadic way, but under strict mathematical scrutiny, it’s not a monad.&lt;/p&gt;
&lt;p&gt;A monad requires &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; (which preserves structure) and &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; (which flattens structure) to be strictly separated, but Promise’s &lt;code class=&quot;language-text&quot;&gt;then&lt;/code&gt; mixes them depending on the return value.&lt;/p&gt;
&lt;p&gt;On top of that, a mathematical monad must allow a doubly-nested state &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟨&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟨&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟩&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟩&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T\langle T\langle A \rangle \rangle&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;⟨&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;⟨&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;⟩⟩&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to exist, but Promise doesn’t allow this at runtime — it collapses immediately into a single layer. Convenient in practice, but it breaks the mathematical properties that make monads predictable.&lt;/p&gt;
&lt;p&gt;Therefore, strictly speaking, &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt; cannot be called a monad.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing Thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With that, we’ve completed the long journey from functors through applicative functors to monads.&lt;/p&gt;
&lt;p&gt;Looking back, this whole thing started from a pretty practical question: “How can we compose functions safely?” We met &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; to get past the limits of functors, invented &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; to deal with nesting, and then noticed that what we’d built was “a monoid object in the category of endofunctors” — something mathematicians already had a name for.&lt;/p&gt;
&lt;p&gt;What’s nice about this is that the monad laws give us real confidence when writing code. The identity laws mean &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; won’t mess with your data. The associativity law means you can refactor freely without changing behavior. That kind of trust is what lets you build complex business logic out of small, composable pieces.&lt;/p&gt;
&lt;p&gt;Understanding monads is really about learning to handle abstract contexts and getting some mathematical backing for the code you write.&lt;/p&gt;
&lt;p&gt;I’ve done my best to take a stab at explaining monads, but honestly, I have no idea whether this article ended up being easy or difficult.&lt;/p&gt;
&lt;p&gt;If you have any further questions, feel free to reach out via email and I’ll do my best to explain. I’d love the interest and support of fellow functional programming enthusiasts.&lt;/p&gt;
&lt;p&gt;With that, I conclude this post: Beyond Functors, All the Way to Monads.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[펑터를 넘어서, 모나드까지]]></title><description><![CDATA[이번 포스팅에서는 이전에 다뤘던 펑터의 개념에 이어 모나드에 대한 설명을 이어가보려고 한다. 아무래도 모나드라고 하면 가장 먼저 떠오르는 것은 “모나드는 내부함자 범주의 모노이드 대상 어쩌고”하는 설명인데, 사실 이것은 모나드를 가장 잘 설명하는 문장이면서도 가장 설명을 못하는 문장이기도 하다. 모나드를 이해하는 순간 모나드를 설명할 수 없게 되어버린다는 모나드의 저주라고 불리는 유명한 밈이 존재할만큼, 수학을 잘 모르는 입장에서는 참 이해하기 난해한 대상이기는 하다. 이에 필자도 야심차게 모나드를 설명하기 위한 도전을 한번 해보려고 한다. (물론 실패할 수도 있다…)]]></description><link>https://evan-moon.github.io/2026/02/07/monads-in-typescript/</link><guid isPermaLink="false">20260207-monads-in-typescript</guid><pubDate>Sat, 07 Feb 2026 21:25:09 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 이전에 다뤘던 펑터의 개념에 이어 모나드에 대한 설명을 이어가보려고 한다.&lt;/p&gt;
&lt;p&gt;아무래도 모나드라고 하면 가장 먼저 떠오르는 것은 “모나드는 내부함자 범주의 모노이드 대상 어쩌고”하는 설명인데, 사실 이것은 모나드를 가장 잘 설명하는 문장이면서도 가장 설명을 못하는 문장이기도 하다.&lt;/p&gt;
&lt;p&gt;모나드를 이해하는 순간 모나드를 설명할 수 없게 되어버린다는 모나드의 저주라고 불리는 유명한 밈이 존재할만큼, 수학을 잘 모르는 입장에서는 참 이해하기 난해한 대상이기는 하다.&lt;/p&gt;
&lt;p&gt;이에 필자도 야심차게 모나드를 설명하기 위한 도전을 한번 해보려고 한다. &lt;small&gt;(물론 실패할 수도 있다…)&lt;/small&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;이전-글에서-다뤘던-것들&quot; style=&quot;position:relative;&quot;&gt;이전 글에서 다뤘던 것들&lt;a href=&quot;#%EC%9D%B4%EC%A0%84-%EA%B8%80%EC%97%90%EC%84%9C-%EB%8B%A4%EB%A4%98%EB%8D%98-%EA%B2%83%EB%93%A4&quot; aria-label=&quot;이전 글에서 다뤘던 것들 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;일단 이전 글을 적은 것이 무려 6년 전이니, 이전 글의 내용을 간단히 복기하고 넘어가도록 하자. 자세한 내용은 &lt;a href=&quot;/2020/01/27/safety-function-composition/&quot;&gt;이전 포스팅&lt;/a&gt;을 참고하면 된다.&lt;/p&gt;
&lt;p&gt;뭐가 복잡하고 말이 많지만 결국 핵심은 간단하다. 함수형 프로그래밍의 세계에서 함수를 합성하려면 첫 번째 함수의 출력 타입과 다음 함수의 입력 타입이 일치해야 한다.&lt;/p&gt;
&lt;p&gt;하지만 문제는 프로그래밍의 세계에는 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;, 에러 같은 불확실성이나 사이드 이펙트가 존재하기 때문에 이 규칙을 지키기가 쉽지 않다는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getStringLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// getFirstLetter의 치역이 string | undefined이므로&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// getStringLength와 바로 합성할 수 없다&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;getStringLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 문제를 해결하기 위해 값과 사이드 이펙트를 컨테이너로 감싸는 개념을 도입했고, 그 컨테이너가 바로 함자, 영어로는 펑터(Functor)였다.&lt;/p&gt;
&lt;p&gt;즉, 펑터는 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;이라는 연산을 통해 컨테이너 안의 값을 꺼내지 않고도 안전하게 변환할 수 있는 구조체라고 보면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;map: F&amp;lt;A&gt; → (A → B) → F&amp;lt;B&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 타입 시그니처는 &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;A&gt;&lt;/code&gt;라는 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; 연산에 내부 값을 변환하는 계산인 &lt;code class=&quot;language-text&quot;&gt;(A → B)&lt;/code&gt;을 넘겨주면 결과적으로 내부 값이 변경되어 &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;B&gt;&lt;/code&gt;가 된다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;이때 &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;A&gt;&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;F&amp;lt;B&gt;&lt;/code&gt;는 내부 값이 바뀌었을지언정, 본래 가지고 있던 구조 자체가 변경되어서는 안되기 때문에 아래 두 가지 법칙을 만족해야한다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;항등 법칙: &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F(\text{id}) = \text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;합성 법칙: &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F(g \circ f) = F(g) \circ F(f)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;id&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 인자로 받은 값을 그대로 반환하는 항등 함수이다. 이 항등 함수에 매핑을 적용하면 아무 일도 발생하지 않아야하는 것이 항등 법칙이다.&lt;/p&gt;
&lt;p&gt;두 번째 합성 법칙은 합성된 함수를 매핑한 것과 각각의 함수를 따로 매핑하고 합성한 결과가 같아야 한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;이 법칙들을 지켜야하는 이유는 단순한 수학적 결벽증 때문이 아니라, 이 법칙들을 지켜줘야 펑터가 “구조를 보존하는 사상”이라는 사실을 보장하기 때문이다.&lt;/p&gt;
&lt;p&gt;항등 법칙이 성립하면 &lt;code class=&quot;language-text&quot;&gt;a.map(x =&gt; x)&lt;/code&gt;가 정말로 아무것도 하지 않음을 신뢰할 수 있지만, 만약 이 과정에서 리스트의 순서라던가 트리의 높이와 같은 내부 구조가 변형된다면 이건 더 이상 매핑이 아니라 “재구성”이다. 즉, 항등 법칙은 펑터가 반드시 알맹이만 건드리고 껍데기는 건드리지 않는다는 신뢰의 기반이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;그리고 합성 법칙이 성립하면 &lt;code class=&quot;language-text&quot;&gt;a.map(f).map(g)&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;a.map(x =&gt; g(f(x)))&lt;/code&gt;로 바꿔도 동작이 동일함을 보장받는다.&lt;/p&gt;
&lt;p&gt;이는 루프를 두 번 도는 &lt;code class=&quot;language-text&quot;&gt;a.map(f).map(g)&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;a.map(x =&gt; g(f(x)))&lt;/code&gt;로 합쳐서 루프를 한 번만 돌아도 동작이 똑같다는 것을 보장하며, 반대로 복잡한 로직을 가독성을 위해 여러 개의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;으로 쪼개도 안전하다는 뜻이기도 하다.&lt;/p&gt;
&lt;p&gt;하지만 이 펑터에도 한계가 존재한다. 바로 이 한계로 인해 우리가 오늘 알아볼 모나드가 등장하게 된다.&lt;/p&gt;
&lt;h2 id=&quot;펑터의-한계&quot; style=&quot;position:relative;&quot;&gt;펑터의 한계&lt;a href=&quot;#%ED%8E%91%ED%84%B0%EC%9D%98-%ED%95%9C%EA%B3%84&quot; aria-label=&quot;펑터의 한계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;1988년, 에든버러 대학의 컴퓨터 과학자 에우제니오 모지(Eugenio Moggi)는 골치 아픈 문제와 씨름하고 있었다. 프로그램의 의미를 수학적으로 정의하는 의미론 연구를 하던 그는, 순수 람다 계산법과 현실 프로그램 사이의 간극을 어떻게 메울지 고민하고 있었다.&lt;/p&gt;
&lt;p&gt;순수 람다 계산법에서 타입 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 “입력 A를 받아 B를 돌려주는 전체 함수”를 의미한다. 수학적으로는 아주 깔끔하지만 사실 현실의 프로그램은 그렇지 않다.&lt;/p&gt;
&lt;p&gt;프로그램은 무한 루프에 빠질 수도 있고, 예외를 던질 수도 있고, 상태를 변경할 수도 있고, 파일을 읽을 수도 있기 때문이다. 이런 여러가지 “효과(effect)“를 발생시키는 프로그램을 순수 함수 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 보면 의미가 왜곡된다.&lt;/p&gt;
&lt;p&gt;그래서 모지는 프로그램을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 아니라 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 보자는 것에서 출발했다. 여기서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 “계산의 개념”을 담는 구조를 의미하며, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 값을 결과로 내는 계산이라는 뜻이다. 값 자체가 아니라 값을 만들어내는 계산을 타입으로 표현하는 것이다.&lt;/p&gt;
&lt;p&gt;말로만 하면 어려우니 직접적인 예시를 한번 보자면, 우리에게 익숙한 계산들은 이런 것들이 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;Maybe&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to \text{Maybe}(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Maybe&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: 실패할 수도 있는 계산&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;IO&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to \text{IO}(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;IO&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: 외부 세계와 상호작용하는 계산&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;State&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to \text{State}(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;State&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: 상태를 변경하는 계산&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;그런데 막상 이렇게 접근하자니 또 한 가지 문제가 발생한다. 바로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 형태의 함수들을 합성하는 것이 까다로워진 것이다. 첫 함수가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \to T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라면 두 번째 함수는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B \to T(C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 형태가 될텐데, 첫 번째 함수의 출력인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 두 번째 함수의 입력 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 맞지 않는 문제가 발생한다.&lt;/p&gt;
&lt;p&gt;모지는 이 합성 문제를 해결하는 구조가 카테고리 이론에서 이미 연구되어 있다는 것을 발견했고, 그것이 바로 함수형 프로그래밍에서의 모나드의 시작이었다.&lt;/p&gt;
&lt;p&gt;이렇게 모지가 수학에서 빌려온 “모나드”라는 이름표가, 오늘날 컴퓨터 이론에서 가장 악명 높으면서도 강력한 추상화의 이름이 되었다.&lt;/p&gt;
&lt;h4 id=&quot;왜-펑터로는-해결이-안될까&quot; style=&quot;position:relative;&quot;&gt;왜 펑터로는 해결이 안될까?&lt;a href=&quot;#%EC%99%9C-%ED%8E%91%ED%84%B0%EB%A1%9C%EB%8A%94-%ED%95%B4%EA%B2%B0%EC%9D%B4-%EC%95%88%EB%90%A0%EA%B9%8C&quot; aria-label=&quot;왜 펑터로는 해결이 안될까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;그렇다면 모지의 고민은 왜 펑터만으로 해결이 어려운 것일까? 우리는 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;이 해결하지 못하는 두 가지 결정적인 병목 지점을 마주하게 된다.&lt;/p&gt;
&lt;p&gt;먼저 계산의 맥락인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 안에 함수가 갇혀버린 경우를 생각해보자. 이런 케이스를 발생시키는 대표적 예시로는 커링이 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 사용하면 &lt;code class=&quot;language-text&quot;&gt;maybeA&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; 연산을 적용하여 다음 인자를 기다리는 함수를 만들어낼 수 있을까? 결론부터 말하자면 불가능하다. 왜냐하면 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 통해 적용된 연산의 결과가 그냥 함수가 아니기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; addA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// map의 타입 시그니처에 대입해보면...&lt;/span&gt;
map&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  maybeNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;일반적으로 커링된 함수를 사용하면 &lt;code class=&quot;language-text&quot;&gt;addA&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;(b: number) =&gt; number&lt;/code&gt; 타입이 되어야겠지만, 여기서는 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 사용하여 연산을 적용했으므로, 결과적으로 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;(b: number) =&gt; number&gt;&lt;/code&gt;라는 타입을 얻게 된다. 즉, 함수가 계산의 맥락 안에 갇혀버렸다.&lt;/p&gt;
&lt;p&gt;그런데 문제는 이렇게 되어버리면 쌩 함수만 인자로 받을 수 있는 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 사용하여 합성을 진행하는 것이 불가능해진다는 것이다. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;은 맥락 밖의 함수를 맥락 안의 값에 적용할 뿐, 맥락 안에 갇힌 함수를 다른 맥락 안에 있는 값에게 전달할 방법이 없다.&lt;/p&gt;
&lt;p&gt;이것은 기본적으로 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;이 커링된 함수를 받을 때 바깥 쪽에 있는 함수에만 연산을 적용하기 때문이다. 커링된 함수처럼 함수가 함수를 반환하는 경우에는 안 쪽의 함수까지 닿을 수가 없다.&lt;/p&gt;
&lt;p&gt;그리고 또 다른 문제는 펑터를 반환하는 두 함수를 합성하는 상황 속에서 발생한다. 이번에도 “값이 있을 수도 있고 없을 수도 있다”를 의미하는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 펑터를 예시로 한번 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; findUser&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; findTeam&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수들은 모지가 고안해냈던 입력 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 받아 계산 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 반환하는 함수들을 의미한다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;findUser&lt;/code&gt; 함수는 유저의 아이디를 인자로 받아 &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;를 반환한다. 이때 이상한 아이디가 들어오면 매칭되는 유저가 없을 것이기 때문에 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 펑터를 사용한 것이다. 그리고 &lt;code class=&quot;language-text&quot;&gt;findTeam&lt;/code&gt; 함수는 &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;를 인자로 받아 유저의 소속 팀을 반환한다. 우리는 이 두 함수를 합성해서 유저의 팀을 찾는 함수를 만드려고 한다.&lt;/p&gt;
&lt;p&gt;문제는 &lt;code class=&quot;language-text&quot;&gt;findUser&lt;/code&gt;가 반환하는 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;User&gt;&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;findTeam&lt;/code&gt;이 바로 받아들일 수 없다는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 사용하면 어찌저찌 합성을 해볼 수는 있다. 한번 합성을 진행해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; findTeam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// map의 타입 시그니처에 대입해보면...&lt;/span&gt;
&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Team&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;어찌어찌 합성은 성공했지만, 결과적으로 타입이 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;Team&gt;&gt;&lt;/code&gt;이라는 슬픈 상황이 되어버렸다. 만약 여기서 팀 정보를 통해 팀장을 찾는 과정을 한 번 더 추가한다면 타입은 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;Maybe&amp;lt;Manager&gt;&gt;&gt;&lt;/code&gt;와 같이 무한히 중첩될 것이다.&lt;/p&gt;
&lt;h4 id=&quot;이-쯤에서-한번-정리해보자&quot; style=&quot;position:relative;&quot;&gt;이 쯤에서 한번 정리해보자&lt;a href=&quot;#%EC%9D%B4-%EC%AF%A4%EC%97%90%EC%84%9C-%ED%95%9C%EB%B2%88-%EC%A0%95%EB%A6%AC%ED%95%B4%EB%B3%B4%EC%9E%90&quot; aria-label=&quot;이 쯤에서 한번 정리해보자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;우리는 모지의 문제를 따라가면서 펑터로는 해결할 수 없는 두 가지의 문제에 직면했다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;문제&lt;/th&gt;
&lt;th&gt;원인&lt;/th&gt;
&lt;th&gt;필요한 것&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;맥락 안의 함수 적용&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;은 바깥의 함수만 받음&lt;/td&gt;
&lt;td&gt;안의 함수를 안의 값에 적용하는 연산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;맥락 중첩&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;은 한 겹만 벗김&lt;/td&gt;
&lt;td&gt;이중 맥락을 단일 맥락으로 펴는 연산&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;center&gt;
 &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4142324907ddfda791bb342ea64416ec/65f94/head.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 73.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGZmVRLsCg//8QAGhAAAgIDAAAAAAAAAAAAAAAAAQIAAxIhI//aAAgBAQABBQI2rK06FZtSLSsR81//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGn/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABsQAAICAwEAAAAAAAAAAAAAAAABESECECJR/9oACAEBAAY/AqYoc+6g5oWR/8QAGRAAAgMBAAAAAAAAAAAAAAAAASEAEUEx/9oACAEBAAE/Ib+mKBBSo19ggUZR5dHYRBdTvYnHs//aAAwDAQACAAMAAAAQp9//xAAXEQADAQAAAAAAAAAAAAAAAAAAASEx/9oACAEDAQE/EM0TP//EABYRAQEBAAAAAAAAAAAAAAAAAAABYf/aAAgBAgEBPxDKx//EABwQAQADAAIDAAAAAAAAAAAAAAEAESExQVGB0f/aAAgBAQABPxB1FVie0GUWWTs+zQoJdVcWYCVwSPO4Mk9IxgEUPCOz/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;head&quot; title=&quot;&quot; src=&quot;/static/4142324907ddfda791bb342ea64416ec/65f94/head.jpg&quot; srcset=&quot;/static/4142324907ddfda791bb342ea64416ec/0913d/head.jpg 160w,
/static/4142324907ddfda791bb342ea64416ec/cb69c/head.jpg 320w,
/static/4142324907ddfda791bb342ea64416ec/65f94/head.jpg 420w&quot; sizes=&quot;(max-width: 420px) 100vw, 420px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
 &lt;small&gt;펑터로 전부 해결할 수 있을 줄 알았는데 전혀 아니었다는 슬픈 결말&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;괜찮다. 문제는 해결하면 되니까. 이제 우리는 이 문제를 해결하기 위한 설계도를 차근차근 그려보려고 한다.&lt;/p&gt;
&lt;p&gt;이 중 첫 번째 문제인 맥락 안에 함수가 갇혀버린 상황은 어플리케이티브 펑터(Applicative Functor)라는 녀석으로 해결할 수 있고, 함수를 합성할 때마다 맥락이 계속 중첩되어 버린다는 문제를 바로 모나드(Monad)가 해결할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;해결책-설계-어플리케이티브-펑터와-모나드&quot; style=&quot;position:relative;&quot;&gt;해결책 설계: 어플리케이티브 펑터와 모나드&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%EC%B1%85-%EC%84%A4%EA%B3%84-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%ED%8B%B0%EB%B8%8C-%ED%8E%91%ED%84%B0%EC%99%80-%EB%AA%A8%EB%82%98%EB%93%9C&quot; aria-label=&quot;해결책 설계 어플리케이티브 펑터와 모나드 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제 우리는 첫 번째 문제를 해결하기 위해 새로운 연산을 발명해야 한다. 이제부터는 앞서 언급했던 “계산의 맥락”이라는 표현이 너무 기니, 간단하게 “컨테이너”라고 부르도록 하겠다.&lt;/p&gt;
&lt;p&gt;첫 번째 문제는 컨테이너 내부에 함수가 갇혀버린 상황이었으니, 이 함수를 다른 컨테이너 안에 있는 값에 적용할 수 있는 연산이 있으면 될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 컨테이너 안의 함수를 다른 컨테이너 안의 값에 적용한다
apply: T&amp;lt;(A → B)&gt; → T&amp;lt;A&gt; → T&amp;lt;B&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 연산과 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;과 차이는 적용하려는 함수가 컨테이너 밖에 있느냐 안에 있느냐 뿐이다. 그리고 이 연산을 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;라고 부른다.&lt;/p&gt;
&lt;p&gt;그리고 이 함수를 값에 적용한 뒤 다시 컨테이너에 담아줘야 하는 연산도 필요하다. 이 연산은 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; 연산이라고 부른다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 순수한 값을 컨테이너에 넣는다
pure: A → T&amp;lt;A&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 이렇게 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; 연산을 갖춘 펑터를 어플리케이티브 펑터라고 부른다. 이번에도 우리에게 익숙한 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 컨테이너를 예시로 들어 이 연산들을 타입스크립트 타입 시그니처로 표현해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apply&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pure&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 이 어플리케이티브 펑터를 통해 앞서 우리가 겪었던 첫 번째 문제인 커링된 함수를 합성해보면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeAddA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;(b: number) =&gt; number&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maybeAddA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;number&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// apply의 타입 시그니처에 대입해보면...&lt;/span&gt;
&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  f&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 우리는 어플리케이티브 펑터의 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;라는 연산을 통해 위 예시의 &lt;code class=&quot;language-text&quot;&gt;maybeA&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;maybeB&lt;/code&gt;와 같은 여러 개의 컨테이너를 동시에 다루는 문제를 우아하게 해결할 수 있게 되었다.&lt;/p&gt;
&lt;h3 id=&quot;어플리케이티브-펑터의-한계&quot; style=&quot;position:relative;&quot;&gt;어플리케이티브 펑터의 한계&lt;a href=&quot;#%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%ED%8B%B0%EB%B8%8C-%ED%8E%91%ED%84%B0%EC%9D%98-%ED%95%9C%EA%B3%84&quot; aria-label=&quot;어플리케이티브 펑터의 한계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;하지만 우리가 해결한 문제에는 중요한 전제가 하나 있다. 바로 어떤 상자들을 합성할지 미리 정해져 있어야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;한번 어플리케이티브 펑터의 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt; 연산 과정을 다시 떠올려보자. &lt;code class=&quot;language-text&quot;&gt;maybeA&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;maybeB&lt;/code&gt;는 계산이 시작되기 전부터 이미 우리 손에 들려있는 독립적인 컨테이너들이다. 즉, 계산의 구조가 값과 상관없이 고정되어있다는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 현실의 프로그램은 이보다 훨씬 동적인 경우가 많다. 이전 계산의 결과 값을 보고 나서야 다음에 어떤 컨테이너를 가져올지, 아니면 아예 컨테이너를 가져오지 않을지를 결정해야하는 상황이 훨씬 많다는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 유저를 찾고, 그 유저의 정보를 토대로 팀을 찾는다.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 즉, 팀을 찾는 함수는 유저가 누구냐에 따라 다른 결과를 내놓는다.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findTeam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;teamId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 또 문제가 발생한다. &lt;code class=&quot;language-text&quot;&gt;findTeam&lt;/code&gt;이 반환하는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 컨테이너는 &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt;라는 값에 의존하여 생성되기 때문이다. 즉, 이전 계산의 결과가 다음 계산의 맥락을 결정한다.&lt;/p&gt;
&lt;p&gt;어플리케이티브 펑터는 이미 존재하는 컨테이너끼리만 소통시킬 수 있기 때문에 이렇게 실행 중에 동적으로 만들어지는 순차적 의존성을 표현할 수가 없다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;정적(Static)&lt;/th&gt;
&lt;th&gt;동적(Dynamic)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“A와 B를 각각 가져와서 합쳐라”&lt;/td&gt;
&lt;td&gt;“A를 가져오고, 그 결과를 보고 B를 할지 말지 정해라”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;결국 동적으로 만들어지는 순차적 의존성을 해결하려면 이전 계산의 결과물로 다음 계산(컨테이너)을 생성해야 하고, 이 과정에서 컨테이너가 중첩되는 것은 피할 수 없는 숙명이 된다.&lt;/p&gt;
&lt;center&gt;
 &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 282px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/298c3198f4c789d26495cbde7800fa25/822fd/oh.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 136.24999999999997%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAwADAAAAAAAAAAAAAAAAAAQFAQID/8QAFwEBAAMAAAAAAAAAAAAAAAAAAgADBf/aAAwDAQACEAMQAAABszaKIdUwMRJriVWjsciL/8QAGxABAQADAAMAAAAAAAAAAAAAAQIAAwQQETH/2gAIAQEAAQUC2qQe4vNtARQoidFrOF1OdP3x/8QAGBEAAgMAAAAAAAAAAAAAAAAAARADITL/2gAIAQMBAT8BApQ5X//EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAECAQE/AWP/xAAeEAABBAIDAQAAAAAAAAAAAAABAAIQESEiMVFhgf/aAAgBAQAGPwLHKBD3Hu4ytjqrBtH0xhxC+z//xAAeEAACAgICAwAAAAAAAAAAAAABEQAhEEExYVFxsf/aAAgBAQABPyE7dFTlt4QhUsIxrfqN4tohAPInOAqA6jKTqBEI6M+rP//aAAwDAQACAAMAAAAQvwTy/8QAGBEBAAMBAAAAAAAAAAAAAAAAAQARIRD/2gAIAQMBAT8QvtXCaiDqT//EABgRAAMBAQAAAAAAAAAAAAAAAAABIRAR/9oACAECAQE/EGsxs6f/xAAfEAEBAAICAQUAAAAAAAAAAAABEQAhMUGhEGFxkfH/2gAIAQEAAT8Qa6AEWV2/WS094knfpCgRqdDnAN7uxl6rhpR4SmLy00ah/POPNPZdY0cGxAuJSLxDzjxh385//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;oh&quot; title=&quot;&quot; src=&quot;/static/298c3198f4c789d26495cbde7800fa25/822fd/oh.jpg&quot; srcset=&quot;/static/298c3198f4c789d26495cbde7800fa25/0913d/oh.jpg 160w,
/static/298c3198f4c789d26495cbde7800fa25/822fd/oh.jpg 282w&quot; sizes=&quot;(max-width: 282px) 100vw, 282px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
 &lt;small&gt;오 그렇다면 중첩된 컨테이너를 펴주는 연산이 있다면 어떨까?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;어플리케이티브 펑터는 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;라는 새로운 연산을 통해 컨테이너 안의 함수를 실행했다. 하지만 만약 우리가 중첩을 평평하게 펴주는 도구를 갖게 된다면, 굳이 새로운 컨테이너 내부의 함수를 실행하는 번거로운 짓을 하지 않고도 이 문제를 해결할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeA&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybeB&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 중첩을 펴주는 녀석이 있다면 map만으로도 문제를 해결할 수 있다!&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 1. 커링된 함수를 매핑하면 컨테이너에 담긴 함수가 나온다&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maybePartialFn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeA&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 결과: Maybe&amp;lt;(b: number) =&gt; number&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 2. map을 사용하여 컨테이너 안에 담긴 함수에 접근하고 계산 수행&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nested &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybePartialFn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fn &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybeB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 결과: Maybe&amp;lt;Maybe&amp;lt;number&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 3. 그리고 중첩을 제거하면?&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;펴주는녀석&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nested&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 결과: Maybe&amp;lt;number&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 일단 합성해서 중첩시켜버리고 나중에 중첩을 펴버리면 되는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;모나드-중첩을-펴는-연산의-발명&quot; style=&quot;position:relative;&quot;&gt;모나드, 중첩을 펴는 연산의 발명&lt;a href=&quot;#%EB%AA%A8%EB%82%98%EB%93%9C-%EC%A4%91%EC%B2%A9%EC%9D%84-%ED%8E%B4%EB%8A%94-%EC%97%B0%EC%82%B0%EC%9D%98-%EB%B0%9C%EB%AA%85&quot; aria-label=&quot;모나드 중첩을 펴는 연산의 발명 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;결국 모나드는 이러한 문제를 해결하기 위해 등장했다. 다시 말하자면 모나드는 컨테이너의 중첩을 펴는 연산을 가진 무언가이다.&lt;/p&gt;
&lt;p&gt;그리고 이렇게 중첩을 펴는 연산을 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;flatten&lt;/code&gt;이라고 부른다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;join: T&amp;lt;T&amp;lt;A&gt;&gt; → T&amp;lt;A&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; join&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; 연산은 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;A&gt;&gt;&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;A&gt;&lt;/code&gt;로 만든다. 수학적으로는 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 두 번 적용한 것을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 한 번으로 줄이는 것”이다.&lt;/p&gt;
&lt;p&gt;사실 이러한 연산은 우리 주변에서도 쉽게 찾아볼 수 있는데, 바로 JavaScript의 &lt;code class=&quot;language-text&quot;&gt;Array.prototype.flat&lt;/code&gt;이 바로 이러한 역할을 한다.&lt;/p&gt;
&lt;p&gt;그리고 어플리케이티브 펑터와 마찬가지로 순수한 값을 컨테이너에 넣어주는 연산도 필요하다. 이 연산은 어플리케이티브 펑터와 마찬가지로 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;라고 부르거나, &lt;code class=&quot;language-text&quot;&gt;of&lt;/code&gt;라고 부르기도 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pure: A → T&amp;lt;A&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pure&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 실제 프로그래밍에서 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;을 직접 쓰는 일은 거의 없다. 앞선 예시에서 보았듯이 모나드는 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 사용하여 컨테이너 안에 담긴 무언가에 접근하여 합성을 진행하고 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;을 이용해서 중첩을 다시 펴는 것이 한 세트로 작동하기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;1. 컨테이너 안의 값에 함수를 적용하고 싶다 = map을 쓴다
2. 그런데 그 함수가 결과를 컨테이너에 담아서 반환한다 = 이중 포장이 된다
3. 이중 포장을 벗겨야 한다 = join을 쓴다&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그래서 우리는 이 두 가지 연산을 하나로 합쳐 좀 더 편리하게 사용하려고 한다.&lt;/p&gt;
&lt;h4 id=&quot;flatmap--map--join&quot; style=&quot;position:relative;&quot;&gt;flatMap = map + join&lt;a href=&quot;#flatmap--map--join&quot; aria-label=&quot;flatmap  map  join permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;매번 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; 다음에 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;을 부르는 것이 번거로우니, 이 두 단계를 하나로 합친 것이 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;이다. 이번에도 마찬가지로 우리에게 친숙한 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 컨테이너를 받는 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;이 어떤 타입 시그니처로 표현되는지 알아보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;map:     T&amp;lt;A&gt; → (A → B)    → T&amp;lt;B&gt;     // 일반 함수를 적용
flatMap: T&amp;lt;A&gt; → (A → T&amp;lt;B&gt;) → T&amp;lt;B&gt;     // 컨테이너 반환 함수를 적용 + 펴기&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flatMap&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;의 차이점은 두 번째 인자에 있다. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;은 단순히 &lt;code class=&quot;language-text&quot;&gt;A =&gt; B&lt;/code&gt; 형태의 함수를 받지만, &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;(A =&gt; Maybe&amp;lt;B&gt;)&lt;/code&gt; 형태의 함수를 받는다.&lt;/p&gt;
&lt;p&gt;타입시그니처로는 표현되지 않았지만 내부적으로 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;의 역할까지 하고 있기 때문에 결과 타입은 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;B&gt;&gt;&lt;/code&gt;와 같은 슬픈 형태가 아니라 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;B&gt;&lt;/code&gt;가 되는 것이다.&lt;/p&gt;
&lt;p&gt;이제 우리는 이 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;을 사용하여 계산들 간의 순차적 의존성을 표현할 수 있게 되었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// map을 쓰면 결과 타입이 중첩됨&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findDepartment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deptId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;Maybe&amp;lt;Department&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// flatMap을 쓰면 해결&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;findUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findDepartment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deptId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Maybe&amp;lt;Department&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, 어플리케이티브 펑터의 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, 모나드의 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;에 대해서 알아보았다. 분량이 워낙 많았으니 한번 다시 정리하고 넘어가보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 펑터의 map&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 어플리케이티브 펑터의 apply&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apply&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 모나드의 flatMap&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flatMap&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;먼저 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;은 컨테이너 안에 있는 값에 일반 함수를 적용하는 녀석이다. 하지만 이것만으로는 컨테이너 내부에 갇힌 함수는 사용할 수 없다는 문제가 발생한다.&lt;/p&gt;
&lt;p&gt;그래서 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;가 등장했다. &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;는 컨테이너 내부에 있는 함수에 접근할 수 있도록 만들어줘서 이런 상황일 때도 계산의 합성이 가능하도록 만들어주었다. 하지만 결국 순차적 의존성을 가진 동적인 계산을 진행하면 컨테이너가 중첩된다는 문제가 발생했다.&lt;/p&gt;
&lt;p&gt;이를 해결하기 위해 중첩된 연산을 펴주는 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;과 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;이 합쳐진 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;이 등장했다. 우리는 이제 이 연산을 통해 앞 결과에 의해 다음 계산을 결정하는 순차적 의존성을 가진 계산도 자유롭게 합성할 수 있게 되었다.&lt;/p&gt;
&lt;h2 id=&quot;법칙은-리팩토링에-대한-증명&quot; style=&quot;position:relative;&quot;&gt;법칙은 리팩토링에 대한 증명&lt;a href=&quot;#%EB%B2%95%EC%B9%99%EC%9D%80-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A6%9D%EB%AA%85&quot; aria-label=&quot;법칙은 리팩토링에 대한 증명 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;그렇다면 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;은 정말 우리가 함수를 안전하게 합성할 수 있게 만들어주는 마법인걸까? 글쎄, 이것을 자신있게 이야기하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;이 지켜줘야하는 몇 가지 법칙이 존재한다.&lt;/p&gt;
&lt;h3 id=&quot;세-가지-법칙&quot; style=&quot;position:relative;&quot;&gt;세 가지 법칙&lt;a href=&quot;#%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B2%95%EC%B9%99&quot; aria-label=&quot;세 가지 법칙 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;우리가 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;을 자유롭게 사용하기 위해 이 연산은 아래 법칙을 지켜준다는 것이 보장되어야 한다.&lt;/p&gt;
&lt;h4 id=&quot;결합-법칙-어느-층부터-합쳐도-같아야-한다&quot; style=&quot;position:relative;&quot;&gt;결합 법칙: 어느 층부터 합쳐도 같아야 한다&lt;a href=&quot;#%EA%B2%B0%ED%95%A9-%EB%B2%95%EC%B9%99-%EC%96%B4%EB%8A%90-%EC%B8%B5%EB%B6%80%ED%84%B0-%ED%95%A9%EC%B3%90%EB%8F%84-%EA%B0%99%EC%95%84%EC%95%BC-%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;결합 법칙 어느 층부터 합쳐도 같아야 한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;가장 먼저 결합 법칙이다. 즉, 중첩을 펼 때, 어느 쪽부터 펴든 결과가 같아야 한다는 것을 의미한다. 한번 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;Maybe&amp;lt;Maybe&amp;lt;A&gt;&gt;&gt;&lt;/code&gt;처럼 삼중의 계산으로 감싸진 컨테이너가 있다고 생각해보자.&lt;/p&gt;
&lt;p&gt;우리는 이제 이 컨테이터를 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;형태로 만들기 위해 중첩을 펴내야 한다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(T(A))) \to T(T(A)) \to T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;이 중첩을 펴서 한 겹으로 만드는 방법은 두 가지다. 첫 번째 방법은 안쪽 두 개의 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 먼저 합친 다음, 바깥 쪽에 남은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 벗겨내 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 만드는 방법이다. 그리고 두 번째 방법은 바깥에 있는 두 개의 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 합친 다음, 안 쪽에 남은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 벗기는 방법이다.&lt;/p&gt;
&lt;p&gt;이 중 어떤 순서로 연산을 수행하던 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 최종 결과는 같아야 한다는 것이 바로 결합법칙이다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\mu = \mu \circ \mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 수식에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(뮤)는 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;을 의미한다.&lt;/p&gt;
&lt;p&gt;여기서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 “안쪽 두 겹”을 합치는 것이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 “바깥쪽 두 겹”을 합치는 것이라고 보면 된다. 즉, 3층 마트료시카를 2층으로 줄일 때, 안쪽 인형들을 먼저 합치느냐 바깥쪽 인형들을 먼저 합치느냐의 차이가 없어야 한다는 것이다.&lt;/p&gt;
&lt;h4 id=&quot;좌단위-법칙-입구에서-장난치지-말자&quot; style=&quot;position:relative;&quot;&gt;좌단위 법칙: 입구에서 장난치지 말자&lt;a href=&quot;#%EC%A2%8C%EB%8B%A8%EC%9C%84-%EB%B2%95%EC%B9%99-%EC%9E%85%EA%B5%AC%EC%97%90%EC%84%9C-%EC%9E%A5%EB%82%9C%EC%B9%98%EC%A7%80-%EB%A7%90%EC%9E%90&quot; aria-label=&quot;좌단위 법칙 입구에서 장난치지 말자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;두 번째는 좌단위 법칙이다. 이 법칙은 넣었다가 바로 벗기면 아무 일도 없었던 것과 동일한 상태여야한다는 것을 의미한다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\eta = \text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token function&quot;&gt;pure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 수식에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(에타)는 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;를 의미한다.&lt;/p&gt;
&lt;p&gt;여기서 특히 주목해야 할 부분은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 앞에 붙은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)인데, 이는 상자 바깥이 아니라 이미 상자에 담겨 있는 내부의 값에 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;를 적용하라는 뜻이다.&lt;/p&gt;
&lt;p&gt;즉, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 컨테이너가 있을 때 내부의 알맹이 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;로 감싸서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 이중 구조를 만든 뒤, 이를 다시 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)으로 펴내면 원래의 상태(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)로 돌아와야 한다는 법칙이다.&lt;/p&gt;
&lt;p&gt;이 법칙이 보장되어야 우리는 컨테이너 내부에서 일어나는 계산의 최소 단위인 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; 연산을 신뢰할 수 있다. 만약 이 좌단위 법칙이 깨진다는 것은 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;가 단순히 값을 감싸는 것을 넘어 내부적으로 로직을 변형시키고 있다는 것을 의미하기 때문이다.&lt;/p&gt;
&lt;h4 id=&quot;우단위-법칙-포장지만-바꿨다면-알맹이는-그대로&quot; style=&quot;position:relative;&quot;&gt;우단위 법칙: 포장지만 바꿨다면 알맹이는 그대로&lt;a href=&quot;#%EC%9A%B0%EB%8B%A8%EC%9C%84-%EB%B2%95%EC%B9%99-%ED%8F%AC%EC%9E%A5%EC%A7%80%EB%A7%8C-%EB%B0%94%EA%BF%A8%EB%8B%A4%EB%A9%B4-%EC%95%8C%EB%A7%B9%EC%9D%B4%EB%8A%94-%EA%B7%B8%EB%8C%80%EB%A1%9C&quot; aria-label=&quot;우단위 법칙 포장지만 바꿨다면 알맹이는 그대로 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;세 번째는 우단위 법칙이다. 이는 좌단위 법칙과 유사하지만, 컨테이너를 씌우는 순서가 반대다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ \eta T = \text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; m&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 이미 존재하는 컨테이너 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 자체를 하나의 값으로 간주하고, 그 바깥을 pure(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)로 한 번 더 감싸는 행위를 의미한다. 결과적으로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 되어 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 이중 구조가 만들어지는 것이다.&lt;/p&gt;
&lt;p&gt;우단위 법칙이 말하고자 하는 핵심은 명확하다. 상자 바깥을 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;로 한 겹 더 감싼 뒤(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;), 다시 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)으로 그 겉껍데기를 벗겨내면 결국 처음의 상태(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{id}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)와 동일해야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;앞서 언급했듯이 이 단위 법칙들이 중요한 이유는 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;라는 연산이 맥락을 왜곡하지 않는 항등원임을 보장하기 때문이다.&lt;/p&gt;
&lt;p&gt;마치 우리가 숫자에 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;을 더해도 값이 변하지 않듯, 어떤 컨테이너를 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;로 감싸고 다시 펴는 행위는 그 컨테이너가 가진 원래의 정보나 상태에 아무런 영향을 주지 않아야 한다.&lt;/p&gt;
&lt;h2 id=&quot;다시-내부함자-범주의-모노이드-대상으로&quot; style=&quot;position:relative;&quot;&gt;다시 “내부함자 범주의 모노이드 대상”으로&lt;a href=&quot;#%EB%8B%A4%EC%8B%9C-%EB%82%B4%EB%B6%80%ED%95%A8%EC%9E%90-%EB%B2%94%EC%A3%BC%EC%9D%98-%EB%AA%A8%EB%85%B8%EC%9D%B4%EB%93%9C-%EB%8C%80%EC%83%81%EC%9C%BC%EB%A1%9C&quot; aria-label=&quot;다시 내부함자 범주의 모노이드 대상으로 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자, 그렇다면 이것이 위키에 나와있는 모나드의 정의인 “내부함자 범주의 모노이드 대상”과 무슨 관련이 있는 것일까?&lt;/p&gt;
&lt;p&gt;여기서부터는 추상적이고 수학적인 이야기가 많이 나오니, 실무적인 수준으로 모나드를 이해하는 것만으로도 충분한 독자들은 건너뛰어도 된다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9e58e5b0f155e0d74c064038ab30b02d/10fd8/hard.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 54.37499999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABAAF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAFmfoFNBm0//8QAGhAAAgMBAQAAAAAAAAAAAAAAAQIDESEAMv/aAAgBAQABBQLB3uUrIDevjBjX/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEREv/aAAgBAwEBPwFKmD//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEv/aAAgBAgEBPwFT/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAEQIRH/2gAIAQEABj8CHwxzJ//EABoQAQACAwEAAAAAAAAAAAAAAAEAETFBcSH/2gAIAQEAAT8hHaG455pvXkRCByWTbDfhyZhn/9oADAMBAAIAAwAAABCDD//EABcRAQADAAAAAAAAAAAAAAAAAAABESH/2gAIAQMBAT8Qiyu//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFyP/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFBUWGR/9oACAEBAAE/EChAOWeXcQBa1HEVv7LKs4tfsBiJ1xqF1PxF2se0Gf/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;hard&quot; title=&quot;&quot; src=&quot;/static/9e58e5b0f155e0d74c064038ab30b02d/c08c5/hard.jpg&quot; srcset=&quot;/static/9e58e5b0f155e0d74c064038ab30b02d/0913d/hard.jpg 160w,
/static/9e58e5b0f155e0d74c064038ab30b02d/cb69c/hard.jpg 320w,
/static/9e58e5b0f155e0d74c064038ab30b02d/c08c5/hard.jpg 640w,
/static/9e58e5b0f155e0d74c064038ab30b02d/10fd8/hard.jpg 942w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;하지만 운동 많이 될테니 그래도 한번 읽어보는 것을 추천한다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;사실 앞서 말했듯이 모나드는 처음부터 수학자들이 “이런 걸 써라”하고 던져준 것이 아니다. 오히려 공학적인 필요에 의해 안전하게 함수를 합성하는 방법을 찾다 보니, 아래와 같은 도구들이 필연적으로 발명된 것에 가깝다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;발명된 것&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;타입을 받아서 새로운 타입을 만드는 타입 생성자&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;A&gt;&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;A&gt;&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(에타)&lt;/td&gt;
&lt;td&gt;값을 컨테이너에 넣는 연산&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Promise.resolve&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(뮤)&lt;/td&gt;
&lt;td&gt;중첩된 컨테이너를 단일 컨테이너로 펴는 연산&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;flatten&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;그리고 이 연산들을 우리가 안전하게 사용하기 위해서는 앞서 살펴본 세 가지 법칙(결합, 좌단위, 우단위)을 지켜야 한다고 했다. 이제 이 구조를 수학적으로 분석해 보면 아주 흥미로운 지점에 도달하게 된다.&lt;/p&gt;
&lt;h3 id=&quot;범주category-대상과-화살표의-세계&quot; style=&quot;position:relative;&quot;&gt;범주(Category): 대상과 화살표의 세계&lt;a href=&quot;#%EB%B2%94%EC%A3%BCcategory-%EB%8C%80%EC%83%81%EA%B3%BC-%ED%99%94%EC%82%B4%ED%91%9C%EC%9D%98-%EC%84%B8%EA%B3%84&quot; aria-label=&quot;범주category 대상과 화살표의 세계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;범주(Category)는 대상(Object)과 대상 사이의 사상(Morphism, 화살표)으로 이루어진 구조다. 필자는 개인적으로 범주보다는 카테고리라는 단어가 더 익숙하므로, 앞으로 카테고리라고 부르도록 하겠다.&lt;/p&gt;
&lt;p&gt;우선 TypeScript 관점에서 가장 친숙한 카테고리는 타입의 카테고리다. 타입의 카테고리에서 대상은 &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;과 같은 타입들이고 사상은 &lt;code class=&quot;language-text&quot;&gt;(a: number) =&gt; string&lt;/code&gt;과 같이 한 대상에서 다른 대상으로 나아가는 계산, 함수이다.&lt;/p&gt;
&lt;p&gt;카테고리와 함자(Functor)에 대한 자세한 내용은 &lt;a href=&quot;/2020/01/27/safety-function-composition/&quot;&gt;이전 포스팅&lt;/a&gt;에 수록되어있으므로, 한번 읽고 오는 것을 추천한다.&lt;/p&gt;
&lt;h3 id=&quot;내부함자endofunctor-같은-세계-안에서-도는-펑터&quot; style=&quot;position:relative;&quot;&gt;내부함자(Endofunctor): 같은 세계 안에서 도는 펑터&lt;a href=&quot;#%EB%82%B4%EB%B6%80%ED%95%A8%EC%9E%90endofunctor-%EA%B0%99%EC%9D%80-%EC%84%B8%EA%B3%84-%EC%95%88%EC%97%90%EC%84%9C-%EB%8F%84%EB%8A%94-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;내부함자endofunctor 같은 세계 안에서 도는 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;그렇다면 모나드의 정의 중 “내부함자 범주의…”라는 것은 결국 내부함자(Endofunctor)로 이루어진 카테고리라는 의미이다.&lt;/p&gt;
&lt;p&gt;이전 포스팅에 간단하게 적어놓았지만 함자, 즉 펑터는 어떤 카테고리를 다른 카테고리로 나아가게 만들어주는 사상이다. 일반적인 펑터는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 다른 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 매핑하지만, 내부함자, 엔도펑터는 출발지와 도착지가 같은 범주인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T: C \to C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;왜 모나드는 “내부함자 카테고리”의 대상인 것일까? 그 이유는 우리가 프로그래밍 세계 안에서 사용하는 펑터는 결국 프로그래밍 세계에서만 돌고 있기 때문이다. 예를 들어 펑터의 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; 연산을 한번 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; map&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maybe&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Maybe&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 타입 시그니처를 보면 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; 함수는 &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt;를 받아 &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt;로 나아가는 것을 볼 수 있다. 중요한 점은 &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt;도 결국 타입스크립트의 타입 시스템에 있는 타입이고, 결과 타입인 &lt;code class=&quot;language-text&quot;&gt;Maybe&amp;lt;B&gt;&lt;/code&gt;도 타입스크립트의 타입 시스템에 있는 타입이라는 것이다.&lt;/p&gt;
&lt;p&gt;즉, 타입의 세계에서 타입의 세계로 향한다. 이것이 프로그래밍에서 사용하는 펑터가 엔도펑터(내부함자)인 이유이다. 다른 세계로 가는 것이 아니라 같은 세계 안에서 변환하기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;내부함자-범주-펑터들-자체가-대상인-세계&quot; style=&quot;position:relative;&quot;&gt;내부함자 범주: 펑터들 자체가 대상인 세계&lt;a href=&quot;#%EB%82%B4%EB%B6%80%ED%95%A8%EC%9E%90-%EB%B2%94%EC%A3%BC-%ED%8E%91%ED%84%B0%EB%93%A4-%EC%9E%90%EC%B2%B4%EA%B0%80-%EB%8C%80%EC%83%81%EC%9D%B8-%EC%84%B8%EA%B3%84&quot; aria-label=&quot;내부함자 범주 펑터들 자체가 대상인 세계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;자 그럼 이제 추상화를 한 단계 올려보자. 프로그래밍에서 사용하는 펑터들이 엔도펑터라는 사실을 알았다면 이제는 엔도펑터들 자체를 대상으로 놓는 새로운 카테고리를 생각할 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;일반 타입 카테고리&lt;/th&gt;
&lt;th&gt;엔도펑터 카테고리&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대상&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;, …&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;, …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사상&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;(a: A) =&gt; B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;펑터 → 펑터&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;카테고리의 사상은 어떠한 대상에서 다른 대상으로 나아가는 것이니, 엔도펑터 카테고리에서의 사상은 펑터에서 다른 펑터로 나아가는 것이라고 생각해볼 수 있다.&lt;/p&gt;
&lt;p&gt;그리고 이렇게 펑터를 다른 펑터로 바꾸는 사상을 우리는 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EC%97%B0_%EB%B3%80%ED%99%98&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;자연 변환(Natural Transformation)&lt;/a&gt;이라고 부른다.&lt;/p&gt;
&lt;h3 id=&quot;모노이드monoid-대상-합치기의-대수학&quot; style=&quot;position:relative;&quot;&gt;모노이드(Monoid) 대상: 합치기의 대수학&lt;a href=&quot;#%EB%AA%A8%EB%85%B8%EC%9D%B4%EB%93%9Cmonoid-%EB%8C%80%EC%83%81-%ED%95%A9%EC%B9%98%EA%B8%B0%EC%9D%98-%EB%8C%80%EC%88%98%ED%95%99&quot; aria-label=&quot;모노이드monoid 대상 합치기의 대수학 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;여기까지 모나드의 정의 중 “내부함자 범주의…”라는 내용을 살펴봤다면, 이제 “모노이드 대상이다”라는 말이 어떤 의미인지 살펴보자.&lt;/p&gt;
&lt;p&gt;수학에서 모노이드라는 것은 다음 세 가지를 갖춘 구조를 의미한다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;집합 또는 대상들의 모임&lt;/li&gt;
&lt;li&gt;이항 연산: 두 원소를 합쳐서 같은 집합 안에 들어있는 원소를 만든다. 반드시 결합 법칙을 만족해야한다.&lt;/li&gt;
&lt;li&gt;항등원: 어떤 원소와 연산해도 그 원소를 그대로 반환하는 특별한 원소.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;개념이 워낙 추상적이라 조금 어렵게 느껴질 수 있지만 막상 예시를 그렇게 복잡하지 않다. 가장 대표적인 모노이드는 정수와 덧셈의 관계이다.&lt;/p&gt;
&lt;p&gt;정수와 덧셈에서 덧셈은 정수 집합의 두 원소를 뽑아와 연산하면 정수 집합의 원소를 다시 반환한다. 마치 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1 + 2 = 3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;처럼 말이다. 그리고 이미 독자 분들도 알다시피 덧셈은 결합 법칙을 만족한다. 그리고 마지막으로 어떤 정수와 더해도 그 정수를 그대로 반환하는 녀석인 항등원은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p&gt;이러한 이유로 정수와 덧셈을 묶은 세트는 “모노이드”라고 부를 수 있는 것이고 수학적으로는 정수 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;Z&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbb{Z}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6889em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;Z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;과 덧셈 기호를 묶어 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;Z&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(\mathbb{Z}, +)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;Z&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라고 표기한다. &lt;small&gt;(정확하게는 덧셈에 대한 정수군에는 역원도 존재하지만, 이 설명에서 중요한 것은 아니니 넘어가겠다)&lt;/small&gt;&lt;/p&gt;
&lt;h3 id=&quot;연결점-모나드는-내부함자-범주의-모노이드-대상&quot; style=&quot;position:relative;&quot;&gt;연결점: 모나드는 내부함자 범주의 모노이드 대상&lt;a href=&quot;#%EC%97%B0%EA%B2%B0%EC%A0%90-%EB%AA%A8%EB%82%98%EB%93%9C%EB%8A%94-%EB%82%B4%EB%B6%80%ED%95%A8%EC%9E%90-%EB%B2%94%EC%A3%BC%EC%9D%98-%EB%AA%A8%EB%85%B8%EC%9D%B4%EB%93%9C-%EB%8C%80%EC%83%81&quot; aria-label=&quot;연결점 모나드는 내부함자 범주의 모노이드 대상 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;자 모노이드가 무엇인지 이해했다면 이제 드디어 “내부함자 범주의 모노이드 대상”이 무슨 뜻인지를 이해할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;일단 내부함자(Endofunctor) 범주는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;와 같은 프로그래밍에서의 펑터들로 이루어진 카테고리를 의미하니, 이 친구들이 모노이드 구조를 갖춘 대상이 맞는지를 살펴보면 될 것 같다.&lt;/p&gt;
&lt;p&gt;앞서 언급했던 대표적인 모노이드인 정수 집합과 덧셈의 관계, 그리고 엔도펑터와 합성 연산 간의 관계를 비교해보자.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;모노이드 요소&lt;/th&gt;
&lt;th&gt;정수 덧셈&lt;/th&gt;
&lt;th&gt;내부함자 범주&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;이항 연산&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;+&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1 + 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;합성 &lt;code class=&quot;language-text&quot;&gt;∘&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;연산의 결과&lt;/td&gt;
&lt;td&gt;정수&lt;/td&gt;
&lt;td&gt;내부함자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;항등원&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;항등 함자 &lt;code class=&quot;language-text&quot;&gt;Id&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이렇게 비교해보니 얼추 비슷해보이긴 한다. 하지만 문제가 하나 있는데, 바로 엔도펑터들의 이항 연산인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 결과는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(A)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 아니라 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T(T(A))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;처럼 중첩된 결과라는 것이다. 즉, 같은 집합 안에 있는 원소가 아니다.&lt;/p&gt;
&lt;p&gt;여기서 바로 아까 정의한 모나드의 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)과 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)가 등장한다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;표현&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;두 겹의 T를 하나의 T로 합치는 자연변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;Id&lt;/mtext&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{Id} \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;항등 함자에서 T로 가는 자연변환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;자연변환이란 펑터 사이의 “구조를 보존하는 변환”이다. &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;가 단순히 값을 컨테이너에 넣는 녀석이 아니라 자연변환이라는 점이 중요하다. 이는 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;가 어떤 타입 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 대해서든 일관된 방식으로 동작해야 함을 의미한다. 즉, 타입에 따라 동작이 달라지면 안 된다.&lt;/p&gt;
&lt;p&gt;그리고 앞서 살펴봤던 모나드의 법칙들을 다시 살펴보면, 이 법칙들이 모노이드가 요구하는 결합 법칙과 항등원에 대한 법칙을 만족한다는 사실을 알 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;법칙&lt;/th&gt;
&lt;th&gt;표현&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;결합 법칙&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\mu = \mu \circ \mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;어떤 순서로 합치든 같다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;단위 법칙&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\eta = id = \mu \circ \eta T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;넣었다 빼면 원래대로 돌아온다. 즉, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 항등원이다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이처럼 우리가 프로그래밍에서 연산의 결과를 일관되게 보장하기 위해 세웠던 법칙들이 모노이드가 요구하는 것들과 정확하게 일치하는 것을 볼 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;정수의 모노이드&lt;/th&gt;
&lt;th&gt;내부함자 범주의 모노이드 (= 모나드)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대상&lt;/td&gt;
&lt;td&gt;정수&lt;/td&gt;
&lt;td&gt;내부함자 (&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;, …)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이항 연산&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;+&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T \circ T \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;항등원&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt; (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;Id&lt;/mtext&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\text{Id} \Rightarrow T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;결합 법칙&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(a+b)+c = a+(b+c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ T\mu = \mu \circ \mu T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;단위 법칙&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0+n = n = n+0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;id&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;μ&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mu \circ \eta T = \text{id} = \mu \circ T\eta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;μ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;η&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;즉 이러한 이유들로 인해 우리가 프로그래밍에서 사용하는 모나드를 “내부함자 범주의 모노이드 대상이다”라고 말할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 언급했듯이 이 정의는 우리가 프로그래밍에서 모나드를 사용하게 된 이유가 아니다. 우리는 그저 “효과가 있는 계산을 순차적으로 합성하고 싶다”라는 실용적이고 공학적인 필요성에서 출발해서  &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;pure&lt;/code&gt;를 발명했을 뿐인데, 그것이 마침 수학자들이 이미 알고 있던 “모노이드”라는 구조와 정확하게 일치했던 것이다.&lt;/p&gt;
&lt;h2 id=&quot;사실-모나드는-박스가-아니다&quot; style=&quot;position:relative;&quot;&gt;사실 모나드는 박스가 아니다&lt;a href=&quot;#%EC%82%AC%EC%8B%A4-%EB%AA%A8%EB%82%98%EB%93%9C%EB%8A%94-%EB%B0%95%EC%8A%A4%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;사실 모나드는 박스가 아니다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;우리는 지금까지 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;라는 구체적인 예시를 통해 모나드의 원리를 파헤쳤다. 하지만 실무에서 모나드를 다룰 때는 단순히 코드를 구현하는 것보다, 이 도구가 담고 있는 맥락을 이해하고 기존 도구들과의 차이를 인지하는 것이 훨씬 중요하다.&lt;/p&gt;
&lt;p&gt;지금까지 많은 모나드 설명 포스팅들이 펑터와 모나드를 박스에 비유해서 설명했고 필자도 그렇게 설명을 했었지만, 사실 이 비유는 직관적이기는 하나 모나드의 정체성을 절반만 설명할 뿐이다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;와 같은 녀석을 단순히 “미래의 값이 담긴 박스”로만 본다면, 왜 &lt;code class=&quot;language-text&quot;&gt;then&lt;/code&gt;이 순차적으로 실행되어야 하는지 설명하기 어렵다. 그래서 펑터나 모나드는 단순한 박스라기보다 “특정 효과가 수반되는 계산의 맥락”이라고 표현하는 것이 적합하다.&lt;/p&gt;
&lt;p&gt;따라서 모나드의 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;이 하는 일도 단순히 박스를 까서 펼치는 것이 아니라, 서로 다른 맥락을 가진 계산들을 안전하게 이어 붙이는 것에 가깝다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;모나드&lt;/th&gt;
&lt;th&gt;담고 있는 맥락(Effect)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;값이 없을 수도 있다는 맥락&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;실패의 이유(에러)를 포함한 맥락&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;시간이 걸리는 비동기 계산의 맥락&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;여러 개의 결과가 존재할 수 있는 비결정적 맥락&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;추가적으로 한 가지 더 짚고 넘어가자면 우리는 &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;에 대해 다시 바라볼 필요가 있다. 코드 상에서 &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;는 매우 모나딕하게 작동하지만 엄밀한 수학적 잣대를 들이대면 모나드가 아니다.&lt;/p&gt;
&lt;p&gt;모나드는 구조를 보존하는 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;과 구조를 펴는 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;이 엄격히 구분되어야 하는데, Promise의 then은 반환값에 따라 이 둘을 적당히 섞어서 처리해버리기 때문이다.&lt;/p&gt;
&lt;p&gt;또한 수학적 모나드는 이중으로 겹쳐진 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟨&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟨&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟩&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;⟩&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T\langle T\langle A \rangle \rangle&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;⟨&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;⟨&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;⟩⟩&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 상태가 존재해야 하지만, Promise는 런타임 수준에서 이를 허용하지 않고 즉시 단일 계층으로 뭉쳐버린다. 물론 이러한 설계가 실무적인 편의성을 주긴 하지만, 수학적 엄밀함이 주는 예측 가능성과는 어느 정도 거리가 있는 셈이다.&lt;/p&gt;
&lt;p&gt;따라서 &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;는 엄밀하게 이야기하자면 모나드라고 할 수 없다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이렇게 펑터부터 시작해서 어플리케이티브 펑터, 모나드까지 긴 여정을 마쳤다.&lt;/p&gt;
&lt;p&gt;돌이켜보면 이 긴 여정은 “어떻게 하면 안전하게 함수를 합성할 수 있을까?”라는 지극히 공학적인 질문에서 시작되었다. 우리는 펑터의 한계를 넘기 위해 &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;를 만났고, 중첩되는 맥락을 해결하기 위해 &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;을 발명했다. 그리고 우리가 만든 이 도구들이 사실 수학자들이 수백 년 전부터 연구해온 ‘내부함자 범주의 모노이드 대상’이라는 견고한 구조와 일치한다는 사실도 발견할 수 있었다.&lt;/p&gt;
&lt;p&gt;이러한 발견이 우리에게 주는 진짜 가치는 바로 우리가 작성하는 코드들의 합성 가능성에 대한 수학적 확신이다. 결합 법칙과 단위 법칙을 통해 맥락에 진입하는 입구가 중립적임을 신뢰할 수 있고, 결합 법칙을 통해서는 어떤 레이어에서 리팩토링을 하던 결과가 같다는 것을 보장받을 수 있다. 그리고 이러한 신뢰가 쌓여야 우리가 작은 맥락 조각들을 이어붙여가며 거대하고 복잡한 비즈니스 로직을 구축해나갈 수 있다.&lt;/p&gt;
&lt;p&gt;결국 모나드를 이해한다는 것은 추상적인 맥락을 다루는 법을 배우고 우리가 작성하는 소프트웨어에 수학적인 질서를 부여하여 코드에 대한 확신을 얻는 과정이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;필자도 나름 모나드를 설명해보겠다고 발버둥을 쳐봤는데, 솔직히 이 글의 난이도가 쉬운 것인지 어려운 것인지 전혀 가늠이 안된다.&lt;/p&gt;
&lt;p&gt;혹시라도 추가적인 궁금증이 있는 분들은 필자의 이메일을 통해 질문을 남겨주시면 최대한 설명을 해드릴테니 많은 함수형 프로그래밍 러버들의 관심과 사랑을 부탁드린다.&lt;/p&gt;
&lt;p&gt;이상으로 펑터를 넘어서, 모나드까지 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Why Do We Feel Some Code Is Easier to Read?]]></title><description><![CDATA[I previously wrote a post called “What Is Good Code? On the Illusion of Readability” where I discussed how subjective and context-dependent the formula “good code = readable code” really is. The conclusion that people judge readability differently is fair enough. But if you trace the mechanics behind it, where that sense of “this is easy to read” actually comes from, you start to find some hints.]]></description><link>https://evan-moon.github.io/2026/01/30/developer-intuition-readable-code-and-neuroscience/en/</link><guid isPermaLink="false">20260130-developer-intuition-readable-code-and-neuroscience-en</guid><pubDate>Fri, 30 Jan 2026 19:47:00 GMT</pubDate><content:encoded>&lt;p&gt;I previously wrote a post called &lt;a href=&quot;/2024/12/23/the-illusion-of-a-right-answer/&quot;&gt;“What Is Good Code? On the Illusion of Readability”&lt;/a&gt; where I discussed how subjective and context-dependent the formula “good code = readable code” really is.&lt;/p&gt;
&lt;p&gt;The conclusion that people judge readability differently is fair enough. But if you trace the mechanics behind it, where that sense of “this is easy to read” actually comes from, you start to find some hints.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;So that’s what this post is about. How humans understand code, and what makes certain forms of information feel easier to process.&lt;/p&gt;
&lt;h2 id=&quot;what-happens-in-the-brain-when-we-read-code&quot; style=&quot;position:relative;&quot;&gt;What Happens in the Brain When We Read Code&lt;a href=&quot;#what-happens-in-the-brain-when-we-read-code&quot; aria-label=&quot;what happens in the brain when we read code permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://doi.org/10.7554/eLife.58906&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;2020 fMRI study at MIT&lt;/a&gt; looked at which brain regions light up when programmers read code.&lt;/p&gt;
&lt;p&gt;It turns out code reading primarily activates the Multiple Demand Network, the region for logical reasoning and complex cognitive tasks, not the language network. The language regions weren’t completely uninvolved, but the Multiple Demand Network response was dominant.&lt;/p&gt;
&lt;p&gt;Put simply, when our brains read code, they rely more on logical reasoning than language processing.&lt;/p&gt;
&lt;p&gt;Five brain regions related to working memory, attention, and language processing showed pronounced activation during code comprehension, while Default Mode Network activity (the regions active when the brain is resting) decreased. Reading code is a fairly expensive operation for the brain.&lt;/p&gt;
&lt;p&gt;So far, this might seem unsurprising. But the more interesting part is the difference between experts and novices. Skilled developers showed lower overall brain activation levels when reading code. Not because they were trying less, but because they were processing more efficiently. Novice developers showed widespread brain activation, meaning they were consciously processing nearly everything one piece at a time.&lt;/p&gt;
&lt;p&gt;Novices tended to read code like natural language text, top to bottom. Experts followed the program’s execution flow. Same code, fundamentally different processing.&lt;/p&gt;
&lt;h2 id=&quot;working-memory-4-slots&quot; style=&quot;position:relative;&quot;&gt;Working Memory: 4 Slots&lt;a href=&quot;#working-memory-4-slots&quot; aria-label=&quot;working memory 4 slots permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To understand why some code reads easily while other code refuses to organize itself in your head, you need to know about working memory.&lt;/p&gt;
&lt;p&gt;In 1956, cognitive psychologist George A. Miller published &lt;a href=&quot;https://doi.org/10.1037/h0043158&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;“The Magical Number Seven, Plus or Minus Two”&lt;/a&gt;, showing that human short-term memory capacity is roughly 7±2 items. Later research revised this downward. &lt;a href=&quot;https://doi.org/10.1017/s0140525x01003922&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Cowan (2001)&lt;/a&gt; found the number of chunks you can hold in working memory at once is closer to 3–4. It varies by task and expertise, but either way, it’s smaller than you’d think.&lt;/p&gt;
&lt;p&gt;Think about what we load into our heads when reading code. The current value of a variable, the direction of control flow, the order of function calls, the state of the current scope… all of these occupy working memory slots. When those slots fill up, the brain struggles to take in new information. That’s the moment you get that “this code feels complicated” sensation.&lt;/p&gt;
&lt;p&gt;To put it in programming terms, working memory is like a fixed-size stack.&lt;/p&gt;
&lt;p&gt;Real working memory is a far more complex system than a stack, but the analogy works well enough: there’s a capacity limit, and exceeding it causes things to break down. The stack size is roughly 4, and exceeding it causes a stack overflow. In practice, the items occupying each slot aren’t uniform in size, and interference between items also occurs, so the exact number matters less than the fact that capacity is limited. The moment that capacity hits its limit is when you feel “this code is hard to read.”&lt;/p&gt;
&lt;p&gt;Let’s compare code that rapidly exhausts working memory with code that doesn’t.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Code that rapidly exhausts all 4 working memory slots&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pending&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coupon&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domestic &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; finalPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cost&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; finalPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;processed&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function isn’t wrong, but it demands too many things be held in the reader’s working memory simultaneously.&lt;/p&gt;
&lt;p&gt;The condition on &lt;code class=&quot;language-text&quot;&gt;order.status&lt;/code&gt;, the check on &lt;code class=&quot;language-text&quot;&gt;order.items&lt;/code&gt;, the discount branching by &lt;code class=&quot;language-text&quot;&gt;customer.tier&lt;/code&gt;, the null check on the coupon, the domestic/international tax branching, the final price calculation… trying to fit all of this context into 3–4 slots is what makes the brain scream.&lt;/p&gt;
&lt;p&gt;If we can break this context into appropriately sized units, we can save working memory slots needed to understand each operation.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Version that reduces working memory load&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateDiscount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coupon&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shipping&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ShippingInfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domestic &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; amount &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pending&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateDiscount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; finalPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cost&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; finalPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;processed&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this version, the amount you need to hold in your head at each step is noticeably reduced. The behavior is identical, but by breaking information into consistent units, how much context occupies each working memory slot becomes manageable.&lt;/p&gt;
&lt;p&gt;When reading &lt;code class=&quot;language-text&quot;&gt;calculateDiscount&lt;/code&gt;, you only need to focus on discount logic. When reading &lt;code class=&quot;language-text&quot;&gt;processOrder&lt;/code&gt;, you can follow the overall flow without knowing each calculation’s internals. Each function fits within working memory’s capacity, which is why it feels easier to understand. This is also why abstraction at the right granularity matters in design. Of course, the reverse is true too. Splitting things too finely means you spend working memory jumping between functions and tracking context. The goal isn’t splitting for its own sake, but reducing how much you need to hold in your head at once.&lt;/p&gt;
&lt;h2 id=&quot;chunking-the-brains-data-compression-algorithm&quot; style=&quot;position:relative;&quot;&gt;Chunking: The Brain’s Data Compression Algorithm&lt;a href=&quot;#chunking-the-brains-data-compression-algorithm&quot; aria-label=&quot;chunking the brains data compression algorithm permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But if working memory only has about 4 slots, how do we comprehend hundreds of lines of code?&lt;/p&gt;
&lt;p&gt;The answer is chunking: grouping multiple small units of information into a single meaningful cluster. &lt;a href=&quot;https://doi.org/10.5334/joc.451&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Research from the University of Zurich&lt;/a&gt; found that chunking reduces working memory load by swapping individual elements for compressed representations pulled from long-term memory. The freed-up capacity then goes to processing new incoming information.&lt;/p&gt;
&lt;p&gt;Think about phone numbers. Trying to remember &lt;code class=&quot;language-text&quot;&gt;01012345678&lt;/code&gt; as eleven individual digits would far exceed working memory capacity. But split it as &lt;code class=&quot;language-text&quot;&gt;010-1234-5678&lt;/code&gt;, and you only need to remember three chunks. Better yet, if &lt;code class=&quot;language-text&quot;&gt;010&lt;/code&gt; is already familiar as “Korean mobile prefix,” it’s automatically processed as a single chunk, meaning you really only need to memorize two new chunks.&lt;/p&gt;
&lt;p&gt;The same thing happens with code. Look at what happens when a skilled developer reads this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; activeUsers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isActive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A novice developer has to load each individual element into working memory: the &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; variable, how &lt;code class=&quot;language-text&quot;&gt;.filter&lt;/code&gt; works, arrow function syntax, the &lt;code class=&quot;language-text&quot;&gt;u.isActive&lt;/code&gt; property access, how &lt;code class=&quot;language-text&quot;&gt;.map&lt;/code&gt; works, another arrow function…&lt;/p&gt;
&lt;p&gt;For a skilled developer, &lt;code class=&quot;language-text&quot;&gt;users.filter(...).map(...)&lt;/code&gt; is recognized as a single chunk: “filter array then transform.” Having seen this pattern hundreds or thousands of times, they pull a stored chunk from long-term memory and use just one working memory slot. The remaining slots can be allocated to higher-level thinking like “why is this being filtered?” or “where does the result get used?”&lt;/p&gt;
&lt;p&gt;This is the same principle that allows chess masters to glance at a board and grasp the entire situation. Chess masters don’t memorize individual piece positions one by one. They recognize familiar formation patterns as single chunks. That’s why they can quickly recall meaningfully arranged boards but perform no better than novices with randomly placed pieces.&lt;/p&gt;
&lt;p&gt;Code works the same way. Idiomatic code is easy to read not because it’s “correct,” but because it matches chunks already stored in the developer’s long-term memory.&lt;/p&gt;
&lt;p&gt;What makes a pattern idiomatic is shaped by external factors: the language’s design intent, standard library conventions, the community’s repeated choices. It’s not simply “familiar because it’s used a lot.” Convergence driven by multiple forces created that familiarity. This is also why project-specific unique patterns or overly creative code are hard to read. When existing chunks don’t match, the brain has to decompose everything into individual elements, and working memory saturates almost instantly.&lt;/p&gt;
&lt;h2 id=&quot;system-1-and-system-2-intuition-and-analysis&quot; style=&quot;position:relative;&quot;&gt;System 1 and System 2: Intuition and Analysis&lt;a href=&quot;#system-1-and-system-2-intuition-and-analysis&quot; aria-label=&quot;system 1 and system 2 intuition and analysis permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is where Daniel Kahneman’s dual process theory comes in. Kahneman divided human thinking into two systems:&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System 1&lt;/strong&gt;: Fast, automatic, intuitive thinking. Based on pattern recognition.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System 2&lt;/strong&gt;: Slow, conscious, analytical thinking. Based on logical reasoning.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Most of our everyday judgments are handled by System 1. Driving a car, sensing your partner’s mood from a single word over the phone. When encountering new information, System 1 doesn’t create new patterns; it matches against patterns already stored.&lt;/p&gt;
&lt;p&gt;When System 1 gets stuck, that’s when System 2 gets called in. The moment you consciously think “what is this?” and start analyzing, that’s System 2 engaging. Apply this framework to code reading, and a lot starts to make sense.&lt;/p&gt;
&lt;p&gt;Readable code is code that’s mostly processed by System 1’s pattern recognition, with minimal System 2 involvement.&lt;/p&gt;
&lt;p&gt;When skilled developers read code, familiar patterns are handled automatically by System 1. &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops, &lt;code class=&quot;language-text&quot;&gt;if-else&lt;/code&gt; branches, &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;reduce&lt;/code&gt; chaining, &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; blocks. These have been seen thousands of times, so they’re processed without conscious effort. System 2 stays in a comfortable low-power mode, just approving the information that System 1 surfaces.&lt;/p&gt;
&lt;p&gt;But when an unexpected pattern appears, things change.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Code that System 1 can handle&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canPurchase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isVerified&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Code that invokes System 2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canPurchase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isVerified&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both express the same intent. But the moment you see the second version, System 1 sends an “I don’t know” signal, and System 2 begins its expensive analysis. You have to unwind the double negation, run De Morgan’s law in your head, and figure out why that final &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; check is necessary. This transition itself is a cognitive cost.&lt;/p&gt;
&lt;p&gt;Kahneman called this cognitive strain. The more System 2 has to step in, the more energy the brain burns and the more fatigued you feel. The “this code is hard to read” sensation is the cognitive cost of System 1 failing to match a pattern and handing things off to System 2.&lt;/p&gt;
&lt;p&gt;From this angle, feedback like “this is hard to understand” in code reviews isn’t just taste. It’s closer to a signal that system-switching costs are actually occurring. The magnitude varies by individual experience and chunk composition, but the cost itself is real.&lt;/p&gt;
&lt;h2 id=&quot;gestalt-principles-how-visual-structure-affects-code-comprehension&quot; style=&quot;position:relative;&quot;&gt;Gestalt Principles: How Visual Structure Affects Code Comprehension&lt;a href=&quot;#gestalt-principles-how-visual-structure-affects-code-comprehension&quot; aria-label=&quot;gestalt principles how visual structure affects code comprehension permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Readable code depends on visual structure too, not just logical structure. This is where Gestalt psychology comes in.&lt;/p&gt;
&lt;p&gt;Gestalt psychology studies how the brain prioritizes overall patterns and structures over individual elements. A few of its principles connect directly to code readability.&lt;/p&gt;
&lt;h3 id=&quot;law-of-proximity&quot; style=&quot;position:relative;&quot;&gt;Law of Proximity&lt;a href=&quot;#law-of-proximity&quot; aria-label=&quot;law of proximity permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Elements that are close together are perceived as a group. Let’s look at two versions of the same code to see why this grouping matters.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Code without proximity principle applied&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; role &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determineRole&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permissions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dashboard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; notifications &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNotifications&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Code with proximity principle applied&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; role &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determineRole&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permissions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dashboard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; notifications &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNotifications&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The second version just adds a single blank line, yet the brain automatically recognizes two groups: “user info processing” and “permission-based data retrieval.”&lt;/p&gt;
&lt;p&gt;Gestalt research shows that proximity is an even stronger grouping cue than similarity of color or shape. UI design uses this directly: related information goes close together, unrelated information gets spaced apart.&lt;/p&gt;
&lt;p&gt;Similarly, blank lines and indentation matter in code not just for aesthetics, but because the brain’s perceptual system uses them to parse structure.&lt;/p&gt;
&lt;h3 id=&quot;law-of-similarity&quot; style=&quot;position:relative;&quot;&gt;Law of Similarity&lt;a href=&quot;#law-of-similarity&quot; aria-label=&quot;law of similarity permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Like proximity, elements that look alike are also perceived as belonging to the same group. This explains why consistent naming matters in code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Naming that violates similarity&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; get_orders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;retrieveOrderList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pmtHistory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadPayments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;uid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Naming that follows similarity&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; orders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchOrders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchPayments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the first version, all three are the same kind of operation (data fetching), but the naming conventions are all over the place. &lt;code class=&quot;language-text&quot;&gt;userData&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;get_orders&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;pmtHistory&lt;/code&gt; each have different forms, and &lt;code class=&quot;language-text&quot;&gt;fetchUser&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;retrieveOrderList&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;loadPayments&lt;/code&gt; lack any consistency. The brain can’t recognize these as the same group and processes each line as a separate item, consuming working memory.&lt;/p&gt;
&lt;p&gt;In the second version, the pattern is clear. The consistent &lt;code class=&quot;language-text&quot;&gt;fetch + resourceName&lt;/code&gt; structure causes all three lines to be recognized as a single chunk: “data fetching in the same pattern.”&lt;/p&gt;
&lt;h3 id=&quot;law-of-continuity&quot; style=&quot;position:relative;&quot;&gt;Law of Continuity&lt;a href=&quot;#law-of-continuity&quot; aria-label=&quot;law of continuity permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The law of continuity states that we perceive elements as a single continuous entity when they follow a natural flow of direction. In code, this relates to the linearity of execution flow.&lt;/p&gt;
&lt;p&gt;Our brains find top-to-bottom, left-to-right flow natural. Deep nesting, complex callbacks, and scattered &lt;code class=&quot;language-text&quot;&gt;goto&lt;/code&gt; statements are hard to read because they violate the law of continuity.&lt;/p&gt;
&lt;p&gt;This is also why early return patterns feel easier to read than nested &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statements. Once edge cases are filtered out, the remaining code flows in a single direction from top to bottom.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Code that breaks continuity&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isActive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inStock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onSale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;salePrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Out of stock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Inactive user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Code that maintains continuity&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isActive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Inactive user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inStock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Out of stock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onSale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;salePrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first version forces your eyes to zigzag right and left as indentation deepens. The brain has to maintain “which condition am I currently inside” in working memory at each nesting level.&lt;/p&gt;
&lt;p&gt;The second version filters out exceptions first, then flows naturally from top to bottom. Because it aligns with the law of continuity, the cost for the brain to parse the structure drops significantly.&lt;/p&gt;
&lt;h2 id=&quot;cognitive-load-theory-three-types-of-load&quot; style=&quot;position:relative;&quot;&gt;Cognitive Load Theory: Three Types of Load&lt;a href=&quot;#cognitive-load-theory-three-types-of-load&quot; aria-label=&quot;cognitive load theory three types of load permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;John Sweller’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Cognitive_load&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Cognitive Load Theory&lt;/a&gt; gives a more systematic framework for everything above.&lt;/p&gt;
&lt;p&gt;It breaks cognitive load during learning or problem-solving into three types:&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Intrinsic load&lt;/strong&gt;: The inherent complexity of the task itself. Algorithm difficulty, domain complexity, and so on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extraneous load&lt;/strong&gt;: Unnecessary complexity from presentation that’s irrelevant to the task. Inconsistent naming, unnecessary indirection, confusing code structure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Germane load&lt;/strong&gt;: The beneficial load spent forming and learning new schemas.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;The takeaway for writing readable code: minimize extraneous load.&lt;/p&gt;
&lt;p&gt;Intrinsic load can’t be reduced. It’s inherent to the problem. Code implementing a distributed consensus algorithm will be complex no matter how well it’s written. The problem is when extraneous load from “how it’s expressed” piles unnecessarily on top of intrinsic load.&lt;/p&gt;
&lt;p&gt;From this perspective, consistent naming, appropriate function decomposition, clear type declarations, meaningful blank lines: these all reduce extraneous cognitive load. They keep the brain’s limited resources from being wasted on presentation issues so you can focus on the actual problem.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://doi.org/10.1016/j.jss.2023.111619&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;2023 systematic literature review&lt;/a&gt; found something interesting here. Among studies comparing source code metrics to measured cognitive load, few traditional metrics showed consistent correlation with what developers actually experienced. Results varied depending on task conditions and measurement methods. What we “measure” as complexity and what a developer’s brain “feels” as complex can be quite different.&lt;/p&gt;
&lt;p&gt;Mechanical metrics capture surface-level complexity, but the cognitive load you actually experience depends on how familiar the patterns are, how efficiently your brain chunks them, how clearly the visual structure maps to the logic. These are subjective factors that no metric fully captures.&lt;/p&gt;
&lt;h2 id=&quot;experience-physically-changes-the-brain&quot; style=&quot;position:relative;&quot;&gt;Experience Physically Changes the Brain&lt;a href=&quot;#experience-physically-changes-the-brain&quot; aria-label=&quot;experience physically changes the brain permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I mentioned earlier that expert and novice brain activation patterns differ. This isn’t just “more experience = better.” A &lt;a href=&quot;https://www.nature.com/articles/s41598-024-56090-6&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;2024 study in Scientific Reports&lt;/a&gt; measured brainwaves from 62 Python programmers while showing them code with intentionally inserted syntax errors and semantic errors.&lt;/p&gt;
&lt;p&gt;Skilled programmers showed distinct brainwave patterns for syntax violations versus semantic violations, the same way our brains produce different responses to grammatical errors versus meaning errors in natural language. Programming experience forms specialized neural circuits for processing specific languages and patterns.&lt;/p&gt;
&lt;p&gt;Coding experience physically changes the brain. Through neuroplasticity, patterns you encounter repeatedly get stored as schemas in long-term memory, and these schemas become the foundation for chunking. System 1 can automatically process code because these schemas have accumulated over time.&lt;/p&gt;
&lt;p&gt;Because schemas form based on the patterns an individual has been exposed to, people who repeatedly encounter the same patterns in the same codebase end up sharing similar schemas. Flip this around, and maintaining a consistent code style within a team isn’t about taste. It’s the process of forming shared chunks in team members’ brains. Coding conventions matter not for uniformity’s sake, but for collective cognitive efficiency.&lt;/p&gt;
&lt;h2 id=&quot;predictive-coding-the-brain-doesnt-read-code-it-predicts&quot; style=&quot;position:relative;&quot;&gt;Predictive Coding: The Brain Doesn’t Read Code, It Predicts&lt;a href=&quot;#predictive-coding-the-brain-doesnt-read-code-it-predicts&quot; aria-label=&quot;predictive coding the brain doesnt read code it predicts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Predictive coding theory offers another angle. The brain doesn’t passively receive information. It constantly predicts what will come next and only does extra processing when the actual input differs from its prediction.&lt;/p&gt;
&lt;p&gt;The same applies when reading code. Our brains constantly predict what the next line will be.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/users/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Your brain is already predicting what comes next&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A skilled developer’s brain reading this code is already predicting “it’ll probably parse the response data and return it.” And when &lt;code class=&quot;language-text&quot;&gt;return response.data;&lt;/code&gt; actually appears, the prediction was correct, so virtually no additional cognitive cost is incurred.&lt;/p&gt;
&lt;p&gt;But what if something completely unexpected shows up?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/users/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    globalEventBus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user-fetched&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Wait, what?&lt;/span&gt;
    localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lastUser&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Huh?&lt;/span&gt;
    analytics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;profile_view&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Why is logging here?&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What the brain predicted from the name &lt;code class=&quot;language-text&quot;&gt;fetchUserProfile&lt;/code&gt; was “a function that fetches a user profile and returns it.” But then event bus emission, localStorage writes, and analytics tracking appear, all outside the prediction. Each time, the brain generates a prediction error signal and invokes System 2 to analyze why this code is here.&lt;/p&gt;
&lt;p&gt;The reason the second version feels hard to read is that the function is named &lt;code class=&quot;language-text&quot;&gt;fetchUserProfile&lt;/code&gt;, but internally it does things that have nothing to do with that name. The more closely a name’s set expectation matches the actual behavior, the fewer prediction errors occur and the less cognitive cost is incurred.&lt;/p&gt;
&lt;p&gt;This applies not just within functions but to interface design as well. Let me use component interfaces familiar to frontend developers like myself as an example.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Predictable interface&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TextInput&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;setName&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Enter your name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Hard-to-predict interface&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserNameInput&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;setUser&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;setUser&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Enter your name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first component follows &lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;onChange&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;placeholder&lt;/code&gt;, an interface shared by virtually every input component in the React ecosystem. A developer’s System 1, having encountered this pattern countless times, processes it as “it’s an input component” and moves on.&lt;/p&gt;
&lt;p&gt;The second uses &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;setUser&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;blank&lt;/code&gt;, an interface either tightly coupled to business logic or with unclear meaning. Until you figure out which fields of the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; object it touches internally and when &lt;code class=&quot;language-text&quot;&gt;blank&lt;/code&gt; is actually used, you can’t use it with confidence. You have to look at the internal implementation every time, and each time, prediction errors occur.&lt;/p&gt;
&lt;p&gt;To write readable code, you need to maximize predictability at every level: function names, variable names, file structure, directory organization, API design.&lt;/p&gt;
&lt;h2 id=&quot;so-what-is-good-code-really&quot; style=&quot;position:relative;&quot;&gt;So What Is “Good Code,” Really?&lt;a href=&quot;#so-what-is-good-code-really&quot; aria-label=&quot;so what is good code really permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Putting it all together, “readable code” is code that:&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;Doesn’t exceed working memory (context stays within 3–4 items)&lt;/li&gt;
&lt;li&gt;Matches existing chunks (familiar patterns that activate long-term memory schemas)&lt;/li&gt;
&lt;li&gt;Can be processed by System 1 (understandable through pattern recognition, without invoking System 2)&lt;/li&gt;
&lt;li&gt;Has visual structure that matches its logical structure (Gestalt principles let the brain parse structure automatically)&lt;/li&gt;
&lt;li&gt;Is predictable (doesn’t violate expectations set by names and structure)&lt;/li&gt;
&lt;li&gt;Has low extraneous cognitive load (strips away presentation complexity, leaving only the problem’s inherent complexity)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;Notice something about this list? None of these mean “correct code.”&lt;/p&gt;
&lt;p&gt;Readability and correctness are separate axes. Code can be perfectly correct but impossible to read, and code can be easy to read but wrong. That said, readable code does make bugs easier to find. With lower extraneous load, the brain can focus its resources on finding logical errors.&lt;/p&gt;
&lt;p&gt;There’s one caveat, though. Kahneman also warned about System 1’s biases. System 1 is fast, but that speed comes at the cost of bias. A classic example is familiarity bias. It’s true that you feel patterns familiar to you as “readable code,” but whether that’s objectively optimal is a separate question. A developer fluent in functional programming might find &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops “hard to read,” and vice versa. In those cases, the feeling of “hard to read” may not reflect the code’s objective quality but the bias of chunks stored in your own System 1.&lt;/p&gt;
&lt;p&gt;When giving “this is hard to understand” feedback in code reviews, it’s worth asking yourself once: is this genuinely high-cognitive-load code, or is it simply a pattern not registered in my System 1? If the former, refactoring is needed. If the latter, it might actually be an opportunity to expand your chunk library.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; style=&quot;position:relative;&quot;&gt;Wrapping Up&lt;a href=&quot;#wrapping-up&quot; aria-label=&quot;wrapping up permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“Readable code” isn’t just a matter of feeling or taste. It’s a natural outcome of how our cognitive systems work: limited working memory, chunking, dual process thinking, Gestalt perception, predictive coding.&lt;/p&gt;
&lt;p&gt;The reason I said “readability is subjective” in my previous post comes down to this. Chunking depends on individual experience. The patterns registered in System 1 differ from person to person.&lt;/p&gt;
&lt;p&gt;When two people look at the same code and one finds it easy while the other finds it hard, that’s not just a difference in preference. The schemas accumulated in their brains are different. Readability is inevitably subjective because it’s baked into our cognitive structure.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[우리는 왜 어떤 코드를 읽기 쉽다고 느낄까]]></title><description><![CDATA[이전에 좋은 코드란 무엇일까? - 가독성이란 허상에 대하여라는 글에서, “좋은 코드 = 가독성이 좋은 코드”라는 공식이 얼마나 주관적이고 맥락 의존적인지에 대해 이야기한 적이 있다. 물론 사람마다 가독성이 좋다고 판단하는 결과는 주관적이라고 볼 수 있다. 하지만 가독성이 좋은 코드라는 것이 어떤 원리로 동작하는지, 그 감각은 대체 어디서 오는 것인지를 추적해보다보면 약간은 힌트를 얻을 수 있다.]]></description><link>https://evan-moon.github.io/2026/01/30/developer-intuition-readable-code-and-neuroscience/</link><guid isPermaLink="false">20260130-developer-intuition-readable-code-and-neuroscience</guid><pubDate>Fri, 30 Jan 2026 19:47:00 GMT</pubDate><content:encoded>&lt;p&gt;이전에 &lt;a href=&quot;/2024/12/23/the-illusion-of-a-right-answer/&quot;&gt;좋은 코드란 무엇일까? - 가독성이란 허상에 대하여&lt;/a&gt;라는 글에서, “좋은 코드 = 가독성이 좋은 코드”라는 공식이 얼마나 주관적이고 맥락 의존적인지에 대해 이야기한 적이 있다.&lt;/p&gt;
&lt;p&gt;물론 사람마다 가독성이 좋다고 판단하는 결과는 주관적이라고 볼 수 있다. 하지만 가독성이 좋은 코드라는 것이 어떤 원리로 동작하는지, 그 감각은 대체 어디서 오는 것인지를 추적해보다보면 약간은 힌트를 얻을 수 있다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;그래서 이번 포스팅에서는 바로 그 이야기를 해보려 한다. 인간이 코드를 이해하는 방식, 그리고 어떤 형태의 정보가 이해하기 쉽다고 느끼는지에 대한 이야기이다.&lt;/p&gt;
&lt;h2 id=&quot;코드를-읽을-때-뇌에서는-무슨-일이-일어날까&quot; style=&quot;position:relative;&quot;&gt;코드를 읽을 때 뇌에서는 무슨 일이 일어날까&lt;a href=&quot;#%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9D%BD%EC%9D%84-%EB%95%8C-%EB%87%8C%EC%97%90%EC%84%9C%EB%8A%94-%EB%AC%B4%EC%8A%A8-%EC%9D%BC%EC%9D%B4-%EC%9D%BC%EC%96%B4%EB%82%A0%EA%B9%8C&quot; aria-label=&quot;코드를 읽을 때 뇌에서는 무슨 일이 일어날까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://doi.org/10.7554/eLife.58906&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;MIT에서 2020년에 진행한 기능적 MRI 연구&lt;/a&gt;에서 프로그래머들이 코드를 읽을 때 뇌의 어떤 영역이 활성화되는지를 관찰했는데, 재밌는 결과가 나왔다.&lt;/p&gt;
&lt;p&gt;연구에 따르면 코드를 읽을 때는 언어 네트워크가 아니라 논리 추론과 복잡한 인지 작업을 담당하는 다중 수요 네트워크가 주로 활성화되었다고 한다. 언어 영역의 관여가 완전히 없었던 것은 아니지만, 다중 수요 네트워크의 반응이 지배적이었다.&lt;/p&gt;
&lt;p&gt;쉽게 말해서, 우리 뇌는 코드를 읽을 때 언어 처리보다는 논리적 추론 쪽에 더 크게 의존한다는 뜻이다.&lt;/p&gt;
&lt;p&gt;이 연구에서 확인된 것은 코드 이해 시 작업 기억, 주의 집중, 언어 처리와 관련된 다섯 개의 뇌 영역이 뚜렷하게 활성화된다는 점이다. 동시에 디폴트 모드 네트워크(뇌가 쉬고 있을 때 활성화되는 영역)의 활동은 감소했다. 즉, 코드를 읽는 건 뇌 입장에서 꽤 비싼 작업인 셈이다.&lt;/p&gt;
&lt;p&gt;여기까지는 그러려니 할 수 있겠지만, 더 흥미로운 사실은 바로 전문가와 초보자의 차이에서 나온다. 숙련된 개발자는 코드를 읽을 때 뇌의 전반적인 활성화 수준이 낮았다. 덜 열심히 한 게 아니라, 더 효율적으로 처리한 것이다. 반면 초보 개발자는 뇌의 넓은 영역이 활성화됐는데, 이는 거의 모든 것을 의식적으로 하나씩 처리하고 있다는 뜻이다.&lt;/p&gt;
&lt;p&gt;초보자는 코드를 자연어 텍스트처럼 위에서 아래로 읽는 경향이 있었고, 전문가는 프로그램의 실행 흐름을 따라 읽었다. 같은 코드를 보고 있지만, 뇌가 처리하는 방식 자체가 다른 것이다.&lt;/p&gt;
&lt;h2 id=&quot;작업-기억-4개의-슬롯&quot; style=&quot;position:relative;&quot;&gt;작업 기억: 4개의 슬롯&lt;a href=&quot;#%EC%9E%91%EC%97%85-%EA%B8%B0%EC%96%B5-4%EA%B0%9C%EC%9D%98-%EC%8A%AC%EB%A1%AF&quot; aria-label=&quot;작업 기억 4개의 슬롯 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;왜 어떤 코드는 쉽게 읽히는데 어떤 코드는 머릿속에서 정리가 안 되는지를 이해하려면, 작업 기억이라는 개념을 알아야 한다.&lt;/p&gt;
&lt;p&gt;1956년 인지심리학자 조지 밀러(George A. Miller)가 발표한 유명한 논문 &lt;a href=&quot;https://doi.org/10.1037/h0043158&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;“The Magical Number Seven, Plus or Minus Two”&lt;/a&gt;에서, 인간의 단기 기억 용량이 약 7±2개의 항목이라는 사실이 밝혀졌다. 이후 연구에서는 이 숫자가 더 줄어들어, &lt;a href=&quot;https://doi.org/10.1017/s0140525x01003922&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Cowan(2001)&lt;/a&gt; 등의 견해에 따르면 작업 기억에 동시에 유지할 수 있는 청크는 약 3~4개 수준으로 수렴한다는 주장이 유력하다. 다만 이 수치는 과제의 종류, 숙련도, 정보의 양식에 따라 달라질 수 있다.&lt;/p&gt;
&lt;p&gt;코드를 읽을 때 우리가 머릿속에 올려놓는 것들을 떠올려보자. 변수의 현재 값, 제어 흐름의 방향, 함수 호출 순서, 현재 스코프의 상태 등 다양한 것들이 작업 기억의 슬롯을 차지한다. 그리고 이 슬롯이 꽉 차면, 뇌는 새로운 정보를 받아들이기 어려워는데, 바로 이때 “이 코드 뭔가 복잡한데”라는 느낌이 찾아오는 것이다.&lt;/p&gt;
&lt;p&gt;이걸 개발랭이들이 이해하기 쉬운 프로그래밍적인 비유로 바꿔보면, 작업 기억은 일종의 고정 크기 스택이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;실제 작업 기억은 스택보다 훨씬 복잡한 시스템이지만, “용량에 한계가 있고 초과하면 처리가 무너진다”는 특성을 직관적으로 이해하기에는 나쁘지 않은 비유다. 스택 사이즈가 약 4인데 이걸 초과하면 스택 오버플로우가 나는 것이다. 다만 실제로는 슬롯에 담기는 항목의 크기가 균일하지 않고, 항목 간 간섭도 발생하기 때문에, 숫자 자체보다는 “용량에 한계가 있다”는 사실이 핵심이다. 그리고 이 용량이 한계에 부딪히는 순간이 바로 “이 코드 읽기 어렵다”는 감각이 발생하는 순간이다.&lt;/p&gt;
&lt;p&gt;한번 작업 기억을 빠르게 소진하는 코드와 그렇지 않은 코드를 비교해보며 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 작업 기억 슬롯 4개를 빠르게 소진하는 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pending&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coupon&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domestic &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; finalPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cost&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; finalPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;processed&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 틀린 코드는 아니지만, 읽는 사람의 작업 기억에 동시에 올려야 할 것이 너무 많다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;order.status&lt;/code&gt;의 조건, &lt;code class=&quot;language-text&quot;&gt;order.items&lt;/code&gt;의 존재 여부, &lt;code class=&quot;language-text&quot;&gt;customer.tier&lt;/code&gt;에 따른 할인 분기, 쿠폰의 널 체크, 세금 계산의 국내/해외 분기, 최종 가격 산출 등 이 모든 맥락을 3~4개의 슬롯에 동시에 담으려 하니 뇌가 비명을 지르는 것이다.&lt;/p&gt;
&lt;p&gt;만약 이 맥락을 적절한 단위와 크기로 나눠줄 수 있다면, 어떤 동작을 이해하기 위해 필요한 작업 슬롯을 아낄 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 작업 기억 부담을 줄인 버전&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateDiscount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coupon&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shipping&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ShippingInfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domestic &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; amount &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pending&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateDiscount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; finalPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipping&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cost&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; finalPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;processed&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 버전에서는 각 단계에서 머릿속에 올려야 할 것이 확연하게 줄어든다. 동작 자체는 동일하지만, 정보를 일정한 단위로 패키징함으로서 작업 슬롯에 들어가는 맥락을 제어해주는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;calculateDiscount&lt;/code&gt;를 읽을 때는 할인 로직에만 집중하면 되며, &lt;code class=&quot;language-text&quot;&gt;processOrder&lt;/code&gt;를 읽을 때는 각 계산의 세부 구현을 몰라도 전체 흐름을 이해할 수 있다. 각 함수가 작업 기억의 용량 안에서 소화 가능한 크기이기 때문에 이해가 쉽다고 느껴진다. 그리고 이것이 우리가 설계를 할 때 적절한 단위로 추상화를 해야하는 이유라고도 할 수 있다. 물론 반대로, 지나치게 잘게 쪼개면 함수 간 점프와 맥락 추적에 작업 기억을 소모하게 된다. 분리 자체가 목적이 아니라, 한 번에 머릿속에 올려야 할 양을 줄이는 것이 목적이다.&lt;/p&gt;
&lt;h2 id=&quot;청킹-뇌의-데이터-압축-알고리즘&quot; style=&quot;position:relative;&quot;&gt;청킹: 뇌의 데이터 압축 알고리즘&lt;a href=&quot;#%EC%B2%AD%ED%82%B9-%EB%87%8C%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%95%95%EC%B6%95-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98&quot; aria-label=&quot;청킹 뇌의 데이터 압축 알고리즘 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;그런데 여기서 한 가지 의문이 생긴다. 작업 기억의 슬롯이 겨우 4개라면, 우리는 대체 어떻게 수백 줄의 코드를 이해할 수 있는 걸까?&lt;/p&gt;
&lt;p&gt;답은 청킹이라는 인지 메커니즘에 있다. 청킹이란 여러 개의 작은 정보 단위를 하나의 의미 있는 덩어리로 묶어서 처리하는 것을 말한다. &lt;a href=&quot;https://doi.org/10.5334/joc.451&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;취리히 대학교의 연구&lt;/a&gt;에 따르면, 청킹은 장기 기억에서 압축된 청크 표상을 불러와 개별 요소의 표상을 대체함으로써 작업 기억의 부하를 줄인다. 이로 인해 확보된 용량은 이후에 입력되는 새로운 정보를 처리하는 데 사용된다.&lt;/p&gt;
&lt;p&gt;전화번호를 생각해보자. &lt;code class=&quot;language-text&quot;&gt;01012345678&lt;/code&gt;이라는 11자리 숫자를 한 자리씩 기억하려면 작업 기억의 용량을 한참 초과한다. 그런데 &lt;code class=&quot;language-text&quot;&gt;010-1234-5678&lt;/code&gt;로 나누면 세 덩어리만 기억하면 된다. 더 나아가, 이미 익숙한 &lt;code class=&quot;language-text&quot;&gt;010&lt;/code&gt;은 “한국 휴대폰 번호 앞자리”라는 하나의 청크로 자동 처리되니, 실질적으로 두 덩어리만 새로 기억하면 되는 것이다.&lt;/p&gt;
&lt;p&gt;코드에서도 같은 일이 일어난다. 숙련된 개발자가 아래 코드를 볼 때 일어나는 일을 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; activeUsers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isActive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;초보 개발자는 이걸 읽을 때 &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt;라는 변수, &lt;code class=&quot;language-text&quot;&gt;.filter&lt;/code&gt; 메서드의 동작, 화살표 함수의 문법, &lt;code class=&quot;language-text&quot;&gt;u.isActive&lt;/code&gt;라는 속성 접근, &lt;code class=&quot;language-text&quot;&gt;.map&lt;/code&gt; 메서드의 동작, 또 다른 화살표 함수… 이런 개별 요소들을 하나씩 작업 기억에 올려야 한다.&lt;/p&gt;
&lt;p&gt;반면 숙련된 개발자에게 &lt;code class=&quot;language-text&quot;&gt;users.filter(...).map(...)&lt;/code&gt;은 “배열 필터링 후 변환”이라는 하나의 청크로 인식된다. 이 패턴을 수백, 수천 번 봤기 때문에, 장기 기억에 저장된 청크를 꺼내와서 작업 기억의 슬롯을 하나만 쓰는 것이다. 나머지 슬롯은 “왜 필터링하는가”, “결과가 어디에 쓰이는가” 같은 더 상위 수준의 사고에 할당할 수 있다.&lt;/p&gt;
&lt;p&gt;이것이 바로 체스 마스터가 체스판을 한 번 보고 전체 상황을 파악할 수 있는 원리와 같다. 체스 마스터는 개별 말의 위치를 하나씩 기억하는 게 아니라, 익숙한 포진 패턴을 하나의 청크로 인식한다. 그래서 의미 있는 배치의 체스판은 빠르게 기억하지만, 말을 무작위로 배치하면 초보자와 별 차이가 없다.&lt;/p&gt;
&lt;p&gt;코드도 마찬가지다. 관용적인 코드가 읽기 쉬운 이유는 그게 “올바른” 코드여서가 아니라, 개발자의 장기 기억에 이미 저장된 청크와 일치하기 때문이다.&lt;/p&gt;
&lt;p&gt;그리고 특정 패턴이 관용적이 되는 데는 언어의 설계 의도, 표준 라이브러리의 관례, 커뮤니티의 반복적 선택 같은 외부 요인이 작용한다. 단순히 “많이 써서 익숙한 것”이 아니라, 여러 이유로 수렴한 결과가 익숙함을 만든 것이다. 프로젝트만의 독특한 패턴이나 지나치게 창의적인 코드가 읽기 어려운 이유도 여기에 있다. 기존 청크와 매칭되지 않으면, 뇌는 모든 것을 개별 요소로 분해해서 처리해야 하고, 작업 기억은 순식간에 포화된다.&lt;/p&gt;
&lt;h2 id=&quot;시스템-1과-시스템-2-직관과-분석&quot; style=&quot;position:relative;&quot;&gt;시스템 1과 시스템 2: 직관과 분석&lt;a href=&quot;#%EC%8B%9C%EC%8A%A4%ED%85%9C-1%EA%B3%BC-%EC%8B%9C%EC%8A%A4%ED%85%9C-2-%EC%A7%81%EA%B4%80%EA%B3%BC-%EB%B6%84%EC%84%9D&quot; aria-label=&quot;시스템 1과 시스템 2 직관과 분석 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;여기서 다니엘 카너먼(Daniel Kahneman)의 이중 처리 이론을 꺼내야 한다. 카너먼은 인간의 사고를 두 가지 시스템으로 나눴다.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;시스템 1&lt;/strong&gt;: 빠르고, 자동적이고, 직관적인 사고. 패턴 인식에 기반한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;시스템 2&lt;/strong&gt;: 느리고, 의식적이고, 분석적인 사고. 논리적 추론에 기반한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;우리가 일상적으로 하는 판단 대부분은 시스템 1이 담당한다. 운전을 하거나, 전화기 너머 여친의 기분을 한마디에 알아채는 것도 시스템 1의 영역이다. 시스템 1은 새로운 정보를 접했을 때, 완전히 새로운 패턴을 만들어내는 게 아니라 기존에 저장된 패턴과 대조하는 방식으로 작동한다.&lt;/p&gt;
&lt;p&gt;시스템 1이 막히면 그때서야 시스템 2가 호출된다. “이게 뭐지?” 하고 의식적으로 분석을 시작하는 순간이 바로 시스템 2가 개입하는 시점이다. 그리고 이 프레임워크를 코드 읽기에 적용하면 정말 많은 것이 설명된다.&lt;/p&gt;
&lt;p&gt;읽기 쉬운 코드란, 대부분 시스템 1의 패턴 인식으로 처리되고 시스템 2의 개입이 최소화되는 코드다.&lt;/p&gt;
&lt;p&gt;숙련된 개발자가 코드를 읽을 때, 익숙한 패턴은 시스템 1이 자동으로 처리한다. &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 루프, &lt;code class=&quot;language-text&quot;&gt;if-else&lt;/code&gt; 분기, &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;reduce&lt;/code&gt; 체이닝, &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; 블록 등 이런 것들은 수천 번 봐온 패턴이기 때문에 의식적 노력 없이 처리된다. 시스템 2는 편안한 저전력 모드에 머물면서, 시스템 1이 올려주는 정보를 승인하기만 하면 된다.&lt;/p&gt;
&lt;p&gt;그런데 갑자기 예상치 못한 패턴이 나타나면 상황이 달라진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 시스템 1이 처리 가능한 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canPurchase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isVerified&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 시스템 2를 호출하는 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canPurchase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isVerified&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;두 코드는 같은 의도를 표현한다. 하지만 두 번째 코드를 보는 순간 뇌에서는 시스템 1이 “모르겠다”는 신호를 보내고, 시스템 2가 비싼 비용을 들여 분석을 시작한다. 이중 부정을 풀고, 드모르간 법칙을 머릿속에서 돌리고, 마지막 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; 체크가 왜 필요한지를 따져봐야 한다. 이러한 전환 자체가 인지적 비용이다.&lt;/p&gt;
&lt;p&gt;카너먼은 이런 현상을 인지적 긴장이라 불렀다. 시스템 2가 개입할수록 뇌는 더 많은 에너지를 소비하고 피로감을 느끼게 된다. “읽기 어려운 코드”라는 주관적 느낌의 실체는 바로 패턴 매칭 실패로 인한 시스템 전환, 그리고 그에 따르는 인지적 비용이 발생하는 것이다.&lt;/p&gt;
&lt;p&gt;이 관점에서 보면, 코드 리뷰에서 “이해하기 어렵다”는 피드백은 단순한 취향 불만이 아니라, 인지 시스템의 전환 비용이 실제로 발생하고 있다는 신호에 가깝다. 그 비용의 크기는 개인의 경험과 청크 구성에 따라 다르겠지만, 비용이 발생한다는 사실 자체는 실재한다.&lt;/p&gt;
&lt;h2 id=&quot;게슈탈트-원리-코드의-시각적-구조가-이해에-미치는-영향&quot; style=&quot;position:relative;&quot;&gt;게슈탈트 원리: 코드의 시각적 구조가 이해에 미치는 영향&lt;a href=&quot;#%EA%B2%8C%EC%8A%88%ED%83%88%ED%8A%B8-%EC%9B%90%EB%A6%AC-%EC%BD%94%EB%93%9C%EC%9D%98-%EC%8B%9C%EA%B0%81%EC%A0%81-%EA%B5%AC%EC%A1%B0%EA%B0%80-%EC%9D%B4%ED%95%B4%EC%97%90-%EB%AF%B8%EC%B9%98%EB%8A%94-%EC%98%81%ED%96%A5&quot; aria-label=&quot;게슈탈트 원리 코드의 시각적 구조가 이해에 미치는 영향 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;읽기 쉬운 코드에는 논리적 구조뿐만 아니라 시각적 구조도 중요하다. 여기서 게슈탈트 심리학의 지각 원리가 등장한다.&lt;/p&gt;
&lt;p&gt;게슈탈트 심리학은 인간의 뇌가 개별 요소가 아닌 전체 패턴과 구조를 우선적으로 인식한다는 점을 연구하는 분야다. 그 핵심 원리 몇 가지는 코드 가독성에 직접적으로 연결된다.&lt;/p&gt;
&lt;h3 id=&quot;근접성의-원리&quot; style=&quot;position:relative;&quot;&gt;근접성의 원리&lt;a href=&quot;#%EA%B7%BC%EC%A0%91%EC%84%B1%EC%9D%98-%EC%9B%90%EB%A6%AC&quot; aria-label=&quot;근접성의 원리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;가까이 있는 요소들은 하나의 그룹으로 인식된다. 한번 두 가지 버전의 코드를 살펴보며 이 그룹이 왜 중요한지를 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 근접성 원리가 적용되지 않은 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; role &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determineRole&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permissions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dashboard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; notifications &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNotifications&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 근접성 원리가 적용된 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; role &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determineRole&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permissions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dashboard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; notifications &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNotifications&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;두 번째 버전에서 빈 줄 하나가 추가됐을 뿐인데 뇌는 자동으로 “사용자 정보 처리”와 “권한 기반 데이터 조회”라는 두 그룹을 인식한다.&lt;/p&gt;
&lt;p&gt;게슈탈트 연구에 따르면 근접성은 색상이나 형태의 유사성보다도 더 강력한 그룹핑 단서다. 이 원리는 UI 디자인에서도 그대로 사용되는데, 서로 연관이 있는 정보는 가까이 붙이고 연관이 없는 정보는 간격을 늘려 멀리 떨어트려놓는 것이 이 때문이다.&lt;/p&gt;
&lt;p&gt;마찬가지로 코드에서 빈 줄과 들여쓰기가 중요한 이유는 단순히 미관 때문이 아니라, 뇌의 지각 시스템이 그걸 기반으로 구조를 파악하기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;유사성의-원리&quot; style=&quot;position:relative;&quot;&gt;유사성의 원리&lt;a href=&quot;#%EC%9C%A0%EC%82%AC%EC%84%B1%EC%9D%98-%EC%9B%90%EB%A6%AC&quot; aria-label=&quot;유사성의 원리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;근접성과 마찬가지로 비슷하게 생긴 요소들도 같은 그룹으로 인식된다. 이것을 유사성의 원리라고 하는데, 이 원리는 코드에서 일관된 네이밍이 왜 중요한지를 설명한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 유사성 원리가 깨진 네이밍&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; get_orders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;retrieveOrderList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pmtHistory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadPayments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;uid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 유사성 원리가 적용된 네이밍&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; orders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchOrders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchPayments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 버전에서는 데이터 페칭이라는 같은 종류의 작업임에도 네이밍 규칙이 제각각이다. &lt;code class=&quot;language-text&quot;&gt;userData&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;get_orders&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;pmtHistory&lt;/code&gt;라는 변수명은 각각 다른 형태를 가지고, &lt;code class=&quot;language-text&quot;&gt;fetchUser&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;retrieveOrderList&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;loadPayments&lt;/code&gt;라는 함수명도 일관성이 없다. 뇌는 이런 코드를 보면 이들을 같은 그룹으로 인식하지 못하고 각 라인을 개별 항목으로 처리하면서 작업 기억을 소진한다.&lt;/p&gt;
&lt;p&gt;두 번째 버전에서는 패턴이 명확하다. &lt;code class=&quot;language-text&quot;&gt;fetch + 리소스명&lt;/code&gt;이라는 일관된 구조 덕분에, 세 줄이 “동일한 패턴의 데이터 패칭”이라는 하나의 청크로 인식된다.&lt;/p&gt;
&lt;h3 id=&quot;연속성의-원리&quot; style=&quot;position:relative;&quot;&gt;연속성의 원리&lt;a href=&quot;#%EC%97%B0%EC%86%8D%EC%84%B1%EC%9D%98-%EC%9B%90%EB%A6%AC&quot; aria-label=&quot;연속성의 원리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;연속성의 원리는 시선이 자연스럽게 흐르는 방향을 따라 요소들을 하나의 연속된 것으로 인식하는 원리다. 코드에서 이건 실행 흐름의 선형성과 관련된다.&lt;/p&gt;
&lt;p&gt;우리 뇌는 위에서 아래로, 왼쪽에서 오른쪽으로 흐르는 것을 자연스럽게 느낀다. 깊은 중첩, 복잡한 콜백, 여기저기 점프하는 &lt;code class=&quot;language-text&quot;&gt;goto&lt;/code&gt;문 등이 읽기 어려운 이유는 연속성의 원리를 위반하기 때문이다.&lt;/p&gt;
&lt;p&gt;우리가 얼리 리턴 패턴을 사용했을 때, 중첩된 &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt;문보다 읽기 쉬운 이유도 마찬가지다. 예외 케이스를 먼저 걸러내고 나면 남은 코드는 위에서 아래로 한 방향으로 흐른다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 연속성이 깨지는 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isActive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inStock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onSale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;salePrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Out of stock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Inactive user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 연속성이 유지되는 코드&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isActive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Inactive user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inStock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Out of stock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tier &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;premium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onSale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;salePrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 버전은 들여쓰기가 깊어지면서 시선이 오른쪽으로, 다시 왼쪽으로 지그재그를 그린다. 뇌는 각 중첩 수준에서 “지금 어느 조건 안에 있는가”를 작업 기억에 유지해야 한다.&lt;/p&gt;
&lt;p&gt;반면 두 번째 버전은 예외를 먼저 걸러낸 뒤 위에서 아래로 자연스럽게 흘러내린다. 연속성의 원리에 부합하기 때문에 뇌가 구조를 파악하는 데 드는 비용이 크게 줄어든다.&lt;/p&gt;
&lt;h2 id=&quot;인지-부하-이론-세-가지-부하의-종류&quot; style=&quot;position:relative;&quot;&gt;인지 부하 이론: 세 가지 부하의 종류&lt;a href=&quot;#%EC%9D%B8%EC%A7%80-%EB%B6%80%ED%95%98-%EC%9D%B4%EB%A1%A0-%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B6%80%ED%95%98%EC%9D%98-%EC%A2%85%EB%A5%98&quot; aria-label=&quot;인지 부하 이론 세 가지 부하의 종류 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;여기까지의 이야기를 좀 더 체계적으로 정리해주는 프레임워크가 있다. 존 스웰러(John Sweller)의 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%A7%80_%EB%B6%80%ED%95%98&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;인지 부하 이론&lt;/a&gt;이다.&lt;/p&gt;
&lt;p&gt;이 이론에 따르면 학습이나 문제 해결 시 발생하는 인지 부하는 세 가지로 나뉜다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;내재적 부하&lt;/strong&gt;: 과제 자체의 본질적 복잡성. 알고리즘의 난이도, 도메인의 복잡성 같은 것.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;외재적 부하&lt;/strong&gt;: 과제와 무관한, 표현 방식에서 오는 불필요한 복잡성. 일관되지 않은 네이밍, 불필요한 간접 참조, 혼란스러운 코드 구조 같은 것.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;본유적 부하&lt;/strong&gt;: 새로운 스키마를 형성하고 학습하는 데 드는 유익한 부하.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;이 이론에 따르면 우리가 읽기 쉬운 코드를 작성하기 위해 추구해야하는 것은 외재적 부하를 최소화하는 것이다.&lt;/p&gt;
&lt;p&gt;어차피 내재적 부하는 문제 자체에 내재된 것이니 줄일 수 없다. 예를 들어 분산 시스템의 합의 알고리즘을 구현하는 코드는 아무리 잘 써도 복잡할 수밖에 없는 것이다. 우리가 피해야할 문제는 “표현 방식”에서 오는 외재적 부하가 내재적 부하 위에 불필요하게 쌓일 때다.&lt;/p&gt;
&lt;p&gt;이 관점으로 보면 코드 가독성을 높이는 일관된 네이밍, 적절한 함수 분리, 명확한 타입 선언, 의미 있는 빈 줄과 같은 패턴은 결국 외재적 인지 부하를 줄이는 행위다. 뇌의 제한된 자원을 외재적 부하에 낭비하지 않고, 내재적 부하(실제 문제)를 처리하는 데 집중할 수 있게 해주는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://doi.org/10.1016/j.jss.2023.111619&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;2023년에 발표된 체계적 문헌 리뷰&lt;/a&gt;에서도 흥미로운 사실이 확인됐다. 소스 코드 메트릭과 실제 측정된 인지 부하 사이의 관계를 조사한 연구들에서 전통적 코드 메트릭 중 실제 인지 부하와 일관되게 높은 상관을 보인 것은 드물었고, 상관이 확인된 경우에도 과제 조건이나 측정 방식에 따라 결과가 달라지는 경향이 있었다. 즉, 우리가 “복잡도”라고 측정하는 것과 개발자의 뇌가 실제로 “복잡하다”고 느끼는 것은 다를 수 있다는 뜻이다.&lt;/p&gt;
&lt;p&gt;이건 의미심장한 결과다. 기계적으로 측정 가능한 메트릭은 코드의 외형적 복잡도를 포착하지만, 개발자의 뇌가 실제로 겪는 인지 부하는 패턴의 익숙함, 청킹의 효율성, 시각적 구조의 명확성과 같이 주관적 인식에 영향을 받는다는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;경험이-뇌를-물리적으로-바꾼다&quot; style=&quot;position:relative;&quot;&gt;경험이 뇌를 물리적으로 바꾼다&lt;a href=&quot;#%EA%B2%BD%ED%97%98%EC%9D%B4-%EB%87%8C%EB%A5%BC-%EB%AC%BC%EB%A6%AC%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%B0%94%EA%BE%BC%EB%8B%A4&quot; aria-label=&quot;경험이 뇌를 물리적으로 바꾼다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 전문가와 초보자의 뇌 활성화 패턴이 다르다고 했다. 이건 단순히 개발 짬바가 쌓이면 더 잘한다는 이야기가 아니다. &lt;a href=&quot;https://www.nature.com/articles/s41598-024-56090-6&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;2024년 Scientific Reports에 발표된 연구&lt;/a&gt;에서는 62명의 파이썬 프로그래머를 대상으로 뇌파를 측정하며, 코드에 의도적으로 삽입한 문법 오류와 의미 오류에 대한 뇌의 반응을 관찰했다.&lt;/p&gt;
&lt;p&gt;결과는 놀라웠다. 숙련된 프로그래머는 코드의 문법적 위반과 의미적 위반에 대해 서로 다른 뇌파 패턴을 보였다. 이는 자연어를 읽을 때 문법 오류와 의미 오류에 대해 다른 뇌파가 나타나는 것과 유사한 패턴이다. 프로그래밍 경험이 뇌에 특정 언어와 패턴을 처리하기 위한 신경 회로를 형성한다는 뜻이다.&lt;/p&gt;
&lt;p&gt;다시 말해, 코딩 경험은 뇌의 물리적 구조를 변화시킨다. 신경가소성에 의해, 반복적으로 노출된 코드 패턴은 장기 기억에 스키마로 저장되고, 이 스키마가 청킹의 기반이 된다. 시스템 1이 코드를 자동으로 처리할 수 있는 것은 이런 스키마가 축적된 결과다.&lt;/p&gt;
&lt;p&gt;또한 스키마는 개인이 노출된 패턴에 따라 형성되기 때문에 같은 코드베이스에서 같은 패턴을 반복적으로 접한 사람들은 비슷한 스키마를 공유하게 된다. 이걸 뒤집어 생각하면 팀에서 일관된 코드 스타일을 유지하는 것은 취향의 문제가 아니라 팀원들의 뇌에 공유된 청크를 형성하는 과정인 셈이다. 코딩 컨벤션이 중요한 이유가 단순히 통일성이 아니라, 집단적 인지 효율성 때문인 것이다.&lt;/p&gt;
&lt;h2 id=&quot;예측-부호화-뇌는-코드를-읽는-게-아니라-예측한다&quot; style=&quot;position:relative;&quot;&gt;예측 부호화: 뇌는 코드를 읽는 게 아니라 예측한다&lt;a href=&quot;#%EC%98%88%EC%B8%A1-%EB%B6%80%ED%98%B8%ED%99%94-%EB%87%8C%EB%8A%94-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9D%BD%EB%8A%94-%EA%B2%8C-%EC%95%84%EB%8B%88%EB%9D%BC-%EC%98%88%EC%B8%A1%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;예측 부호화 뇌는 코드를 읽는 게 아니라 예측한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;최근 인지과학에서 주목받는 이론 중 하나는 예측 부호화다. 이 이론에 따르면, 뇌는 수동적으로 정보를 수신하는 게 아니라, 끊임없이 다음에 올 정보를 예측하고, 실제 입력이 그 예측과 다를 때만 추가적인 처리를 한다.&lt;/p&gt;
&lt;p&gt;코드를 읽을 때도 마찬가지다. 우리 뇌는 다음 줄에 뭐가 올지 끊임없이 예측한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/users/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 여기에 뭐가 올지, 이미 예측하고 있다&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드를 읽는 숙련된 개발자의 뇌는 이미 “뭐 이제 응답 데이터를 파싱해서 리턴하겠지”라고 예측하고 있다. 그리고 실제로 &lt;code class=&quot;language-text&quot;&gt;return response.data;&lt;/code&gt; 같은 코드가 나오면 그 예측이 맞았으므로 추가적인 인지 비용이 거의 발생하지 않는다.&lt;/p&gt;
&lt;p&gt;하지만 만약 예측과 전혀 다른 쌩뚱맞은 코드가 나오면 어떻게 될까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/users/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    globalEventBus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user-fetched&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 엥 이거 뭐임?&lt;/span&gt;
    localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lastUser&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 어라?&lt;/span&gt;
    analytics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;profile_view&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 아 로깅을 왜 여기서 해&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;fetchUserProfile&lt;/code&gt;이라는 이름에서 뇌가 예측한 것은 “사용자 프로필을 가져와서 돌려주는 함수”다. 그런데 이벤트 버스 발행, 로컬 스토리지 저장, 애널리틱스 추적이라는 예측 밖의 동작이 나타난다. 이때마다 뇌는 예측 오류 신호를 발생시키고, 시스템 2를 호출해서 이 코드가 왜 여기에 있는지를 분석하기 시작한다.&lt;/p&gt;
&lt;p&gt;즉, 우리가 두 번째 버전의 코드를 읽기 어렵다고 느끼는 이유는 함수의 이름은 &lt;code class=&quot;language-text&quot;&gt;fetchUserProfile&lt;/code&gt;이지만, 내부에서는 그와 전혀 상관없는 동작들이 발생하고 있기 대문이다. 이름이 설정한 예측과 실제 동작이 일치할수록 예측 오류가 줄어들고 인지 비용이 절감된다.&lt;/p&gt;
&lt;p&gt;이건 함수 내부뿐 아니라 인터페이스 설계에서도 마찬가지다. 필자와 같은 프론트엔드 개발자에게 익숙한 컴포넌트 인터페이스를 예시로 들어보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 예측 가능한 인터페이스&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TextInput&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;setName&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;이름을 입력하세요&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 예측이 어려운 인터페이스&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserNameInput&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;setUser&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;setUser&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;이름을 입력하세요&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 컴포넌트는 &lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;onChange&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;defaultValue&lt;/code&gt;라는 React 생태계에서 거의 모든 입력 컴포넌트가 공유하는 인터페이스를 따른다. 이 패턴을 수없이 접해온 개발자의 시스템 1은 “입력 컴포넌트구나”로 처리하고 넘어간다.&lt;/p&gt;
&lt;p&gt;반면 두 번째는 &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;setUser&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;blank&lt;/code&gt;라는 비즈니스 로직에 강하게 결합되었거나 의미를 알기 어려운 인터페이스를 가지고 있다. 이 컴포넌트가 내부에서 &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; 객체의 어떤 필드를 건드리는지, &lt;code class=&quot;language-text&quot;&gt;blank&lt;/code&gt;는 도대체 언제 사용되는 것인지 파악하기 전까지는 안심하고 사용할 수가 없다. 매번 내부 구현을 들여다봐야 하고, 그때마다 예측 오류가 발생한다.&lt;/p&gt;
&lt;p&gt;즉 읽기 쉬운 코드를 작성하기 위해서 우리는 함수의 이름 뿐 아니라 변수명, 파일 구조, 디렉토리 구성, API 설계 등 코드베이스의 모든 수준에서 예측 가능성을 높여야한다.&lt;/p&gt;
&lt;h2 id=&quot;그래서-좋은-코드란-결국&quot; style=&quot;position:relative;&quot;&gt;그래서 “좋은 코드”란 결국&lt;a href=&quot;#%EA%B7%B8%EB%9E%98%EC%84%9C-%EC%A2%8B%EC%9D%80-%EC%BD%94%EB%93%9C%EB%9E%80-%EA%B2%B0%EA%B5%AD&quot; aria-label=&quot;그래서 좋은 코드란 결국 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지의 내용을 정리해보면, “읽기 쉬운 코드”라는 주관적 느낌의 실체는 다음과 같다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;작업 기억을 초과하지 않는 코드&lt;/strong&gt;: 동시에 머릿속에 담아야 할 맥락이 3~4개 이내인 코드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;기존 청크와 매칭되는 코드&lt;/strong&gt;: 익숙한 패턴을 사용해서 장기 기억의 스키마를 활용할 수 있는 코드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;시스템 1에서 처리 가능한 코드&lt;/strong&gt;: 시스템 2를 불필요하게 호출하지 않는, 패턴 인식만으로 이해 가능한 코드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;시각적 구조가 논리적 구조와 일치하는 코드&lt;/strong&gt;: 게슈탈트 원리에 부합하여 뇌의 지각 시스템이 구조를 자동으로 파악하는 코드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;예측 가능한 코드&lt;/strong&gt;: 이름과 구조에서 설정한 기대를 위반하지 않는 코드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;외재적 인지 부하가 낮은 코드&lt;/strong&gt;: 문제 자체의 복잡성만 남기고, 표현에서 오는 불필요한 복잡성을 제거한 코드&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;이 목록을 보면 재밌는 사실을 하나 발견할 수 있다. 이 중 어느 것도 “정확한 코드”를 의미하지 않는다는 점이다.&lt;/p&gt;
&lt;p&gt;가독성과 정확성은 별개의 축이다. 완벽하게 정확하지만 읽기 불가능한 코드도 있고, 읽기는 쉽지만 틀린 코드도 있다. 다만 읽기 쉬운 코드는 버그를 발견하기도 쉽다. 외재적 부하가 낮으니, 뇌의 자원을 논리적 오류를 찾는 데 집중할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;다만 한 가지 주의할 점이 있다. 카너먼은 시스템 1의 편향에 대해서도 경고했다. 시스템 1은 빠르지만, 그 속도의 대가로 편향이 존재한다. 대표적인 것이 익숙함 편향이다. 자신에게 익숙한 패턴을 “읽기 쉬운 코드”로 느끼는 것은 사실이지만, 그것이 객관적으로 최선인지는 별개의 문제다. 함수형 프로그래밍에 익숙한 개발자는 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 루프를 “읽기 어렵다”고 느낄 수 있고, 반대의 경우도 마찬가지다. 이때 “읽기 어렵다”는 느낌은 코드의 객관적 품질이 아니라, 자신의 시스템 1에 저장된 청크의 편향을 반영하는 것일 수 있다.&lt;/p&gt;
&lt;p&gt;코드 리뷰에서 “이해하기 어렵다”는 피드백을 줄 때, 한 번쯤 자문해볼 가치가 있다. 이게 정말로 인지 부하가 높은 코드인가, 아니면 단순히 내 시스템 1에 등록되지 않은 패턴인가? 전자라면 리팩토링이 필요하고, 후자라면 오히려 내 청크 라이브러리를 확장할 기회다.&lt;/p&gt;
&lt;h2 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;마무리&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“읽기 쉬운 코드”는 그냥 느낌이나 취향의 문제가 아니다. 작업 기억의 용량 제한, 청킹 메커니즘, 이중 처리 시스템, 게슈탈트 지각 원리, 예측 부호화와 같은 인간의 인지 구조가 만들어내는 자연스러운 결과다.&lt;/p&gt;
&lt;p&gt;필자가 이전 글에서 “가독성은 주관적이다”라고 했던 이야기의 이유도 바로 여기에 있다. 청킹은 개인의 경험에 의존하고 시스템 1에 등록된 패턴은 사람마다 다르기 때문이다.&lt;/p&gt;
&lt;p&gt;같은 코드를 보고 누군가는 쉽다고 느끼고 누군가는 어렵다고 느끼는 건 그저 취향이 달라서가 아니라 뇌에 축적된 스키마가 다르기 때문이다. 가독성이 주관적일 수밖에 없는 이유 자체가 인지 구조에 내재되어 있는 셈이다.&lt;/p&gt;
&lt;p&gt;이상으로 우리는 왜 어떤 코드를 읽기 쉽다고 느낄까 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Why Do Type Systems Behave Like Proofs?]]></title><description><![CDATA[We use types every day and face countless type errors. Each time, we read the error message, search for a fix, and move on. We rarely stop to think about why the type system behaves the way it does. Knowing how to use types is like understanding grammar. Understanding the type system is closer to understanding why that grammar was designed the way it is.]]></description><link>https://evan-moon.github.io/2026/01/25/types-as-proofs-typescript-hidden-math/en/</link><guid isPermaLink="false">20260125-types-as-proofs-typescript-hidden-math-en</guid><pubDate>Sun, 25 Jan 2026 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We use types every day and face countless type errors. Each time, we read the error message, search for a fix, and move on. We rarely stop to think about &lt;em&gt;why&lt;/em&gt; the type system behaves the way it does.&lt;/p&gt;
&lt;p&gt;Knowing how to use types is like understanding grammar. Understanding the type system is closer to understanding why that grammar was designed the way it is.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;I previously translated the &lt;a href=&quot;/2024/01/30/category-theory-for-programmers-0-preface/&quot;&gt;“Category Theory for Programmers”&lt;/a&gt; series, covering concepts like categories, functors, and composition. Looking back, it had a fairly steep learning curve, so I wanted to write a more accessible version.&lt;/p&gt;
&lt;p&gt;In this post, I’ll focus on the correspondence between types and logic, and explore what it actually means when the type checker says “pass.”&lt;/p&gt;
&lt;h2 id=&quot;is-type-checking-really-just-checking&quot; style=&quot;position:relative;&quot;&gt;Is Type Checking Really Just “Checking”?&lt;a href=&quot;#is-type-checking-really-just-checking&quot; aria-label=&quot;is type checking really just checking permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When most developers first learn TypeScript, they treat the type system like a linter. Put in the wrong type and you get a red underline; put in the right type and it passes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Error: Argument of type &apos;string&apos; is not assignable to parameter of type &apos;number&apos;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This isn’t wrong, but it’s missing something.&lt;/p&gt;
&lt;p&gt;A type system isn’t just a tool for catching errors. There’s a mathematical structure behind it, and passing type checking means more than “no errors found.” Types correspond to propositions in logic, and code that satisfies a type corresponds to a proof of that proposition.&lt;/p&gt;
&lt;p&gt;So what are the type errors we encounter? Simple mistakes — or signals that some contract we implicitly entered into has been broken?&lt;/p&gt;
&lt;p&gt;To get there, we need to talk about the math behind type systems.&lt;/p&gt;
&lt;h2 id=&quot;formal-logic-set-theory-and-lambda-calculus&quot; style=&quot;position:relative;&quot;&gt;Formal logic, set theory, and lambda calculus&lt;a href=&quot;#formal-logic-set-theory-and-lambda-calculus&quot; aria-label=&quot;formal logic set theory and lambda calculus permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Type systems rest on three mathematical ideas. Math might sound intimidating here, but these are things we already work with in code every day.&lt;/p&gt;
&lt;h4 id=&quot;formal-logic-what-it-means-to-prove-something-true&quot; style=&quot;position:relative;&quot;&gt;Formal Logic: What It Means to “Prove Something True”&lt;a href=&quot;#formal-logic-what-it-means-to-prove-something-true&quot; aria-label=&quot;formal logic what it means to prove something true permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Formal logic is a system for handling propositions like ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;,” ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;,” and “if &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.” The core idea is: “if you want to claim something is true, you have to prove it.”&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Everyday Meaning&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;∧&lt;/td&gt;
&lt;td&gt;and&lt;/td&gt;
&lt;td&gt;“I have an umbrella and rain boots”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;∨&lt;/td&gt;
&lt;td&gt;or&lt;/td&gt;
&lt;td&gt;“I’ll take the bus or the subway”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;→&lt;/td&gt;
&lt;td&gt;if … then&lt;/td&gt;
&lt;td&gt;“If it rains, the ground gets wet”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For example, to claim that &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∨&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \lor B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∨&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true, you need to show that &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true or show that &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true. “One of them must be true, but I don’t know which” doesn’t count as a proof.&lt;/p&gt;
&lt;p&gt;And once you accept ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∨&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \lor B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∨&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;,” you can see that to derive anything from it, you need branches that handle both cases (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;). This is structurally identical to why type narrowing is needed when working with &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; in code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// To claim &quot;A or B&quot; is true, you must concretely show which one&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &quot;It&apos;s one of the two&quot; isn&apos;t enough. You need to check which case.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;string&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;set-theory-types-are-collections-of-elements&quot; style=&quot;position:relative;&quot;&gt;Set Theory: Types Are Collections of Elements&lt;a href=&quot;#set-theory-types-are-collections-of-elements&quot; aria-label=&quot;set theory types are collections of elements permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Think of a set as a bag that holds similar things. The &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; type is a bag containing every number the program can represent. The &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; type is a bag of all strings. And &lt;code class=&quot;language-text&quot;&gt;number | string&lt;/code&gt; is the combined contents of both bags.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Pull one from the number bag&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Pull one from the string bag&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Pull from either bag&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you think of types as sets, many things become natural. The &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; type is an empty bag, and &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; is the bag that contains everything.&lt;/p&gt;
&lt;p&gt;Strictly speaking, TypeScript’s actual type system differs from pure set theory in some ways, but this level of understanding is sufficient for building intuition.&lt;/p&gt;
&lt;h4 id=&quot;lambda-calculus-functions-and-more&quot; style=&quot;position:relative;&quot;&gt;Lambda Calculus: Functions, and More&lt;a href=&quot;#lambda-calculus-functions-and-more&quot; aria-label=&quot;lambda calculus functions and more permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Lambda calculus is a concept created in the 1930s by mathematician Alonzo Church to answer the question: “What is computation?” The name sounds intimidating, but if you’re a developer, you already use it every day.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// In lambda calculus: λx.x&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// In lambda calculus: λx.λy.x&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Arrow functions are close to the modern syntax for lambda (&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;λ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\lambda&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;λ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) notation, and they directly demonstrate lambda calculus’s core idea of “function definition and application.” What Church proved is that these simple concepts alone can express arithmetic, conditionals, loops, and even numbers themselves.&lt;/p&gt;
&lt;p&gt;Real JavaScript functions aren’t 100% identical to lambda calculus due to side effects, exceptions, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; binding, and the runtime object model. But they share the same basic insight: computation is about creating and applying functions. That’s enough for our purposes.&lt;/p&gt;
&lt;h4 id=&quot;the-curry-howard-correspondence&quot; style=&quot;position:relative;&quot;&gt;The Curry-Howard correspondence&lt;a href=&quot;#the-curry-howard-correspondence&quot; aria-label=&quot;the curry howard correspondence permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;So how are these three concepts used in type systems? To answer this, we need to talk about the Curry-Howard correspondence, the concept that unifies them.&lt;/p&gt;
&lt;p&gt;The Curry-Howard correspondence (also called the Curry-Howard isomorphism) is a direct relationship between computer programs and logical proofs: proof rules in logic correspond to type rules in type systems.&lt;/p&gt;
&lt;p&gt;Logician Haskell Curry first noticed this pattern in the 1930s while adding types to lambda calculus. In 1969, William Howard dug deeper and established these correspondences:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;In Logic&lt;/th&gt;
&lt;th&gt;In Programming&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Proposition&lt;/td&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proof&lt;/td&gt;
&lt;td&gt;Program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;If A then B&lt;/td&gt;
&lt;td&gt;Function from A to B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A and B&lt;/td&gt;
&lt;td&gt;Tuple/object containing both A and B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A or B&lt;/td&gt;
&lt;td&gt;Union type: A or B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False (unprovable)&lt;/td&gt;
&lt;td&gt;never (no value can exist)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If I had to boil it down to one line:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Types correspond to propositions, and programs that produce values of those types correspond to proofs of those propositions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TypeScript is a language that partially borrows this idea for practical purposes. “Partially” because escape hatches like &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; and type assertions exist.&lt;/p&gt;
&lt;p&gt;So in this post, when I say “proof,” think of it as “fulfilling the contract that the type rules demand.” I’ll revisit TypeScript’s limitations at the end.&lt;/p&gt;
&lt;h2 id=&quot;logical-structures-through-types&quot; style=&quot;position:relative;&quot;&gt;Logical Structures Through Types&lt;a href=&quot;#logical-structures-through-types&quot; aria-label=&quot;logical structures through types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s now look at how the Curry-Howard correspondence actually manifests, one piece at a time.&lt;/p&gt;
&lt;h4 id=&quot;functions-evidence-of-if-a-then-b&quot; style=&quot;position:relative;&quot;&gt;Functions: Evidence of “If A Then B”&lt;a href=&quot;#functions-evidence-of-if-a-then-b&quot; aria-label=&quot;functions evidence of if a then b permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Let’s start with the most fundamental correspondence: function types. The function type &lt;code class=&quot;language-text&quot;&gt;(a: A) =&gt; B&lt;/code&gt; corresponds to “if &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;” in logic.&lt;/p&gt;
&lt;p&gt;What does this mean? Let me put it in a more everyday analogy.&lt;/p&gt;
&lt;p&gt;Say a friend promises: “If you give me flour, I’ll make you bread.” This is the proposition “flour → bread.” How do you verify this promise is real? Simple — you give them flour, and bread comes out.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bread &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Knead the flour, let it ferment, bake it...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; bread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function passing type checking shows that the promise “give me flour and I can make bread” is fulfillable within the type rules. The function’s implementation itself is the fulfillment of that contract.&lt;/p&gt;
&lt;p&gt;What happens when a type error occurs?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bread &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Error: Type &apos;Flour&apos; is not assignable to type &apos;Bread&apos;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; flour&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You promised to take flour and make bread, but you just handed back the flour. That’s a breach of contract, hence the type error.&lt;/p&gt;
&lt;p&gt;When this contract structure is properly maintained, we can start inferring function results.&lt;/p&gt;
&lt;p&gt;In logic, there’s an inference rule called Modus Ponens:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If “if &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;” is true, and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true, then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is also true.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, if the proposition “if it rains, the ground gets wet” is true and “it’s raining” is also true, then we can easily infer “the ground is wet.” This structure is identical to function calls in programming, which is why we can infer the result type of a function.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// The &quot;flour → bread&quot; promise&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Bread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// We have flour&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFlour&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Therefore we get bread&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bread&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The function &lt;code class=&quot;language-text&quot;&gt;makeBread&lt;/code&gt; is the proposition “if you give me flour, I can make bread.” If this proposition is true and “flour is given” is also true, then naturally the value stored in &lt;code class=&quot;language-text&quot;&gt;bread&lt;/code&gt; being of type &lt;code class=&quot;language-text&quot;&gt;Bread&lt;/code&gt; is also true.&lt;/p&gt;
&lt;p&gt;The function calls and return type inference we do every day share this exact structure with logical inference.&lt;/p&gt;
&lt;h4 id=&quot;tuples-evidence-of-and&quot; style=&quot;position:relative;&quot;&gt;Tuples: Evidence of “And”&lt;a href=&quot;#tuples-evidence-of-and&quot; aria-label=&quot;tuples evidence of and permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The logical ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;” corresponds to tuples or objects in programming.&lt;/p&gt;
&lt;p&gt;Think of an everyday example. To travel abroad, you need to satisfy the condition “I have a passport and I have a plane ticket.” How do you fulfill this? Show both.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CanTravel&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Passport&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Ticket&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Fulfilling the &quot;can travel&quot; condition = a tuple with both passport and ticket&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; proof&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CanTravel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;myPassport&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; myTicket&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once the &lt;code class=&quot;language-text&quot;&gt;CanTravel&lt;/code&gt; type is satisfied — in other words, once “I have a passport and a plane ticket” holds — you can freely extract either one from the tuple.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPassport&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;travel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CanTravel&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Passport &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Extract A from &quot;A and B&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; travel&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTicket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;travel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CanTravel&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Ticket &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Extract B from &quot;A and B&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; travel&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This mirrors the logical rule “if &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \land B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true, then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true.” Extracting an element from a tuple corresponds to logical inference.&lt;/p&gt;
&lt;h4 id=&quot;unions-evidence-of-or&quot; style=&quot;position:relative;&quot;&gt;Unions: Evidence of “Or”&lt;a href=&quot;#unions-evidence-of-or&quot; aria-label=&quot;unions evidence of or permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;TypeScript’s union type &lt;code class=&quot;language-text&quot;&gt;A | B&lt;/code&gt; corresponds to ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;” in logic. The key point is that to claim ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;” is true, you must concretely show either that &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true or that &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is true.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentMethod&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CreditCard &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; BankTransfer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Fulfilling &quot;credit card or bank transfer&quot; = concretely provide one&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payment1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;credit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cardNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1234...&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payment2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bank&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; accountNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;5678...&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And even if the proposition ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;” is true, you can’t know which one it is until you concretely check.&lt;/p&gt;
&lt;p&gt;So to derive anything from this proposition, you need to handle both cases.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Receipt &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;credit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Handle case A&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;chargeCreditCard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Handle case B&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processBankTransfer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is why exhaustiveness checking matters in TypeScript. Logically, when handling ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;,” you need strategies for both cases to have complete coverage.&lt;/p&gt;
&lt;p&gt;That said, whether TypeScript automatically checks that all cases are handled depends on your configuration and code patterns. If you want to strictly enforce exhaustiveness, use a pattern like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assertNever&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Unexpected value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Shape&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;circle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; radius&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;square&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; side&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;triangle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; height&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;area&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shape&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Shape&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shape&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;circle&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;radius &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;square&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;side &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Argument of type &apos;{ type: &quot;triangle&quot;; height: number; }&apos; is not assignable to parameter of type &apos;never&apos;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assertNever&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shape&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If all union cases are handled, the &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt; branch is unreachable and &lt;code class=&quot;language-text&quot;&gt;shape&lt;/code&gt; becomes &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;. But if you add a new shape and forget to handle it, &lt;code class=&quot;language-text&quot;&gt;shape&lt;/code&gt; won’t be &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; anymore, and you’ll get a compile error.&lt;/p&gt;
&lt;h4 id=&quot;never-expressing-impossible&quot; style=&quot;position:relative;&quot;&gt;Never: Expressing “Impossible”&lt;a href=&quot;#never-expressing-impossible&quot; aria-label=&quot;never expressing impossible permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;TypeScript’s &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; type means “no such value can exist.” In logic, this is expressed as contradiction or falsehood.&lt;/p&gt;
&lt;p&gt;Using the set theory analogy from earlier, &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; is an empty bag. Nothing is in it, and nothing ever will be.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;throwError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// This function never returns normally&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// A return value &quot;cannot exist&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There’s an interesting principle from logic here: “from a contradiction, anything can be derived.” In Latin, “Ex falso quodlibet” — if an impossible situation has occurred, anything goes.&lt;/p&gt;
&lt;p&gt;We can express this principle in TypeScript:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;absurd&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// From never, you can convert to any type&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function expresses the rule “if &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;, then &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;.” Try replacing &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; with any concrete type and you’ll immediately get an error. Since &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; represents falsehood/contradiction, any type can follow it without being logically wrong.&lt;/p&gt;
&lt;p&gt;To be precise, TypeScript doesn’t exactly implement Ex falso in the formal sense. The &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; type is treated as a bottom type — a subtype of all types — so values of type &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; can be assigned to any type position. It resembles the Ex falso principle, but it’s really a consequence of subtyping.&lt;/p&gt;
&lt;h4 id=&quot;generics-contracts-that-hold-for-all-cases&quot; style=&quot;position:relative;&quot;&gt;Generics: Contracts That Hold “For All Cases”&lt;a href=&quot;#generics-contracts-that-hold-for-all-cases&quot; aria-label=&quot;generics contracts that hold for all cases permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When first learning generics, we’re usually told they let you “decide the type later.” That’s true, but there’s more to it.&lt;/p&gt;
&lt;p&gt;In logic, there’s something called a universal proposition: “for all &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;P(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; holds.” Like “all humans are mortal.”&lt;/p&gt;
&lt;p&gt;Generic functions have a structure similar to this universal proposition.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function expresses the contract: “for every type &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;, if you give me a &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;, I’ll return a &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;.”&lt;/p&gt;
&lt;p&gt;The catch is that you must show this holds for &lt;em&gt;all&lt;/em&gt; cases — which means you can’t assume anything about any specific case.&lt;/p&gt;
&lt;p&gt;That’s why assuming something specific about a generic type immediately produces a type error:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;broken&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Assuming all T is number...&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Operator &apos;+&apos; cannot be applied to types &apos;T&apos; and &apos;number&apos;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The moment you assume &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; is &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;, this is no longer a contract about all &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; — it’s narrowed to a contract about &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;. It’s no longer a universal proposition.&lt;/p&gt;
&lt;p&gt;We solve this by adding constraints to the “for all” premise:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;addOne&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With &lt;code class=&quot;language-text&quot;&gt;T extends number&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; becomes “a &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; that is a subset of &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;.” We’re adjusting the scope of “all.” That’s why we use the &lt;code class=&quot;language-text&quot;&gt;extends&lt;/code&gt; keyword for these constraints.&lt;/p&gt;
&lt;h2 id=&quot;composition-and-transformation&quot; style=&quot;position:relative;&quot;&gt;Composition and Transformation&lt;a href=&quot;#composition-and-transformation&quot; aria-label=&quot;composition and transformation permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far we’ve looked at the basic correspondences between types and logic. Now let’s talk about how to combine and transform them.&lt;/p&gt;
&lt;h4 id=&quot;function-composition-chaining-inferences&quot; style=&quot;position:relative;&quot;&gt;Function Composition: Chaining Inferences&lt;a href=&quot;#function-composition-chaining-inferences&quot; aria-label=&quot;function composition chaining inferences permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In logic, there’s the syllogism. The most basic hypothetical syllogism can be expressed as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.
If &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.
Therefore, if &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; then &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, if “eating makes you full” is true and “being full makes you sleepy” is true, then “eating makes you sleepy” is also true. In programming, this is expressed as function composition.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parseNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPositive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Connecting string → number&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// and number → boolean&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// gives us string → boolean&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPositiveString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parseNumber&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isPositive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;isPositiveString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;42&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Chain enough small inferences and you get larger, more complex ones. That’s what makes function composition powerful, and why &lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;compose&lt;/code&gt;, Functors, and Monads come up so often in functional programming.&lt;/p&gt;
&lt;p&gt;In category theory, composition is the defining operation of a category. If you’re interested, see &lt;a href=&quot;/2024/01/30/category-theory-for-programmers-1-category/&quot;&gt;“Category Theory for Programmers - 1. Category: The Essence of Composition”&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;currying-a-logically-natural-transformation&quot; style=&quot;position:relative;&quot;&gt;Currying: A Logically Natural Transformation&lt;a href=&quot;#currying-a-logically-natural-transformation&quot; aria-label=&quot;currying a logically natural transformation permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Currying is the pattern of transforming a multi-argument function into a chain of single-argument functions. It makes composition easier because any function can be reduced to the common pattern of unary functions.&lt;/p&gt;
&lt;p&gt;An interesting point is that this transformation from multi-argument to single-argument functions is &lt;em&gt;always&lt;/em&gt; possible. Why?&lt;/p&gt;
&lt;p&gt;In logic, there’s an equivalence called the Exportation law, and currying is a pattern based on this concept:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;≡&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(A \land B) \rightarrow C \equiv A \rightarrow (B \rightarrow C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≡&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;“If (A and B) then C” is logically equivalent to “If A, then (if B then C).”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Strictly speaking, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(A \land B) \rightarrow C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; corresponds to “a function that takes a tuple of &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and returns &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;,” and JavaScript’s multi-argument functions are a practical approximation of this.&lt;/p&gt;
&lt;p&gt;In more everyday terms: “If you have flour and water, you can make dough” and “If you have flour, then (if you have water, you can make dough)” mean the same thing. This is why the transformation is always safe.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Takes two arguments at once&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDough&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Dough &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Takes one argument at a time (curried)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDoughCurried&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;water&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Dough &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Both are logically equivalent&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dough1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDough&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dough2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDoughCurried&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Currying is possible not because it’s merely a programming technique, but because it mirrors a logical equivalence.&lt;/p&gt;
&lt;h4 id=&quot;type-algebra-like-addition-and-multiplication&quot; style=&quot;position:relative;&quot;&gt;Type Algebra: Like Addition and Multiplication&lt;a href=&quot;#type-algebra-like-addition-and-multiplication&quot; aria-label=&quot;type algebra like addition and multiplication permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Have you heard the term Algebraic Data Types? It means that types support operations analogous to arithmetic in algebra.&lt;/p&gt;
&lt;p&gt;For example, there are product types and sum types. A representative product type is the tuple (“and”), and a sum type is the union type (“or”).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 2 values&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Bool&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Bool&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 2 * 2 = 4 values&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// [true, true], [true, false], [false, true], [false, false]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Three&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 3 values&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Five&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Three &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Bool&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// 3 + 2 = 5 values&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &apos;a&apos;, &apos;b&apos;, &apos;c&apos;, true, false&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is why they’re called Algebraic Data Types. When you look at types in terms of the number of possible values, sum types behave like addition and product types like multiplication.&lt;/p&gt;
&lt;p&gt;What’s even more interesting is that the distributive law from algebra also shows up in types. Mathematically:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;≡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \times (B + C) \equiv (A \times B) + (A \times C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≡&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In TypeScript, this structure becomes very clear in one particular feature: conditional types.&lt;/p&gt;
&lt;p&gt;TypeScript’s conditional types automatically distribute over union types. This property lets you directly observe the distributive law of type algebra:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PairWith&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Since boolean = true | false, this distributes into a union of three products&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// [string, number] | [string, false] | [string, true]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PairWith&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This example shows that when &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt; is the sum type &lt;code class=&quot;language-text&quot;&gt;number | boolean&lt;/code&gt;, the product type &lt;code class=&quot;language-text&quot;&gt;[A, B]&lt;/code&gt; distributes into the sum type &lt;code class=&quot;language-text&quot;&gt;[A, number] | [A, boolean]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At the type level, we see the same algebraic distributive law: &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;≡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \times (B + C) \equiv (A \times B) + (A \times C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≡&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;TypeScript’s type system doesn’t always automatically treat these distributed forms as identical types. But at the level of type computation and transformation rules, the ideas of algebraic data type addition, multiplication, and distribution are clearly alive.&lt;/p&gt;
&lt;p&gt;In category theory, products and sums are treated from an even more abstract perspective called Universal Construction. See &lt;a href=&quot;/2024/04/18/category-theory-for-programmers-9-function-types/&quot;&gt;“Category Theory for Programmers - 9. Function Types”&lt;/a&gt; for how these algebraic structures are extended.&lt;/p&gt;
&lt;h2 id=&quot;typescript-isnt-100-logically-sound&quot; style=&quot;position:relative;&quot;&gt;TypeScript Isn’t 100% Logically Sound&lt;a href=&quot;#typescript-isnt-100-logically-sound&quot; aria-label=&quot;typescript isnt 100 logically sound permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we’ve covered the basic concepts, let’s look at the TypeScript limitations I mentioned earlier.&lt;/p&gt;
&lt;p&gt;I said TypeScript partially borrows the Curry-Howard correspondence. What are its limits?&lt;/p&gt;
&lt;p&gt;TypeScript intentionally provides several escape hatches that can lead to logical contradictions, all in the name of practicality. I’ll cover two representative ones here.&lt;/p&gt;
&lt;p&gt;The first escape hatch is the existence of &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; and type assertions. &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; is a declaration to skip type checking entirely. In logical terms, it’s like “accepting anything as true without verification.” Type assertions via &lt;code class=&quot;language-text&quot;&gt;as&lt;/code&gt; are the same.&lt;/p&gt;
&lt;p&gt;These are escape hatches that bypass the proof system, which is why TypeScript becomes a language that permits logical contradictions.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Assigning a string to a number type&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt; z &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Forced type conversion&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The second escape hatch is corner cases in structural typing. Notably, function parameter bivariance, index signatures, and optional properties can all undermine logical interpretation.&lt;/p&gt;
&lt;p&gt;Logically, function parameters should be contravariant. In simple terms, if &lt;code class=&quot;language-text&quot;&gt;Dog&lt;/code&gt; is a subtype of &lt;code class=&quot;language-text&quot;&gt;Animal&lt;/code&gt;, then &lt;code class=&quot;language-text&quot;&gt;(animal: Animal) =&gt; void&lt;/code&gt; should be a subtype of &lt;code class=&quot;language-text&quot;&gt;(dog: Dog) =&gt; void&lt;/code&gt; — because a function that accepts a broader type can substitute for one that accepts a narrower type.&lt;/p&gt;
&lt;p&gt;But TypeScript treats method-syntax function declarations as bivariant:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; breed&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Handler&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;animal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Animal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dogHandler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// A function that only handles Dogs is assigned where Animal is expected&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Not caught even with strictFunctionTypes&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dog&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Dog&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;breed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  dogHandler&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cat&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Possible runtime error&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Index signatures can also lead to logical contradictions. Even when accessing a key that doesn’t exist on an object, TypeScript infers the declared type rather than &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; scores&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; alice&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bobScore &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; scores&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Type is number, actual value is undefined&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bobScore&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Runtime error&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you want stricter type checking, enable the &lt;code class=&quot;language-text&quot;&gt;noUncheckedIndexedAccess&lt;/code&gt; option in tsconfig to properly infer &lt;code class=&quot;language-text&quot;&gt;number | undefined&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, there’s the confusion between optional properties and &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. In a type like &lt;code class=&quot;language-text&quot;&gt;{ a?: string }&lt;/code&gt;, the state where &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; is &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; and the state where &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; doesn’t exist at all aren’t logically distinguished:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OK&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Both are treated as the same type, but&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Object.hasOwn(config1, &apos;timeout&apos;) and Object.hasOwn(config2, &apos;timeout&apos;) differ&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since TypeScript 4.4, the &lt;code class=&quot;language-text&quot;&gt;exactOptionalPropertyTypes&lt;/code&gt; option lets you more strictly distinguish between “doesn’t exist” and “exists as &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;.”&lt;/p&gt;
&lt;p&gt;These escape hatches are the result of TypeScript choosing practical JavaScript compatibility over 100% logical soundness.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; style=&quot;position:relative;&quot;&gt;Wrapping Up&lt;a href=&quot;#wrapping-up&quot; aria-label=&quot;wrapping up permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This post isn’t about how to use TypeScript better. If you’ve worked with types extensively in practice, most of the examples here are probably familiar.&lt;/p&gt;
&lt;p&gt;What I wanted to convey is a &lt;em&gt;perspective&lt;/em&gt;. Instead of seeing type errors as obstacles to get past, try reading them as a tool that tells you what contract you declared and where it’s breaking down.&lt;/p&gt;
&lt;p&gt;Once you start thinking this way, type errors hit differently. Less “why doesn’t this work” and more “what contract am I violating.”&lt;/p&gt;
&lt;p&gt;Type systems have more to say than we usually give them credit for.&lt;/p&gt;
&lt;p&gt;If you found this post interesting, check out the &lt;a href=&quot;/2024/01/30/category-theory-for-programmers-0-preface/&quot;&gt;“Category Theory for Programmers”&lt;/a&gt; series. It covers how composition, product and sum types, and function types are generalized in category theory, and how functors and natural transformations extend them further.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[타입 시스템은 왜 증명처럼 동작하는가]]></title><description><![CDATA[우리는 매일 타입을 사용하며, 무수한 타입 에러를 마주한다. 그때마다 에러 메시지를 읽고, 구글링해서 해결하긴 하지만 정작 “타입 시스템이 왜 이렇게 동작하는지”를 깊게 생각하며 문제를 해결하는 경우는 드물다. 타입을 쓸 줄 아는 것이 문법을 이해하는 것이라면, 타입 시스템을 이해하는 것은 그 문법이 왜 그렇게 설계되었는지에 대한 본질을 이해하는 것에 가깝다.]]></description><link>https://evan-moon.github.io/2026/01/25/types-as-proofs-typescript-hidden-math/</link><guid isPermaLink="false">20260125-types-as-proofs-typescript-hidden-math</guid><pubDate>Sun, 25 Jan 2026 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;우리는 매일 타입을 사용하며, 무수한 타입 에러를 마주한다. 그때마다 에러 메시지를 읽고, 구글링해서 해결하긴 하지만 정작 “타입 시스템이 왜 이렇게 동작하는지”를 깊게 생각하며 문제를 해결하는 경우는 드물다.&lt;/p&gt;
&lt;p&gt;타입을 쓸 줄 아는 것이 문법을 이해하는 것이라면, 타입 시스템을 이해하는 것은 그 문법이 왜 그렇게 설계되었는지에 대한 본질을 이해하는 것에 가깝다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;사실 이러한 이해를 돕기 위해 &lt;a href=&quot;/2024/01/30/category-theory-for-programmers-0-preface/&quot;&gt;“프로그래머를 위한 카테고리 이론”&lt;/a&gt; 시리즈를 번역하면서 카테고리, 펑터, 합성 같은 개념을 다뤘었는데, 지금 돌아보니 진입 장벽이 꽤 높은 내용이라, 조금 더 쉬운 버전의 포스팅을 다시 작성하려고 한다.&lt;/p&gt;
&lt;p&gt;그래서 이번 포스팅에서는 타입과 논리학의 대응 관계를 중심으로, 타입 검사기가 “통과”라고 말할 때 그것이 정확히 무엇을 의미하는지 살펴보려 한다.&lt;/p&gt;
&lt;h2 id=&quot;타입-검사는-정말-검사일-뿐일까&quot; style=&quot;position:relative;&quot;&gt;타입 검사는 정말 “검사”일 뿐일까&lt;a href=&quot;#%ED%83%80%EC%9E%85-%EA%B2%80%EC%82%AC%EB%8A%94-%EC%A0%95%EB%A7%90-%EA%B2%80%EC%82%AC%EC%9D%BC-%EB%BF%90%EC%9D%BC%EA%B9%8C&quot; aria-label=&quot;타입 검사는 정말 검사일 뿐일까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;TypeScript를 처음 배울 때 대부분의 개발자는 타입 시스템을 일종의 린터(linter)처럼 받아들인다. 마치 린터처럼 잘못된 타입을 넣으면 빨간 줄이 그어지고, 올바른 타입을 넣으면 통과하기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Error: Argument of type &apos;string&apos; is not assignable to parameter of type &apos;number&apos;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;틀린 말은 아니지만 이 관점에는 한 가지 빠진 것이 있다.&lt;/p&gt;
&lt;p&gt;타입 시스템은 단순히 에러를 잡는 도구가 아니다. 그 뒤에는 수학적 구조가 있고, 타입 검사를 통과한다는 것은 단순히 에러가 없다는 것 이상의 의미를 가진다. 타입은 논리학의 명제에 대응하고, 그 타입을 만족하는 코드는 그 명제의 증명에 대응한다.&lt;/p&gt;
&lt;p&gt;그렇다면 우리가 마주하는 타입 에러는 무엇일까? 단순한 실수일까, 아니면 우리가 암묵적으로 맺은 어떤 계약이 깨졌다는 신호일까.&lt;/p&gt;
&lt;p&gt;이 이야기를 이해하려면 가장 먼저 타입 시스템에 사용되는 기본적인 수학의 개념들에 대한 이야기를 해야한다.&lt;/p&gt;
&lt;h2 id=&quot;타입-시스템의-세-기둥-형식-논리학-집합론-람다-대수&quot; style=&quot;position:relative;&quot;&gt;타입 시스템의 세 기둥: 형식 논리학, 집합론, 람다 대수&lt;a href=&quot;#%ED%83%80%EC%9E%85-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EC%84%B8-%EA%B8%B0%EB%91%A5-%ED%98%95%EC%8B%9D-%EB%85%BC%EB%A6%AC%ED%95%99-%EC%A7%91%ED%95%A9%EB%A1%A0-%EB%9E%8C%EB%8B%A4-%EB%8C%80%EC%88%98&quot; aria-label=&quot;타입 시스템의 세 기둥 형식 논리학 집합론 람다 대수 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;타입 시스템은 세 가지 수학적 아이디어 위에 서 있다. 갑자기 수학에 대한 이야기가 나와서 어렵게 느껴질 수 있지만 걱정할 필요 없다. 이 개념들은 우리가 이미 코드로 매일 다루고 있는 것들이다.&lt;/p&gt;
&lt;h4 id=&quot;형식-논리학-참이다를-증명한다는-것&quot; style=&quot;position:relative;&quot;&gt;형식 논리학: “참이다”를 증명한다는 것&lt;a href=&quot;#%ED%98%95%EC%8B%9D-%EB%85%BC%EB%A6%AC%ED%95%99-%EC%B0%B8%EC%9D%B4%EB%8B%A4%EB%A5%BC-%EC%A6%9D%EB%AA%85%ED%95%9C%EB%8B%A4%EB%8A%94-%EA%B2%83&quot; aria-label=&quot;형식 논리학 참이다를 증명한다는 것 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;형식 논리학은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이거나 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다 같은 논리들을 다루는 체계다. 핵심 아이디어는 “참이라고 주장하려면, 그것을 증명해야 한다는 것”이다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기호&lt;/th&gt;
&lt;th&gt;일상적 의미&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;∧&lt;/td&gt;
&lt;td&gt;그리고&lt;/td&gt;
&lt;td&gt;“우산도 있고 장화도 있다”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;∨&lt;/td&gt;
&lt;td&gt;또는&lt;/td&gt;
&lt;td&gt;“버스를 타거나 지하철을 탄다”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;→&lt;/td&gt;
&lt;td&gt;~하면 ~이다&lt;/td&gt;
&lt;td&gt;“비가 오면 땅이 젖는다”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;예를 들어 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∨&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \lor B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∨&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참이라고 말하려면, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참임을 보여주거나, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참임을 보여줘야 한다. “둘 중 하나는 참이겠지만 어느 쪽인지는 몰라요”라는 식의 주장은 증명으로 인정되지 않는다.&lt;/p&gt;
&lt;p&gt;그리고 일단 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∨&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \lor B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∨&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;“를 받아들이면, 그로부터 무언가를 이끌어내기 위해서는 두 경우(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)를 모두 다루는 분기가 필요하다는 것도 알 수 있다. 이는 마치 코드에서 &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt;를 다룰 때 타입 좁히기가 필요한 이유와 같은 구조다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// &quot;A 또는 B&quot;가 참이라고 주장하려면, 둘 중 하나를 구체적으로 보여줘야 한다&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &quot;둘 중 하나겠지&quot;로는 안 된다. 어떤 경우인지 확인해야 한다.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;string&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;집합론-타입은-원소들의-모임이다&quot; style=&quot;position:relative;&quot;&gt;집합론: 타입은 원소들의 모임이다&lt;a href=&quot;#%EC%A7%91%ED%95%A9%EB%A1%A0-%ED%83%80%EC%9E%85%EC%9D%80-%EC%9B%90%EC%86%8C%EB%93%A4%EC%9D%98-%EB%AA%A8%EC%9E%84%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;집합론 타입은 원소들의 모임이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;집합은 비슷한 것들을 모아놓은 주머니라고 생각하면 된다. 예를 들어 &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; 타입은 프로그램 상에서 표현할 수 있는 모든 숫자를 담은 주머니, &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; 타입은 모든 문자열을 담은 주머니이고, &lt;code class=&quot;language-text&quot;&gt;number | string&lt;/code&gt;은 이 두 주머니의 내용물을 합친 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 숫자 주머니에서 하나 꺼냄&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 문자열 주머니에서 하나 꺼냄&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 둘 중 아무 주머니에서나 꺼낸 것&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;타입을 집합으로 생각하면 많은 것이 자연스러워진다. &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입은 빈 주머니이고, &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; 타입은 세상 모든 것이 들어있는 주머니다.&lt;/p&gt;
&lt;p&gt;물론 엄밀하게 이야기하자면 TypeScript의 실제 타입 시스템은 순수한 집합론과 다른 부분이 있지만, 이 정도 이해로도 직관을 잡기에는 충분하다.&lt;/p&gt;
&lt;h4 id=&quot;람다-대수-함수-그-이상의-의미&quot; style=&quot;position:relative;&quot;&gt;람다 대수: 함수, 그 이상의 의미&lt;a href=&quot;#%EB%9E%8C%EB%8B%A4-%EB%8C%80%EC%88%98-%ED%95%A8%EC%88%98-%EA%B7%B8-%EC%9D%B4%EC%83%81%EC%9D%98-%EC%9D%98%EB%AF%B8&quot; aria-label=&quot;람다 대수 함수 그 이상의 의미 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;람다 대수는 1930년대 알론조 처치(Alonzo Church)라는 수학자가 “계산이란 무엇인가?”라는 질문에 답하려고 만든 개념이다. 이름은 무시무시하게 느껴지지만, 사실 개발자라면 이미 매일 쓰고 있는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 람다 대수로 표현하면 λx.x&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 람다 대수로 표현하면 λx.λy.x&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;화살표 함수는 람다(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;λ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\lambda&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;λ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) 표기의 현대적 문법에 가깝고, 람다 대수의 핵심 아이디어인 “함수 정의와 적용”을 가장 직접적으로 보여준다. 처치가 증명한 놀라운 사실은 이 단순한 개념만으로도 사칙연산, 조건문, 반복문, 심지어 숫자 자체까지 모두 표현할 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;물론 실제 JavaScript 함수는 부수효과, 예외, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; 바인딩, 런타임 객체 모델 같은 것 때문에 람다 대수와 100% 동일하다고 말하기는 어렵다. 하지만 “계산이란 결국 함수를 만들고 적용하는 것”이라는 핵심적인 통찰은 공유하기 때문에 이 정도 이해로도 충분하다.&lt;/p&gt;
&lt;h4 id=&quot;세-세계가-만나는-지점-curry-howard-대응&quot; style=&quot;position:relative;&quot;&gt;세 세계가 만나는 지점: Curry-Howard 대응&lt;a href=&quot;#%EC%84%B8-%EC%84%B8%EA%B3%84%EA%B0%80-%EB%A7%8C%EB%82%98%EB%8A%94-%EC%A7%80%EC%A0%90-curry-howard-%EB%8C%80%EC%9D%91&quot; aria-label=&quot;세 세계가 만나는 지점 curry howard 대응 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;그렇다면 이 세 가지 개념이 타입 시스템에 어떻게 사용되고 있다는 것일까? 이 질문에 대한 답을 하려면 이 개념들을 하나로 묶어주는 Curry-Howard 대응에 대해 이야기해야한다.&lt;/p&gt;
&lt;p&gt;Curry-Howard 대응 또는 Curry-Howard 동형이라고 불리는 개념은 컴퓨터 프로그램과 논리적 증명을 직접적으로 연관시키는 대응 관계를 의미한다. 더 정확하게 말하자면 논리학의 증명 규칙과 타입 시스템의 타입 규칙이 서로 대응한다는 주장이다.&lt;/p&gt;
&lt;p&gt;이 개념은 이미 1930년대에 하스켈 커리(Haskell Curry)라는 논리학자가 람다 대수에 타입을 붙여보다가 발견한 규칙이며, 이후 1969년 윌리엄 하워드(William Howard)가 이 발견을 더 깊이 파고들어 아래와 같은 대응 관계를 확립했다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;논리학에서&lt;/th&gt;
&lt;th&gt;프로그래밍에서&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;명제&lt;/td&gt;
&lt;td&gt;타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;증명&lt;/td&gt;
&lt;td&gt;프로그램&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A이면 B&lt;/td&gt;
&lt;td&gt;A를 받아 B를 반환하는 함수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A 그리고 B&lt;/td&gt;
&lt;td&gt;A와 B를 둘 다 가진 튜플/객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A 또는 B&lt;/td&gt;
&lt;td&gt;A이거나 B인 유니온 타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;거짓 (증명 불가능)&lt;/td&gt;
&lt;td&gt;never (값이 존재할 수 없음)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;결국 이 개념의 핵심을 한 줄로 요약해보면 아래와 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;타입은 명제에 대응하고, 그 타입의 값을 만드는 프로그램은 그 명제의 증명에 대응한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TypeScript는 실용을 위해 이 아이디어를 부분적으로 차용한 언어다. 부분적으로 차용한 언어라는 의미는 &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;나 타입 단언 같은 탈출구가 있기 때문이다.&lt;/p&gt;
&lt;p&gt;그래서 이 글에서 “증명”이라는 표현은 “타입 규칙이 요구하는 계약을 충족한다” 정도로 이해하면 된다. TypeScript의 한계에 대해서는 글 끝에서 다시 이야기해보겠다.&lt;/p&gt;
&lt;h2 id=&quot;타입으로-보는-논리적-구조&quot; style=&quot;position:relative;&quot;&gt;타입으로 보는 논리적 구조&lt;a href=&quot;#%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%EB%B3%B4%EB%8A%94-%EB%85%BC%EB%A6%AC%EC%A0%81-%EA%B5%AC%EC%A1%B0&quot; aria-label=&quot;타입으로 보는 논리적 구조 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;그렇다면 이 Curry-Howard 대응이 실제로 어떻게 나타나는지 하나씩 뜯어보자.&lt;/p&gt;
&lt;h4 id=&quot;함수-a이면-b의-증거&quot; style=&quot;position:relative;&quot;&gt;함수: “A이면 B”의 증거&lt;a href=&quot;#%ED%95%A8%EC%88%98-a%EC%9D%B4%EB%A9%B4-b%EC%9D%98-%EC%A6%9D%EA%B1%B0&quot; aria-label=&quot;함수 a이면 b의 증거 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;먼저 가장 핵심적인 대응인 함수 타입부터 살펴보자. 함수 타입 &lt;code class=&quot;language-text&quot;&gt;(a: A) =&gt; B&lt;/code&gt;는 논리학에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 해당한다.&lt;/p&gt;
&lt;p&gt;이게 무슨 말일까? 이해를 돕기 위해 조금 더 일상적인 비유로 풀어보면 이렇다.&lt;/p&gt;
&lt;p&gt;친구가 “네가 밀가루를 주면, 내가 빵을 만들어줄게”라고 약속했다고 하자. 이것은 “밀가루 → 빵”이라는 명제다. 그렇다면 이 약속이 진짜인지는 어떻게 확인할 수 있을까? 간단하다. 실제로 밀가루를 줬을 때 빵이 나오면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bread &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 밀가루를 반죽하고, 발효시키고, 굽는 과정을 거친 뒤...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; bread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수가 타입 검사를 통과한다는 것은, “밀가루를 주면 빵을 만들 수 있다”는 약속이 타입 규칙 안에서 이행 가능함을 보여준 것이다. 함수의 구현체 자체가 그 계약의 이행인 셈이다.&lt;/p&gt;
&lt;p&gt;그렇다면 반대로 타입 에러가 발생한다면 어떻게 되는 걸까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bread &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Error: Type &apos;Flour&apos; is not assignable to type &apos;Bread&apos;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; flour&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;원래 밀가루를 주면 빵을 만들어서 주기로 했는데, 뜬금없이 밀가루를 다시 돌려줬으니 이것은 계약 불이행이라고 볼 수 있고, 따라서 타입 에러가 발생한다.&lt;/p&gt;
&lt;p&gt;또한 이 계약과 구조가 제대로 지켜지면 이제 우리는 함수의 동작 결과를 추론할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;논리학에는 전건 긍정(Modus Ponens)이라는 추론 규칙이 있는데, 간단하게 정리해보면 아래와 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다”가 참이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참이면, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;도 참이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;예를 들어 “비가 오면 땅이 젖는다”는 명제가 참이고 “비가 온다”라는 명제도 참이라면, 이에 따라 “땅이 젖는다”라는 명제도 참이라는 것을 손쉽게 추론할 수 있다. 이 구조는 프로그래밍에서 함수 호출과 같은 구조이기 때문에 우리는 함수의 결과 타입을 추론할 수 있게 되는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// &quot;밀가루 → 빵&quot; 약속&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Bread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  

&lt;span class=&quot;token comment&quot;&gt;// 밀가루가 있음&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFlour&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 따라서 빵을 얻음&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bread&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeBread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수 &lt;code class=&quot;language-text&quot;&gt;makeBread&lt;/code&gt;는 “밀가루를 주면 빵을 만들어준다”라는 명제이다. 즉, 이 명제가 참이고 “밀가루를 준다”라는 명제도 참이라면 자연스럽게 &lt;code class=&quot;language-text&quot;&gt;bread&lt;/code&gt; 변수에 담기는 값이 &lt;code class=&quot;language-text&quot;&gt;Bread&lt;/code&gt; 타입이라는 명제도 참이 되는 것이다.&lt;/p&gt;
&lt;p&gt;우리가 매일 하는 함수의 호출과 결과 타입의 추론은 이러한 논리적 추론과 같은 구조를 가지고 있는 것이다.&lt;/p&gt;
&lt;h4 id=&quot;튜플-그리고의-증거&quot; style=&quot;position:relative;&quot;&gt;튜플: “그리고”의 증거&lt;a href=&quot;#%ED%8A%9C%ED%94%8C-%EA%B7%B8%EB%A6%AC%EA%B3%A0%EC%9D%98-%EC%A6%9D%EA%B1%B0&quot; aria-label=&quot;튜플 그리고의 증거 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;논리학의 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 그리고 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;“는 프로그래밍의 튜플이나 객체에 해당한다.&lt;/p&gt;
&lt;p&gt;일상적인 예로 생각해보자. 해외여행을 가려면 “여권이 있고 비행기 표도 있다”는 조건을 만족해야 한다. 이 조건을 충족하려면? 여권과 비행기 표를 둘 다 보여주면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CanTravel&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Passport&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Ticket&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// &quot;여행 가능&quot; 조건의 충족 = 여권과 티켓을 모두 갖춘 튜플&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; proof&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CanTravel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;myPassport&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; myTicket&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;CanTravel&lt;/code&gt; 타입이 만족했다면, 다른 말로 “여권도 있고 비행기 표도 있다”는 조건이 만족했다면 아래와 같이 &lt;code class=&quot;language-text&quot;&gt;CanTravel&lt;/code&gt; 타입의 튜플에서 여권이나 비행기표 모두 자유롭게 꺼내올 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPassport&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;travel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CanTravel&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Passport &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// &quot;A 그리고 B&quot;에서 A를 꺼냄&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; travel&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTicket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;travel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CanTravel&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Ticket &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// &quot;A 그리고 B&quot;에서 B를 꺼냄&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; travel&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것은 논리학에서 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \land B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;도 참이다”라는 규칙과 같은 구조다. 튜플에서 요소를 꺼내는 것이 논리적 추론과 대응되는 셈이다.&lt;/p&gt;
&lt;h4 id=&quot;유니온-또는의-증거&quot; style=&quot;position:relative;&quot;&gt;유니온: “또는”의 증거&lt;a href=&quot;#%EC%9C%A0%EB%8B%88%EC%98%A8-%EB%98%90%EB%8A%94%EC%9D%98-%EC%A6%9D%EA%B1%B0&quot; aria-label=&quot;유니온 또는의 증거 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;TypeScript의 유니온 타입 &lt;code class=&quot;language-text&quot;&gt;A | B&lt;/code&gt;는 논리학의 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 또는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;“에 해당한다. 여기서 중요한 점은 우리가 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 또는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;“가 참이라고 주장하려면 반드시 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참이라는 사실을 보여주거나, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 참이라는 사실을 보여줘야 한다는 것이다. 두 논리 중 하나를 구체적으로 제시해야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentMethod&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CreditCard &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; BankTransfer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// &quot;신용카드 또는 계좌이체&quot;의 충족 = 둘 중 하나를 구체적으로 제시&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payment1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;credit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cardNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1234...&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payment2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bank&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; accountNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;5678...&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;또한 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 또는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;“라는 명제가 참이라고 해도 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 둘 중 뭐가 참인지 구체적으로 확인하기 전까지는 알 수가 없다는 것과 같다.&lt;/p&gt;
&lt;p&gt;그래서 이 명제로부터 다른 무언가를 이끌어내려면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 대한 처리를 모두 해줘야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Receipt &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;credit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// A인 경우 처리&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;chargeCreditCard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// B인 경우 처리&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processBankTransfer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것이 TypeScript에서 Exhaustiveness check가 중요한 이유다. 논리적으로 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 또는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;“를 다룰 때는 두 경우 모두에 대한 전략이 있어야만 완전한 처리가 되기 때문이다.&lt;/p&gt;
&lt;p&gt;다만 TypeScript가 모든 케이스를 다뤘는지 자동으로 체크해주는 것은 설정과 코드 패턴에 따라 달라진다. 그러니 확실하게 Exhaustiveness check를 강제하고 싶다면 아래와 같은 패턴을 사용하는 것이 좋다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assertNever&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Unexpected value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Shape&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;circle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; radius&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;square&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; side&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;triangle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; height&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;area&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shape&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Shape&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shape&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;circle&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;radius &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;square&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;side &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Argument of type &apos;{ type: &quot;triangle&quot;; height: number; }&apos; is not assignable to parameter of type &apos;never&apos;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assertNever&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shape&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;기본적으로 유니온 타입의 모든 케이스를 처리했다면 &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt;에 도달할 일이 없고, &lt;code class=&quot;language-text&quot;&gt;shape&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입이 된다. 하지만 만약 새로운 도형을 추가했는데 처리를 깜빡했다면, &lt;code class=&quot;language-text&quot;&gt;shape&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입이 아니게 되고 컴파일 에러가 발생한다.&lt;/p&gt;
&lt;h4 id=&quot;never-불가능의-표현&quot; style=&quot;position:relative;&quot;&gt;never: “불가능”의 표현&lt;a href=&quot;#never-%EB%B6%88%EA%B0%80%EB%8A%A5%EC%9D%98-%ED%91%9C%ED%98%84&quot; aria-label=&quot;never 불가능의 표현 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;TypeScript의 &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입은 “이런 값은 존재할 수 없다”를 의미한다. 논리학에서는 이것을 모순 또는 거짓이라고 표현한다.&lt;/p&gt;
&lt;p&gt;앞서 언급했던 집합론으로 비유하자면, &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입은 빈 주머니다. 즉, &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;라는 주머니 안에는 아무것도 없고, 앞으로도 없을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;throwError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 이 함수는 정상적으로 반환되지 않는다&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 반환값이 &quot;존재할 수 없다&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 논리학의 재미있는 원리 하나가 나온다. 바로 “모순으로부터는 무엇이든 도출할 수 있다”는 것이다. 이는 라틴어로 “Ex falso quodlibet”이라고 하는데, 쉽게 말하면 불가능한 상황이 발생했다면, 그 다음에는 뭐든지 가능하다는 것이다.&lt;/p&gt;
&lt;p&gt;이 원리는 타입스크립트에서 아래와 같은 함수를 선언해봄으로써 구현해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;absurd&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// never에서는 어떤 타입으로든 변환 가능&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 ”&lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;이면 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;이다”라는 규칙을 표현하고 있다. 한번 &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입을 다른 구체적인 타입으로 바꿔보면 바로 에러가 발생하는 것을 알 수 있다. &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;는 거짓, 모순이기 때문이 그 다음에는 어떤 타입이 오든 논리적으로 틀린 것이 아닌 것이다.&lt;/p&gt;
&lt;p&gt;사실 이 부분도 정확하게 뜯어보면 TypeScript가 Ex falso을 정확하게 구현한 것은 아니긴 하다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입은 모든 타입의 서브 타입으로 취급되는 바닥 타입(Bottom Type)이기 때문에, &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입의 값은 어떤 타입 위치에도 대입 가능한 것으로 간주된다. 논리학의 Ex falso 원리와 닮긴 했지만 실제로는 서브타이핑의 결과라고 볼 수 있다.&lt;/p&gt;
&lt;h4 id=&quot;제네릭-모든-경우에-통하는-계약&quot; style=&quot;position:relative;&quot;&gt;제네릭: “모든 경우에 통하는” 계약&lt;a href=&quot;#%EC%A0%9C%EB%84%A4%EB%A6%AD-%EB%AA%A8%EB%93%A0-%EA%B2%BD%EC%9A%B0%EC%97%90-%ED%86%B5%ED%95%98%EB%8A%94-%EA%B3%84%EC%95%BD&quot; aria-label=&quot;제네릭 모든 경우에 통하는 계약 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;우리는 제네릭을 처음 배울 때 보통 “타입을 나중에 정하는 것”이라고 배운다. 사실 이것도 틀린 말은 아니지만, 제네릭이 의미하는 바는 더 심오하다.&lt;/p&gt;
&lt;p&gt;논리학에는 전칭 명제라는 것이 있는데, 이는 “모든 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 대해 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;P(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 성립한다”는 형태의 명제다. 예를 들어 “모든 사람은 죽는다”처럼 말이다.&lt;/p&gt;
&lt;p&gt;그리고 제네릭 함수는 바로 이 전칭 명제와 비슷한 구조를 가진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 “모든 타입 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;에 대해, &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;를 주면 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;를 돌려줄 수 있다”는 계약을 표현한다.&lt;/p&gt;
&lt;p&gt;여기서 중요한 것은 “모든 경우”에 대해 성립함을 보여야한다는 점인데, 이게 가능하려면 어떠한 특정 경우에 대한 가정도 하면 안된다.&lt;/p&gt;
&lt;p&gt;그래서 우리가 제네릭 타입을 사용했을 때 아래와 같은 가정을 하면 바로 타입 에러가 발생하는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;broken&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 모든 T가 number임을 가정하면...&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Operator &apos;+&apos; cannot be applied to types &apos;T&apos; and &apos;number&apos;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같이 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;라고 가정하는 순간, 이것은 더 이상 모든 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;에 대한 계약이 아니라, &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;에 대한 계약으로 범위가 좁아져 버린다. 더이상 전칭 명제라고 보기 어려운 것이다.&lt;/p&gt;
&lt;p&gt;그래서 우리는 “모든” 이라는 전제에 제약을 추가함으로서 이 문제를 해결할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;addOne&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같이 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;를 상속받았다면 자연스럽게 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;는 이제 ”&lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;의 부분 집합인 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;“로 개념이 변경된다. 즉, “모든” 이라는 개념의 범위를 조정하는 제약을 거는 것이다. 그래서 우리는 이런 제약을 걸때 &lt;code class=&quot;language-text&quot;&gt;extends&lt;/code&gt;라는 상속 키워드를 사용한다.&lt;/p&gt;
&lt;h2 id=&quot;합성과-변환&quot; style=&quot;position:relative;&quot;&gt;합성과 변환&lt;a href=&quot;#%ED%95%A9%EC%84%B1%EA%B3%BC-%EB%B3%80%ED%99%98&quot; aria-label=&quot;합성과 변환 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지는 타입과 논리학의 기본적인 대응 관계를 살펴봤다. 이제부터는 이것들을 조합하고 변환하는 방법에 대해서 이야기해보도록 하자.&lt;/p&gt;
&lt;h4 id=&quot;함수-합성-추론을-연결하기&quot; style=&quot;position:relative;&quot;&gt;함수 합성: 추론을 연결하기&lt;a href=&quot;#%ED%95%A8%EC%88%98-%ED%95%A9%EC%84%B1-%EC%B6%94%EB%A1%A0%EC%9D%84-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0&quot; aria-label=&quot;함수 합성 추론을 연결하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;논리학에는 삼단논법이라는 것이 있다. 가장 기본적인 정언적 삼단논법은 “만약 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라면, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다”로 표현할 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 삼단논법은 가정을 기반으로 한 가언적 삼단논법으로 표현할 수도 있는데, 이 경우 아래와 같은 명제가 된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다.
&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다.
그러므로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;예를 들어 “밥을 먹으면 배부르다”라는 명제가 참이고, “배부르면 잠이온다”라는 명제가 참이라면, “밥을 먹으면 잠이 온다”라는 명제도 참이라는 것이다. 그리고 이것이 프로그래밍에서는 함수의 합성으로 표현된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parseNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPositive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// string → number와&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// number → boolean을 연결하면&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// string → boolean이 된다&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPositiveString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parseNumber&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isPositive&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;isPositiveString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;42&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이는 마치 작은 추론들을 연결해서 더 크고 복잡한 추론을 만드는 것과 동일한데, 이렇게 작고 간단한 구조를 쌓아나가며 큰 구조를 만들 수 있다는 점이 함수 합성이 강력한 이유이다.&lt;/p&gt;
&lt;p&gt;그래서 함수형 프로그래밍에서는 &lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;compose&lt;/code&gt;와 같은 개념이나 펑터(Functor)나 모나드(Monad)와 같이 함수의 합성과 관련된 개념들이 핵심이 된다.&lt;/p&gt;
&lt;p&gt;사실 카테고리 이론에서는 이 합성이야말로 카테고리의 본질이라고 말한다. 만약 관심이 있다면 &lt;a href=&quot;/2024/01/30/category-theory-for-programmers-1-category/&quot;&gt;“프로그래머를 위한 카테고리 이론 - 1. 카테고리: 합성의 본질”&lt;/a&gt;도 참고해보자.&lt;/p&gt;
&lt;h4 id=&quot;커링-논리적으로-자연스러운-변환&quot; style=&quot;position:relative;&quot;&gt;커링: 논리적으로 자연스러운 변환&lt;a href=&quot;#%EC%BB%A4%EB%A7%81-%EB%85%BC%EB%A6%AC%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%9E%90%EC%97%B0%EC%8A%A4%EB%9F%AC%EC%9A%B4-%EB%B3%80%ED%99%98&quot; aria-label=&quot;커링 논리적으로 자연스러운 변환 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;커링(Currying)은 여러 인자를 받는 함수를 한 인자씩 받는 함수의 체인으로 바꾸는 패턴을 의미한다. 커링을 사용하면 어떤 함수든 단항 함수라는 공통의 패턴으로 만들 수 있기 때문에 합성하기가 편해진다는 장점이 있다.&lt;/p&gt;
&lt;p&gt;한 가지 재미있는 점은 다항 함수를 단항 함수의 합성으로 변환하는 것이 항상 가능하다는 점이다. 왜 이 변환이 항상 가능한 것일까?&lt;/p&gt;
&lt;p&gt;논리학에는 수출 법칙(Exportation)이라는 동치 관계가 있는데, 커링은 바로 이 개념을 활용한 패턴이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;≡&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(A \land B) \rightarrow C \equiv A \rightarrow (B \rightarrow C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≡&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;“(A 그리고 B)이면 C이다”와 “A이면 (B이면 C이다)“는 논리적으로 동치다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;엄밀히 말하면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(A \land B) \rightarrow C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 튜플로 받아 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 반환하는 함수”에 대응하며, JavaScript의 다중 인자 함수는 이를 실용적으로 근사한 형태라고 이해하는 것이 정확하다.&lt;/p&gt;
&lt;p&gt;조금 더 일상적인 상황을 예를 들어 보면, “밀가루와 물이 있으면 반죽을 만들 수 있다”라는 명제와 “밀가루가 있으면, (물이 있으면 반죽을 만들 수 있다)“라는 명제는 같은 의미를 가진다는 것이다. 그래서 이 변환은 항상 안전하게 진행된다는 것이 보장된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 두 인자를 한번에 받음&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDough&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Dough &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 한 인자씩 받음 (커링)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDoughCurried&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;water&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Dough &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 둘은 논리적으로 동등하다&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dough1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDough&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dough2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeDoughCurried&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flour&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 다항 함수를 단항 함수로 변경하는 커링이 가능한 이유는 단순한 프로그래밍 기법이 아니라 논리적 동치 관계와 닮아있기 때문이다.&lt;/p&gt;
&lt;h4 id=&quot;타입-대수-덧셈과-곱셈처럼&quot; style=&quot;position:relative;&quot;&gt;타입 대수: 덧셈과 곱셈처럼&lt;a href=&quot;#%ED%83%80%EC%9E%85-%EB%8C%80%EC%88%98-%EB%8D%A7%EC%85%88%EA%B3%BC-%EA%B3%B1%EC%85%88%EC%B2%98%EB%9F%BC&quot; aria-label=&quot;타입 대수 덧셈과 곱셈처럼 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;혹시 대수적 데이터 타입(Algebraic Data Type)이라는 말을 들어본 적이 있는가? 이 말은 타입에도 대수학에서의 사칙연산과 같은 연산 법칙들을 적용할 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;예를 들어 곱 타입과 합 타입이 있는데, 대표적인 곱 타입은 위에서 한번 언급했던 “그리고”를 의미하는 튜플, 그리고 합 타입은 “또는”을 의미하는 유니언 타입이 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 2가지 값&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Bool&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Bool&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 2 * 2 = 4가지 값&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// [true, true], [true, false], [false, true], [false, false]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Three&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 3가지 값&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Five&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Three &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Bool&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// 3 + 2 = 5가지 값&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &apos;a&apos;, &apos;b&apos;, &apos;c&apos;, true, false&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것이 대수적 데이터 타입(Algebraic Data Types)이라는 이름이 붙은 이유다. 타입을 값의 경우의 수 관점에서 바라보면 합 타입은 덧셈처럼, 그리고 곱 타입은 곱셈처럼 동작한다.&lt;/p&gt;
&lt;p&gt;더 흥미로운 점은 대수학에서처럼 타입에서도 분배법칙이 등장한다는 것이다. 수학적으로는 다음과 같은 관계가 성립한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;≡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \times (B + C) \equiv (A \times B) + (A \times C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≡&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TypeScript에서도 이 구조는 특정 지점에서 매우 명확하게 드러난다. 바로 조건부 타입(Conditional Type) 이다.&lt;/p&gt;
&lt;p&gt;TypeScript의 조건부 타입은 유니온 타입에 대해 자동으로 분배(distribute)된다. 이 성질을 이용하면 타입 대수의 분배법칙을 직접 확인할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PairWith&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// boolean = true | false이기 때문에 3가지 곱의 합으로 분배된다&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// [string, number] | [string, false] | [string, true]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PairWith&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 예시는 &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;number | boolean&lt;/code&gt;이라는 합 타입일 때, &lt;code class=&quot;language-text&quot;&gt;[A, B]&lt;/code&gt;라는 곱타입은 다시 &lt;code class=&quot;language-text&quot;&gt;[A, number] | [A, boolean]&lt;/code&gt;이라는 합 타입으로 분배될 수 있음을 보여준다.&lt;/p&gt;
&lt;p&gt;즉, 타입 레벨에서도 대수의 분배 법칙과 동일하게 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;≡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \times (B + C) \equiv (A \times B) + (A \times C)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≡&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 모습이 보여지는 것이다.&lt;/p&gt;
&lt;p&gt;물론 TypeScript의 타입 시스템은 이러한 분배 구조를 항상 자동으로 동일한 타입으로 취급하지는 않는다. 하지만 최소한 타입을 계산하고 변환하는 규칙의 수준에서는 대수적 데이터 타입의 덧셈, 곱셈, 분배라는 아이디어가 분명하게 살아있다고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;카테고리 이론에서는 이 곱과 합을 보편적 구성(Universal Construction)이라는 더 추상적인 관점에서 다룬다. &lt;a href=&quot;/2024/04/18/category-theory-for-programmers-9-function-types/&quot;&gt;“프로그래머를 위한 카테고리 이론 - 9. 함수 타입”&lt;/a&gt;에서 이 대수적 구조가 어떻게 확장되는지 볼 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;typescript는-100-논리적이지-않다&quot; style=&quot;position:relative;&quot;&gt;TypeScript는 100% 논리적이지 않다&lt;a href=&quot;#typescript%EB%8A%94-100-%EB%85%BC%EB%A6%AC%EC%A0%81%EC%9D%B4%EC%A7%80-%EC%95%8A%EB%8B%A4&quot; aria-label=&quot;typescript는 100 논리적이지 않다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;기본적인 개념들에 대해서 살펴봤다면, 이제는 필자가 위에서 언급했던 TypeScript의 한계에 대해 한번 알아보자.&lt;/p&gt;
&lt;p&gt;필자는 TypeScript가 Curry-Howard 대응을 부분적으로 차용한 언어라고 했는데, 그 한계가 뭘까?&lt;/p&gt;
&lt;p&gt;TypeScript는 언어의 실용성을 높이기 위해 의도적으로 논리적 모순을 초래할 수 있는 몇 가지 탈출구를 제공한다. 이 포스팅에서는 그 중 대표적인 두 가지에 대해서 이야기해보려 한다.&lt;/p&gt;
&lt;p&gt;첫 번째 탈출구는 &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;와 타입 단언의 존재이다. &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;는 어떤 타입이든 검사하지 않고 통과시키겠다는 선언이다. 즉, 논리학적으로 보면 “검증 없이 뭐든 참으로 인정”하는 것과 같다. &lt;code class=&quot;language-text&quot;&gt;as&lt;/code&gt;를 통한 타입 단언도 마찬가지다.&lt;/p&gt;
&lt;p&gt;이것들은 증명 체계를 우회하는 탈출구이고, 이로 인해 TypeScript는 논리적인 모순을 허용하는 언어가 되어버렸다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// number 타입에 문자열 할당&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; z &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 타입 강제 변환&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;두 번째 탈출구는 바로 구조적 타이핑의 코너 케이스들이다. 대표적으로는 함수 파라미터의 이변성(Bivariance), 인덱스 시그니처, 옵셔널 프로퍼티 등의 탈출구로 인해 논리적 해석이 흔들리는 경우가 존재한다.&lt;/p&gt;
&lt;p&gt;논리적으로 함수 파라미터는 반공변(Contravariant)적이어야 한다. 쉽게 말해 &lt;code class=&quot;language-text&quot;&gt;Dog&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Animal&lt;/code&gt;의 서브타입이라면, &lt;code class=&quot;language-text&quot;&gt;(animal: Animal) =&gt; void&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;(dog: Dog) =&gt; void&lt;/code&gt;의 서브타입이어야 한다는 것이다. 이는 더 넓은 타입을 받는 함수가 더 좁은 타입을 받는 함수를 대체할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 TypeScript는 메소드 문법으로 선언된 함수에서 이를 이변적으로 처리한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Dog&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; breed&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Handler&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;animal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Animal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dogHandler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Dog만 처리하는 함수인데 Animal을 받는 자리에 할당됨&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// strictFunctionTypes로도 잡히지 않음&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dog&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Dog&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;breed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  dogHandler&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cat&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 런타임 에러 가능&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 인덱스 시그니처 또한 논리적인 모순을 초래할 수 있다. 객체에서 존재하지 않는 키에 접근하더라도 TypeScript는 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;가 아닌 선언된 타입으로 추론하기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; scores&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; alice&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bobScore &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; scores&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 타입은 number, 실제 값은 undefined&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bobScore&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 런타임 에러&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;조금 더 엄밀한 타입 체크를 원한다면 tsconfig의 &lt;code class=&quot;language-text&quot;&gt;noUncheckedIndexedAccess&lt;/code&gt; 옵션을 활성화하면 제대로 &lt;code class=&quot;language-text&quot;&gt;number | undefined&lt;/code&gt;로 추론되도록 만들 수 있다.&lt;/p&gt;
&lt;p&gt;마지막으로 옵셔널 프로퍼티와 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;의 혼동도 문제가 된다. 예를 들어 &lt;code class=&quot;language-text&quot;&gt;{ a?: string }&lt;/code&gt;이라는 타입에서 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;인 상태와 아예 존재하지 않는 것이 논리적으로 구분되지 않는다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OK&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OK&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 둘 다 같은 타입으로 취급되지만,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Object.hasOwn(config1, &apos;timeout&apos;)과 Object.hasOwn(config2, &apos;timeout&apos;)은 다르다&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 부분 또한 TypeScript 4.4 이후 도입된 &lt;code class=&quot;language-text&quot;&gt;exactOptionalPropertyTypes&lt;/code&gt; 옵션을 사용하면 “존재하지 않음”과 ”&lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;로 존재함”을 더 엄밀하게 구분할 수 있다.&lt;/p&gt;
&lt;p&gt;이런 탈출구들은 TypeScript가 100% 논리적인 정합성보다는 실용적으로 JavaScript와의 호환성을 선택한 결과라고 볼 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이 글은 타입스크립트를 잘 쓰는 방법을 설명하려는 글은 아니다. 이미 실무에서 타입을 충분히 다뤄본 사람이라면, 여기서 등장하는 대부분의 예시는 익숙할 수도 있다.&lt;/p&gt;
&lt;p&gt;다만 필자가 이 글을 통해 전하고 싶었던 건, 타입 시스템을 대하는 관점에 가깝다. 타입 에러를 “통과시켜야 할 장애물”로 보는 대신, 내가 어떤 계약을 선언했고, 그 계약이 어디에서 깨지고 있는지를 읽어내는 도구로 바라보는 시선 말이다.&lt;/p&gt;
&lt;p&gt;이 관점이 한 번 자리 잡히면, 타입 에러를 대하는 태도도 자연스럽게 달라진다. 왜 안 되는지를 묻기 전에, 무슨 계약을 어기고 있는지를 먼저 떠올리게 된다.&lt;/p&gt;
&lt;p&gt;타입 시스템은 생각보다 많은 이야기를 하고 있다. 다만 그걸 단순한 컴파일 통과 여부로만 읽고 지나치기엔, 조금 아까운 도구일지도 모르겠다.&lt;/p&gt;
&lt;p&gt;이 글이 흥미로웠다면, &lt;a href=&quot;/2024/01/30/category-theory-for-programmers-0-preface/&quot;&gt;“프로그래머를 위한 카테고리 이론”&lt;/a&gt; 시리즈도 읽어보자. 여기서 다룬 합성, 곱과 합 타입, 함수 타입 같은 개념들이 카테고리 이론에서 어떻게 일반화되는지, 그리고 펑터나 자연 변환 같은 개념이 이 아이디어를 어떻게 확장하는지 볼 수 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[People Create Excellence, but Systems Make It Last]]></title><description><![CDATA[In this post, I want to talk about what I’ve been thinking about over the roughly two and a half years I’ve spent as a frontend chapter lead at Toss. My job and goal as a chapter lead at Toss is clear: make the Toss frontend chapter the most excellent engineering organization in the world.]]></description><link>https://evan-moon.github.io/2026/01/24/leading-frontend-organization/en/</link><guid isPermaLink="false">20260124-leading-frontend-organization-en</guid><pubDate>Sat, 24 Jan 2026 12:44:14 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I want to talk about what I’ve been thinking about over the roughly two and a half years I’ve spent as a frontend chapter lead at Toss.&lt;/p&gt;
&lt;p&gt;My job and goal as a chapter lead at Toss is clear: make the Toss frontend chapter the most excellent engineering organization in the world.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;There are many ways to define “excellence,” but what I believe truly matters isn’t creating excellence in the current moment. It’s building an organization that can march toward excellence on its own, even without me.&lt;/p&gt;
&lt;h2 id=&quot;organizational-excellence-is-built-from-individual-excellence&quot; style=&quot;position:relative;&quot;&gt;Organizational Excellence Is Built from Individual Excellence&lt;a href=&quot;#organizational-excellence-is-built-from-individual-excellence&quot; aria-label=&quot;organizational excellence is built from individual excellence permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;what-is-an-excellent-organization&quot; style=&quot;position:relative;&quot;&gt;What Is an Excellent Organization?&lt;a href=&quot;#what-is-an-excellent-organization&quot; aria-label=&quot;what is an excellent organization permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I believe an excellent organization is fundamentally a collection of excellent individuals. When exceptional people come together and work side by side, organizational excellence follows. And indeed, the Toss frontend chapter has many outstanding developers who quickly grasp complex problems, craft elegant solutions, and help each other grow.&lt;/p&gt;
&lt;p&gt;When leading a small organization, you can build excellence by establishing clear technical and cultural hiring standards and focusing on collecting exceptional talent. That’s why at my previous company, I remember pouring the most energy into hiring.&lt;/p&gt;
&lt;p&gt;But the Toss frontend chapter is a large organization — around 250 people across the broader community, with nearly 140 in the Toss Core frontend chapter where I work. Leading an organization this large requires a different approach than leading a small one.&lt;/p&gt;
&lt;p&gt;At this scale, simply gathering excellent individuals isn’t enough. With more diverse people joining, the organization needs significantly more energy to understand each person’s strengths and capabilities and make sound decisions.&lt;/p&gt;
&lt;h3 id=&quot;from-10-to-140-the-need-for-systems&quot; style=&quot;position:relative;&quot;&gt;From 10 to 140: The Need for Systems&lt;a href=&quot;#from-10-to-140-the-need-for-systems&quot; aria-label=&quot;from 10 to 140 the need for systems permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Back when the frontend chapter had around 10 people, everyone could know each other in detail — faces, names, personalities.&lt;/p&gt;
&lt;p&gt;But when I returned to Toss, the frontend chapter had already grown into a massive organization compared to before.&lt;/p&gt;
&lt;p&gt;Even within the same chapter, there are cases where people don’t know who else is on the team. If you’re not actively paying attention, you might not even notice when new hires join. The rules of the game are simply different with 10 people versus 140.&lt;/p&gt;
&lt;p&gt;Even a chapter lead, without making a deliberate effort, would find it extremely difficult to understand this many people’s strengths, growth trajectories, and motivations. Right now, individual effort from leads still covers things to some degree, but if the headcount keeps growing, there will inevitably come a point where even that becomes impossible.&lt;/p&gt;
&lt;p&gt;Information about individuals would fragment across the minds of multiple leads, and depending on who interacts with which lead, some people would naturally become more visible while others fade into the background.&lt;/p&gt;
&lt;p&gt;That’s why I came to think that the lead’s role in this game needs to shift: from “directly caring for people” to “building systems that make the organization excellent on its own.”&lt;/p&gt;
&lt;h2 id=&quot;spin-the-flywheel-that-creates-organizational-excellence&quot; style=&quot;position:relative;&quot;&gt;Spin the Flywheel That Creates Organizational Excellence&lt;a href=&quot;#spin-the-flywheel-that-creates-organizational-excellence&quot; aria-label=&quot;spin the flywheel that creates organizational excellence permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I mentioned, the key to building an excellent organization is designing one that naturally gravitates toward excellence on its own. This is similar to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Flywheel&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;flywheel effect&lt;/a&gt; borrowed from product development.&lt;/p&gt;
&lt;p&gt;The flywheel effect describes a structure where small, repeated impacts accumulate to produce increasingly larger outcomes. It requires a lot of energy at first, but once it starts spinning, momentum allows it to generate bigger results with less effort.&lt;/p&gt;
&lt;p&gt;Similarly, in organizational management, when individual activities connect into a virtuous cycle, excellence naturally accelerates.&lt;/p&gt;
&lt;p&gt;The flywheel I’ve designed for an excellent organization consists of six stages:&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Recruit&lt;/strong&gt;: Gather exceptional talent obsessed with growth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-awareness&lt;/strong&gt;: Understand the organization’s expectations and your current state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opportunity&lt;/strong&gt;: Give prepared talent chances to experience growth in small increments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recognition&lt;/strong&gt;: Deliver tangible and psychological rewards to those who’ve grown.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: People with positive experiences participate in chapter activities, making the organization more excellent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Branding&lt;/strong&gt;: Organize and share the chapter’s work externally.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;stage-1-recruit--gather-exceptional-talent-obsessed-with-growth&quot; style=&quot;position:relative;&quot;&gt;Stage 1: Recruit — Gather Exceptional Talent Obsessed with Growth&lt;a href=&quot;#stage-1-recruit--gather-exceptional-talent-obsessed-with-growth&quot; aria-label=&quot;stage 1 recruit  gather exceptional talent obsessed with growth permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Building an excellent organization requires a continuous inflow of exceptional talent. The important thing here isn’t simply finding skilled people, but people who are obsessed with growth and have high growth potential.&lt;/p&gt;
&lt;p&gt;Identifying these people during the hiring process matters, but what matters even more is branding that makes people on the outside think, “If I go there, I can grow even more” — naturally driving more applications to Toss.&lt;/p&gt;
&lt;p&gt;We need to concretely show what technical capabilities the Toss frontend chapter has and what kind of culture it fosters. This is exactly where Stage 6 (Branding) connects back to Stage 1 (Recruit).&lt;/p&gt;
&lt;h3 id=&quot;stage-2-self-awareness--view-organizational-expectations-and-personal-strengths-through-a-shared-language&quot; style=&quot;position:relative;&quot;&gt;Stage 2: Self-awareness — View Organizational Expectations and Personal Strengths Through a Shared Language&lt;a href=&quot;#stage-2-self-awareness--view-organizational-expectations-and-personal-strengths-through-a-shared-language&quot; aria-label=&quot;stage 2 self awareness  view organizational expectations and personal strengths through a shared language permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I believe growth always starts with self-awareness. So the growth that an excellent organization produces ultimately begins with how accurately each member recognizes their own capabilities and strengths.&lt;/p&gt;
&lt;p&gt;It’s similar to a strategy game. Think of Lü Bu and Zhuge Liang from the Romance of the Three Kingdoms. Both are exceptional talents, but the moment they’re given mismatched roles, their excellence vanishes. Assigning Lü Bu to domestic administration or sending Zhuge Liang into single combat would obviously produce poor results.&lt;/p&gt;
&lt;p&gt;The problem is that in reality, people often don’t know whether they’re a Lü Bu or a Zhuge Liang — or they might be a Lü Bu who says they want to do administration. I think this is less about willpower and more about a lack of self-awareness.&lt;/p&gt;
&lt;p&gt;That’s why I believe the first step toward growth in an excellent organization is helping members accurately recognize their own capabilities and strengths, then connecting them with the right growth opportunities.&lt;/p&gt;
&lt;p&gt;Along these lines, the Toss frontend chapter uses a tool called the Skill Tree. Rather than a device for defining excellence, it’s more like a reference line that helps members see their current capabilities and strengths more clearly, and articulate their next growth direction for themselves.&lt;/p&gt;
&lt;p&gt;Once someone can articulate their growth direction and strengths, leads use this information to coach them so their strengths translate into real outcomes and growth.&lt;/p&gt;
&lt;h3 id=&quot;stage-3-opportunity--let-people-experience-growth-in-small-increments&quot; style=&quot;position:relative;&quot;&gt;Stage 3: Opportunity — Let People Experience Growth in Small Increments&lt;a href=&quot;#stage-3-opportunity--let-people-experience-growth-in-small-increments&quot; aria-label=&quot;stage 3 opportunity  let people experience growth in small increments permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once self-awareness is established, what the organization needs to do next is clear: provide opportunities for members to take on challenges without pressure and experience small wins. No matter how well someone understands their strengths and current state, growth remains theoretical without a real arena to try things in.&lt;/p&gt;
&lt;p&gt;This conviction became sharper through a recent leadership survey. The results showed that interest in leadership roles was far greater than expected. However, a common response was: “I’m interested, but I don’t feel ready yet.”&lt;/p&gt;
&lt;p&gt;At first, I assumed members felt their capabilities were lacking. But looking at individual responses more closely, it was closer to “I don’t know what I should be preparing for or what capabilities I need to build.” The chapter wasn’t providing enough hints about the direction and methods of growth.&lt;/p&gt;
&lt;p&gt;So I decided we needed to create more of these opportunities and expose them more frequently. Growth isn’t built from a single giant leap — it’s built on many small wins. We need to create an environment where chapter members can take on challenges without hesitation.&lt;/p&gt;
&lt;p&gt;This problem awareness led to the creation of the Next F-Lead program. This program focuses on three core competencies: strategic thinking, interview skills, and 1-on-1 coaching. The goal isn’t to suddenly turn someone into a lead — it’s to let them experience the F-Lead role in small doses beforehand. Through this, members come to see leadership not as “something far removed from me” but as “a next step I can gradually prepare for.”&lt;/p&gt;
&lt;p&gt;Beyond Next F-Lead, we’re working to help members envision their next steps more clearly through various education and experience programs. The key isn’t pushing anyone in a specific direction — it’s creating an environment where each person can try things and choose for themselves.&lt;/p&gt;
&lt;p&gt;Someone who has experienced small wins can imagine bigger challenges, and that imagination translates into real action toward the next stage of growth. That’s why the Opportunity stage is so important in the flywheel.&lt;/p&gt;
&lt;h3 id=&quot;stage-4-recognition--let-people-experience-achievement-through-tangible-and-psychological-rewards&quot; style=&quot;position:relative;&quot;&gt;Stage 4: Recognition — Let People Experience Achievement Through Tangible and Psychological Rewards&lt;a href=&quot;#stage-4-recognition--let-people-experience-achievement-through-tangible-and-psychological-rewards&quot; aria-label=&quot;stage 4 recognition  let people experience achievement through tangible and psychological rewards permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Growth isn’t completed by experience alone. Recognition must follow for those who’ve produced growth. Positive feedback as a reward is easily underestimated in organizational management, but it’s one of the most important elements for re-accelerating the flywheel.&lt;/p&gt;
&lt;p&gt;Within the Toss frontend chapter, there are already many people contributing to the organization by showing their strengths — people who consistently share technical knowledge, participate in activities like the Open Source Committee or Code Quality Committee, or build and share tools that help colleagues work better.&lt;/p&gt;
&lt;p&gt;These contributions elevate the organization, but if their value isn’t made visible enough, even the contributors themselves may struggle to feel their own achievements. That’s why I believe these people need to be recognized more often and more clearly.&lt;/p&gt;
&lt;p&gt;The same goes for people in lead roles. They don’t just deliver their own results — they help colleagues grow right beside them. From the organization’s perspective, it’s an extremely important role. From the individual’s perspective, it’s no light responsibility. There’s a lot to do and a lot to think about. For me, every day working alongside these people is filled with gratitude, and their dedication absolutely deserves to be rewarded.&lt;/p&gt;
&lt;p&gt;That’s why the Toss frontend chapter is preparing a dedicated leadership education program for leads. Beyond just training, we’re also planning opportunities for deeper participation in chapter decision-making, along with explicit expansion of authority and roles. This isn’t just a reward — it’s a clear message: “The organization takes your growth seriously.”&lt;/p&gt;
&lt;p&gt;Recognition isn’t the end of achievement. It’s the signal that starts the next phase of growth. Someone who has experienced accomplishment naturally wants to contribute again, and that contribution makes the organization more excellent once more. That’s why the Recognition stage can’t be left out of the flywheel.&lt;/p&gt;
&lt;h3 id=&quot;stage-5-contribution--positive-experiences-make-the-organization-excellent&quot; style=&quot;position:relative;&quot;&gt;Stage 5: Contribution — Positive Experiences Make the Organization Excellent&lt;a href=&quot;#stage-5-contribution--positive-experiences-make-the-organization-excellent&quot; aria-label=&quot;stage 5 contribution  positive experiences make the organization excellent permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;People who’ve been recognized and experienced achievement naturally start contributing to the organization. And when these contributions are met with the recognition mentioned in Stage 4 — shout-outs, expanded authority, participation in decision-making — the behavior is naturally reinforced. This is the core of the flywheel.&lt;/p&gt;
&lt;p&gt;I believe an organization becomes excellent when knowledge sharing and vigorous debate appear frequently. These are what contribution looks like, and these contributions collectively make an organization excellent.&lt;/p&gt;
&lt;p&gt;The Toss frontend chapter has a long history of such contributions.&lt;/p&gt;
&lt;p&gt;In the early days when the team was small, efforts like building internal libraries, developing TDS (Toss Design System), and creating admin tools were all driven by this kind of contribution. Now it takes the form of technical tool and knowledge sharing, the Open Source Committee, the Code Quality Committee, Frontend Accelerator mentoring, user accessibility improvements, and more.&lt;/p&gt;
&lt;p&gt;Leads who completed Next F-Lead improve the program. Developers active in the Open Source Committee propose new libraries. Chapter members who’ve used the Skill Tree provide feedback. All of this is contribution.&lt;/p&gt;
&lt;p&gt;Systems are improved by individuals, and improved systems in turn make more individuals excellent. The small flywheel is already spinning.&lt;/p&gt;
&lt;h3 id=&quot;stage-6-branding--share-excellence-with-the-outside-world&quot; style=&quot;position:relative;&quot;&gt;Stage 6: Branding — Share Excellence with the Outside World&lt;a href=&quot;#stage-6-branding--share-excellence-with-the-outside-world&quot; aria-label=&quot;stage 6 branding  share excellence with the outside world permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The final stage is branding — organizing the excellent chapter’s activities and sharing them externally.&lt;/p&gt;
&lt;p&gt;Currently, the Toss frontend chapter is building its brand of excellence through various activities: the Open Source Committee, Frontend Accelerator mentoring, the Frontend Fundamentals documentation project, and the Bonfire YouTube content series, among others.&lt;/p&gt;
&lt;p&gt;For example, the Open Source Committee has produced several libraries including es-toolkit, es-hangul, and overlay-kit. &lt;a href=&quot;https://es-toolkit.dev/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;es-toolkit&lt;/a&gt; in particular has been adopted by big tech companies like Microsoft, as well as well-known tools like Storybook and Yarn. It currently sees around 9 million weekly downloads.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://frontend-fundamentals.com/code-quality/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Frontend Fundamentals&lt;/a&gt; and the Frontend Accelerator mentoring program aim to grow the broader frontend ecosystem. The hope is that this produces more excellent developers in the ecosystem, which in turn naturally funnels exceptional talent toward Toss — creating a virtuous cycle.&lt;/p&gt;
&lt;p&gt;Content like the &lt;a href=&quot;https://toss.tech/article/firesidechat_frontend_10&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Bonfire YouTube series&lt;/a&gt; is a good way to reach many developers at low cost. It shows the standards by which the Toss frontend chapter writes code and who the developers are, which creates branding effects.&lt;/p&gt;
&lt;p&gt;All of these activities deliver the message: “The Toss frontend chapter is an excellent organization.” People obsessed with growth who see this message are drawn to Toss. When branding works well, it feeds back into Stage 1 (Recruit), completing the flywheel.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing Thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The thing I value most as a leader is building “an organization that runs without me.” It might sound paradoxical, but that’s what real sustainability looks like.&lt;/p&gt;
&lt;p&gt;Reducing individual dependency and leaving behind clear standards and functioning systems. Making the flywheel keep spinning even when I go on vacation, focus on something else, or even leave this role entirely. That’s why I’ve spent the past two and a half years focusing not on directly caring for people, but on building systems that make the organization excellent on its own.&lt;/p&gt;
&lt;p&gt;A really excellent organization keeps producing excellent individuals. And those individuals make the organization even better.&lt;/p&gt;
&lt;p&gt;In truth, each system still has much room for improvement. The Skill Tree needs to become more refined. Next F-Lead needs to produce more leads. The recognition system is still being built. Above all, I’m still searching for a clear answer to whether all of this is truly “making the organization more excellent.”&lt;/p&gt;
&lt;p&gt;But I think the direction is right. Small wins are accumulating. Feedback from chapter members keeps flowing in. And most importantly, the small flywheel is actually spinning.&lt;/p&gt;
&lt;p&gt;Organizational management isn’t a problem that yields answers overnight. But with a clear direction and functioning systems, the flywheel should spin faster over time.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[조직의 탁월함은 사람으로 만들지만 지속성은 시스템이 만든다]]></title><description><![CDATA[이번 포스팅에서는 필자가 지금까지 약 2년 반 정도 토스에서 프론트엔드 챕터 리드로 일하면서 고민해왔던 내용에 대해 이야기하려고 한다. 필자가 토스팀에서 챕터 리드로서 해야하는 일, 그리고 목표는 명확하다. 토스 프론트엔드 챕터를 세상에서 가장 탁월한 조직으로 만들어내는 것이다.]]></description><link>https://evan-moon.github.io/2026/01/24/leading-frontend-organization/</link><guid isPermaLink="false">20260124-leading-frontend-organization</guid><pubDate>Sat, 24 Jan 2026 12:44:14 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 필자가 지금까지 약 2년 반 정도 토스에서 프론트엔드 챕터 리드로 일하면서 고민해왔던 내용에 대해 이야기하려고 한다.&lt;/p&gt;
&lt;p&gt;필자가 토스팀에서 챕터 리드로서 해야하는 일, 그리고 목표는 명확하다. 토스 프론트엔드 챕터를 세상에서 가장 탁월한 조직으로 만들어내는 것이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;이 탁월함에 대해서는 여러가지 정의를 할 수 있지만, 사실 중요한 것은 현재 상태에서 탁월함을 만들어내는 것보다 필자가 없어도 스스로 탁월함을 향해 나아갈 수 있는 조직이 되는 것이 핵심이라고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;조직의-탁월함은-개인의-탁월함이-모여-만들어진다&quot; style=&quot;position:relative;&quot;&gt;조직의 탁월함은 개인의 탁월함이 모여 만들어진다&lt;a href=&quot;#%EC%A1%B0%EC%A7%81%EC%9D%98-%ED%83%81%EC%9B%94%ED%95%A8%EC%9D%80-%EA%B0%9C%EC%9D%B8%EC%9D%98-%ED%83%81%EC%9B%94%ED%95%A8%EC%9D%B4-%EB%AA%A8%EC%97%AC-%EB%A7%8C%EB%93%A4%EC%96%B4%EC%A7%84%EB%8B%A4&quot; aria-label=&quot;조직의 탁월함은 개인의 탁월함이 모여 만들어진다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;탁월한-조직이란-무엇인가&quot; style=&quot;position:relative;&quot;&gt;탁월한 조직이란 무엇인가&lt;a href=&quot;#%ED%83%81%EC%9B%94%ED%95%9C-%EC%A1%B0%EC%A7%81%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;탁월한 조직이란 무엇인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;탁월한 조직은 기본적으로 탁월한 개인들의 집합이라고 생각한다. 탁월한 개인이 모여 서로에게 자극을 주고 받으며 등을 맞대고 함께 일할 수 있는 조직이 되면 자연스레 조직의 탁월함도 만들어지기 때문이다. 실제로 토스 프론트엔드 챕터에는 복잡한 문제를 빠르게 이해하고, 우아한 해결책을 만들어내고, 서로를 성장시키는 탁월한 개발자들이 많이 있다.&lt;/p&gt;
&lt;p&gt;규모가 작은 조직을 리딩할 때는 명확한 기술 / 문화적 채용 기준을 수립하고 탁월한 인재들을 수집하는 것에 집중함으로서 조직의 탁월함을 만들어볼 수 있다. 그래서 필자가 전직장에 있을 때는 채용에 가장 공을 들였던 기억이 난다.&lt;/p&gt;
&lt;p&gt;그러나 토스 프론트엔드 챕터는 커뮤니티 기준으로 250명, 필자가 몸담고 있는 토스 코어 프론트엔드 챕터만 140명에 가까운 대조직이다. 이렇게 큰 조직을 리딩할 때는 작은 조직과는 조금 다른 접근 방법이 필요하다.&lt;/p&gt;
&lt;p&gt;이 정도로 조직이 크다면 탁월한 개인들을 모으는 것만으로는 충분하지 않다. 더 다양하고 많은 사람들이 모이게 되면서 조직이 이 사람들의 강점과 역량을 파악하고 탁월한 의사결정을 하는데 더 많은 에너지가 필요하기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;10명에서-140명-시스템의-필요성&quot; style=&quot;position:relative;&quot;&gt;10명에서 140명, 시스템의 필요성&lt;a href=&quot;#10%EB%AA%85%EC%97%90%EC%84%9C-140%EB%AA%85-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1&quot; aria-label=&quot;10명에서 140명 시스템의 필요성 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;예전 프론트엔드 챕터가 10명 남짓이었을 시절에는 챕터원들이 서로에 대해 상세하게 파악하는 것이 가능했다. 인원이 적으니 얼굴도 이름도 성격도 알 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 필자가 다시 토스로 돌아왔을 때, 프론트엔드 챕터는 이미 예전에 비해 엄청난 대조직이 되어있었다.&lt;/p&gt;
&lt;p&gt;같은 챕터라고 해도 어떤 사람이 있는지 모르는 경우도 있으며 심지어 특별히 관심을 쓰지 않으면 어떤 신규입사자가 들어왔는지도 모른다. 애초에 10명일 때와 140명일 때는 게임의 룰 자체가 다른 것이다.&lt;/p&gt;
&lt;p&gt;심지어 챕터 리드조차 특별하게 신경을 쓰지 않는다면 이 많은 인원의 강점, 성장 곡선, 동기를 파악하는 것이 굉장히 어렵다. 지금은 그래도 리드 개인의 노력으로 어느 정도 커버가 되는 수준이지만 만약 여기서 인원이 더 늘어난다면 이마저도 불가능한 순간이 분명히 올 것이다.&lt;/p&gt;
&lt;p&gt;개인에 대한 정보는 여러 명의 리드들의 머릿속에 파편화될 것이며, 리드와의 상호작용 여부에 따라 누군가는 더 잘 보이고 누군가는 덜 보이는 상황이 발생하게 될 것이 뻔하다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 이 게임에서 리드의 역할이 “사람을 직접 케어하는 것”에서 “조직을 저절로 탁월하게 만드는 시스템을 구축하는 것”으로 변화해야한다고 생각했다.&lt;/p&gt;
&lt;h2 id=&quot;조직의-탁월함을-만드는-플라이휠을-굴려라&quot; style=&quot;position:relative;&quot;&gt;조직의 탁월함을 만드는 플라이휠을 굴려라&lt;a href=&quot;#%EC%A1%B0%EC%A7%81%EC%9D%98-%ED%83%81%EC%9B%94%ED%95%A8%EC%9D%84-%EB%A7%8C%EB%93%9C%EB%8A%94-%ED%94%8C%EB%9D%BC%EC%9D%B4%ED%9C%A0%EC%9D%84-%EA%B5%B4%EB%A0%A4%EB%9D%BC&quot; aria-label=&quot;조직의 탁월함을 만드는 플라이휠을 굴려라 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 언급했듯이 탁월한 조직을 만드는 것의 핵심은 탁월함을 향해 저절로 굴러가는 조직을 설계하는 것이다. 이는 마치 제품 개발 개념에서 차용하는 &lt;a href=&quot;https://brunch.co.kr/@b-rian/4&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;플라이휠 효과&lt;/a&gt;와도 유사하다.&lt;/p&gt;
&lt;p&gt;플라이휠 효과란 하나의 작은 임팩트들이 반복적으로 누적되며 점점 더 큰 성과를 만들어내는 구조를 말한다. 초기에는 많은 에너지가 필요하지만, 한 번 돌아가기 시작하면 관성에 의해 점점 적은 힘으로도 더 큰 성과를 만들어낸다.&lt;/p&gt;
&lt;p&gt;이와 마찬가지로 조직 운영에서도 개별 활동이 선순환 구조로 연결될 때, 탁월함은 자연스럽게 가속된다.&lt;/p&gt;
&lt;p&gt;필자가 설계한 탁월한 조직의 플라이휠은 크게 6단계로 구성된다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;유입&lt;/strong&gt;: 성장에 미쳐있는 탁월한 인재를 모은다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;메타인지&lt;/strong&gt;: 조직이 원하는 기대치, 현재 나의 상태를 파악한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;기회제공&lt;/strong&gt;: 준비가 되어있는 인재가 다음 성장을 작은 단위로 경험할 수 있는 기회를 제공한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;인정&lt;/strong&gt;: 성장을 만들어낸 인재들에게 물리/심리적 보상을 전달하여 인정과 성취의 경험을 제공한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;기여&lt;/strong&gt;: 좋은 경험을 한 인재들이 프론트엔드 챕터의 여러 활동에 참여하여 조직이 탁월해진다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;브랜딩&lt;/strong&gt;: 이렇게 탁월해진 챕터의 활동을 정리하여 외부로 알린다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1단계-유입---성장에-미쳐있는-탁월한-인재를-모은다&quot; style=&quot;position:relative;&quot;&gt;1단계: 유입 - 성장에 미쳐있는 탁월한 인재를 모은다&lt;a href=&quot;#1%EB%8B%A8%EA%B3%84-%EC%9C%A0%EC%9E%85---%EC%84%B1%EC%9E%A5%EC%97%90-%EB%AF%B8%EC%B3%90%EC%9E%88%EB%8A%94-%ED%83%81%EC%9B%94%ED%95%9C-%EC%9D%B8%EC%9E%AC%EB%A5%BC-%EB%AA%A8%EC%9D%80%EB%8B%A4&quot; aria-label=&quot;1단계 유입   성장에 미쳐있는 탁월한 인재를 모은다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;탁월한 조직을 만들려면 탁월한 인재가 계속 들어와야 한다. 그런데 여기서 중요한 건 단순히 실력 있는 인재가 아니라 성장에 미쳐있고 성장 가능성이 높은 인재를 모으는 것이다.&lt;/p&gt;
&lt;p&gt;이를 위해 채용 단계에서 이런 분들을 찾아낼 수 있는 것도 중요하지만, 더 중요한 것은 브랜딩을 통해 외부에 있는 사람들이 “아, 저기에 가면 내가 더 성장할 수 있겠구나”라는 생각을 할 수 있도록 만들어 자연스레 토스팀에 더 많은 지원을 하는 그림을 만드는 것이다.&lt;/p&gt;
&lt;p&gt;토스 프론트엔드 챕터가 어떤 기술력을 가지고 있는지, 어떤 문화를 가진 조직인지를 구체적으로 보여줘야 한다. 이것이 바로 6단계 브랜딩이 다시 1단계 유입으로 연결되는 지점이다.&lt;/p&gt;
&lt;h3 id=&quot;2단계-메타인지---조직의-기대치와-나의-강점을-같은-언어로-바라본다&quot; style=&quot;position:relative;&quot;&gt;2단계: 메타인지 - 조직의 기대치와 나의 강점을 같은 언어로 바라본다&lt;a href=&quot;#2%EB%8B%A8%EA%B3%84-%EB%A9%94%ED%83%80%EC%9D%B8%EC%A7%80---%EC%A1%B0%EC%A7%81%EC%9D%98-%EA%B8%B0%EB%8C%80%EC%B9%98%EC%99%80-%EB%82%98%EC%9D%98-%EA%B0%95%EC%A0%90%EC%9D%84-%EA%B0%99%EC%9D%80-%EC%96%B8%EC%96%B4%EB%A1%9C-%EB%B0%94%EB%9D%BC%EB%B3%B8%EB%8B%A4&quot; aria-label=&quot;2단계 메타인지   조직의 기대치와 나의 강점을 같은 언어로 바라본다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 믿는 성장은 언제나 메타인지에서 출발한다. 그래서 탁월한 조직이 만들어내는 구성원들의 성장 또한 결국 구성원 각자가 자신의 역량과 강점을 얼마나 정확하게 인식하고 있는지에서 시작된다고 믿는다.&lt;/p&gt;
&lt;p&gt;이건 마치 삼국지 게임과도 비슷하다. 예를 들어 여포와 제갈량을 한번 생각해보자. 두 사람 모두 뛰어난 인재이지만 맞지 않는 역할이 주어지는 순간 그 탁월함은 사라진다. 여포에게 내정을 맡기거나, 제갈량에게 일기토를 시키면 좋지 않은 결과가 나올 것이 뻔하기 때문이다.&lt;/p&gt;
&lt;p&gt;문제는 현실에서는 자신이 여포인지 제갈량인지조차 모르는 경우가 많고, 혹은 여포임에도 내정을 하고 싶다고 말하는 경우도 있다. 이는 의지의 문제가 아니라 메타인지의 부족에 가깝다고 생각한다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 탁월한 조직에서 만들어내는 성장의 첫걸음은 구성원들이 스스로의 역량과 강점을 제대로 인식하고, 그에 맞는 올바른 성장 기회를 얻는 것에서부터 출발한다고 생각한다.&lt;/p&gt;
&lt;p&gt;이런 생각에 연장선에서, 토스 프론트엔드 챕터에서는 스킬트리라는 도구를 활용하고 있다. 이 스킬트리는 탁월함을 규정하기 위한 장치라기보다는 구성원들이 자신의 현재 역량 상태와 강점을 더 선명하게 인식하고 다음 성장 방향을 스스로 언어화할 수 있도록 돕기 위한 참고선에 가깝다.&lt;/p&gt;
&lt;p&gt;그리고 자신의 성장 방향과 강점을 언어화할 수 있다면 이제 리드들은 이 정보를 바탕으로 각자의 강점이 실제 성과와 성장으로 이어질 수 있도록 코칭한다.&lt;/p&gt;
&lt;h3 id=&quot;3단계-기회제공---작은-단위로-성장을-경험하게-한다&quot; style=&quot;position:relative;&quot;&gt;3단계: 기회제공 - 작은 단위로 성장을 경험하게 한다&lt;a href=&quot;#3%EB%8B%A8%EA%B3%84-%EA%B8%B0%ED%9A%8C%EC%A0%9C%EA%B3%B5---%EC%9E%91%EC%9D%80-%EB%8B%A8%EC%9C%84%EB%A1%9C-%EC%84%B1%EC%9E%A5%EC%9D%84-%EA%B2%BD%ED%97%98%ED%95%98%EA%B2%8C-%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;3단계 기회제공   작은 단위로 성장을 경험하게 한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;메타인지가 이루어졌다면, 그 다음으로 조직이 해야 할 일은 명확하다. 구성원들이 부담 없이 도전하고, 작은 단위의 성공을 경험할 수 있는 기회를 제공하는 것이다. 아무리 자신의 강점과 현재 상태를 잘 인식하고 있어도, 실제로 시도해볼 수 있는 장이 없다면 성장은 관념에 머물 수밖에 없다.&lt;/p&gt;
&lt;p&gt;이 생각은 최근 진행한 리더십 설문조사를 통해 더 선명해졌다. 설문 결과를 보면 리더십 역할에 대한 관심은 생각보다 훨씬 많았다. 다만 많은 구성원들이 공통적으로 “관심은 있지만 아직 준비가 안 된 것 같다.”라고 답했다는 점이 특징이었다.&lt;/p&gt;
&lt;p&gt;처음에는 구성원들이 스스로의 역량이 부족하다고 느낀다고 생각했지만, 개별 응답을 더 분석해보니 오히려 “내가 무엇을 준비해야 하는지, 어떤 역량을 쌓아야 하는지 잘 모르겠다”에 더 가까웠다. 즉, 챕터가 성장의 방향성과 기준, 그리고 그 방법에 대한 힌트를 충분히 제공하지 못하고 있었던 것이다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 이런 기회를 더 많이 만들고, 더 자주 노출해야 한다고 생각했다. 성장은 한 번의 큰 도약이 아니라, 여러 번의 작은 성공 경험 위에서 만들어지는 것이기 때문에 챕터원들이 부담없이 도전할 수 있는 환경을 만들어줘야한다.&lt;/p&gt;
&lt;p&gt;이런 문제의식에서 시작된 것이 Next F-Lead 프로그램이다. 이 프로그램은 전략적 사고, 인터뷰 스킬, 1 on 1 코칭이라는 세 가지 핵심 역량에 집중한다. 목표는 누군가를 갑자기 리드로 만드는 게 아니라, F-Lead의 역할을 작은 단위로 미리 경험해볼 수 있도록 돕는 데 있다. 이를 통해 구성원들은 “리더십이 나와는 먼 이야기”가 아니라 “조금씩 준비해볼 수 있는 다음 단계”라는 감각을 얻게 된다.&lt;/p&gt;
&lt;p&gt;Next F-Lead뿐만 아니라, 다양한 교육과 체험 프로그램을 통해 구성원들이 자신의 Next Step을 더 선명하게 그릴 수 있도록 노력하고 있다. 중요한 건 누군가를 특정 방향으로 밀어붙이는 게 아니라, 각자가 스스로 도전해보고 선택할 수 있는 환경을 만들어주는 것이라고 생각한다.&lt;/p&gt;
&lt;p&gt;작은 성공을 경험한 사람은 더 큰 도전을 상상할 수 있고, 그 상상은 다시 다음 성장을 향한 실제 행동으로 이어진다. 이것이 기회제공 단계가 플라이휠에서 중요한 이유다.&lt;/p&gt;
&lt;h3 id=&quot;4단계-인정---물리적심리적-보상으로-성취를-경험하게-하다&quot; style=&quot;position:relative;&quot;&gt;4단계: 인정 - 물리적/심리적 보상으로 성취를 경험하게 하다&lt;a href=&quot;#4%EB%8B%A8%EA%B3%84-%EC%9D%B8%EC%A0%95---%EB%AC%BC%EB%A6%AC%EC%A0%81%EC%8B%AC%EB%A6%AC%EC%A0%81-%EB%B3%B4%EC%83%81%EC%9C%BC%EB%A1%9C-%EC%84%B1%EC%B7%A8%EB%A5%BC-%EA%B2%BD%ED%97%98%ED%95%98%EA%B2%8C-%ED%95%98%EB%8B%A4&quot; aria-label=&quot;4단계 인정   물리적심리적 보상으로 성취를 경험하게 하다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;성장은 경험만으로 완성되지 않는다. 성장을 만들어낸 사람에게는 반드시 인정이 따라와야 한다. 특히 긍정적인 피드백을 통한 보상은 조직 운영에서 과소평가되기 쉽지만, 실제로는 플라이휠을 다시 가속시키는 데 가장 중요한 요소 중 하나다.&lt;/p&gt;
&lt;p&gt;토스 프론트엔드 챕터 안에는 이미 자신의 강점을 드러내며 조직에 기여하고 있는 사람들이 많이 있다. 예를 들면 기술 공유를 꾸준히 하는 사람, 오픈소스 위원회나 코드 퀄리티 위원회 같은 활동에 참여하는 사람, 동료들이 더 잘 일할 수 있도록 도구를 만들어 공유하는 사람들이다.&lt;/p&gt;
&lt;p&gt;이런 기여들은 조직을 한 단계 끌어올리지만, 그 가치가 충분히 드러나지 않으면 당사자조차 자신의 성취를 체감하기 어렵다. 그래서 필자는 이들이 지금보다 더 자주, 더 분명하게 인정받아야 한다고 생각한다.&lt;/p&gt;
&lt;p&gt;리드 역할을 맡고 있는 사람들 역시 마찬가지다. 이들은 자신의 성과뿐 아니라 동료들의 성장을 바로 옆에서 돕는 역할을 수행한다. 조직 관점에서는 매우 중요한 역할이고, 개인 관점에서는 결코 가볍지 않은 책임이다. 실제로 해야 할 일도 많고, 고민해야 할 것도 많다. 필자에게 이들과 함께하는 매일은 감사의 연속이며, 이런 헌신은 반드시 보상받아야 한다.&lt;/p&gt;
&lt;p&gt;그래서 토스 프론트엔드 챕터에서는 이들을 위한 전용 리더십 교육 프로그램을 준비하고 있다. 단순한 교육을 넘어, 챕터의 의사결정에 더 깊이 참여할 수 있는 기회, 명시적인 권한과 역할의 확장도 함께 기획하고 있다. 이건 단순한 보상이 아니라 “당신의 성장은 조직이 진지하게 대하고 있다”는 명확한 메시지다.&lt;/p&gt;
&lt;p&gt;인정은 성과의 끝이 아니라 다음 성장을 시작하게 만드는 신호다. 성취를 경험한 사람은 다시 기여하고 싶어지고, 그 기여는 다시 조직을 탁월하게 만든다. 이것이 인정 단계가 플라이휠에서 빠질 수 없는 이유다.&lt;/p&gt;
&lt;h3 id=&quot;5단계-기여---좋은-경험이-조직을-탁월하게-만든다&quot; style=&quot;position:relative;&quot;&gt;5단계: 기여 - 좋은 경험이 조직을 탁월하게 만든다&lt;a href=&quot;#5%EB%8B%A8%EA%B3%84-%EA%B8%B0%EC%97%AC---%EC%A2%8B%EC%9D%80-%EA%B2%BD%ED%97%98%EC%9D%B4-%EC%A1%B0%EC%A7%81%EC%9D%84-%ED%83%81%EC%9B%94%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A0%EB%8B%A4&quot; aria-label=&quot;5단계 기여   좋은 경험이 조직을 탁월하게 만든다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;인정을 받고 성취를 경험한 인재들은 자연스럽게 조직에 기여하게 된다. 그리고 이런 기여를 했을 때 앞서 4단계에서 언급한 샤라웃, 권한 확장, 의사결정 참여 같은 인정을 다시 받게 되면, 이런 행동은 자연스럽게 강화된다. 이것이 플라이휠의 핵심이다.&lt;/p&gt;
&lt;p&gt;필자는 지식의 공유, 새로운 아이디어와 피드백, 격렬한 토론 등이 자주 등장해야 탁월한 조직이 될 것이라 믿는다. 이런 것들이 바로 기여에 해당하고, 이런 기여들이 모여 결국 탁월한 조직이 된다.&lt;/p&gt;
&lt;p&gt;사실 토스 프론트엔드 챕터는 이런 기여들을 경험해본 적이 많은 조직이다.&lt;/p&gt;
&lt;p&gt;사람이 별로 없던 초반에는 사내 라이브러리 구축, TDS(Toss Design System) 개발, 어드민 개발 등이 이런 기여를 통해 진행됐다. 지금은 기술 관련 도구나 정보 공유, 오픈소스 위원회, 코드 퀄리티 위원회, Frontend Accelerator 멘토링 지원, 유저 접근성 개선 등으로 나타나고 있다.&lt;/p&gt;
&lt;p&gt;Next F-Lead를 수료한 리드들이 프로그램을 개선하고, 오픈소스 위원회에서 활동한 개발자들이 새로운 라이브러리를 제안하고, 스킬트리를 사용한 챕터원들이 피드백을 준다. 이 모든 것이 기여다.&lt;/p&gt;
&lt;p&gt;시스템은 개인에 의해 개선되고, 개선된 시스템은 다시 더 많은 개인을 탁월하게 만든다. 작은 플라이휠은 이미 돌아가고 있는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;6단계-브랜딩---탁월함을-외부로-알린다&quot; style=&quot;position:relative;&quot;&gt;6단계: 브랜딩 - 탁월함을 외부로 알린다&lt;a href=&quot;#6%EB%8B%A8%EA%B3%84-%EB%B8%8C%EB%9E%9C%EB%94%A9---%ED%83%81%EC%9B%94%ED%95%A8%EC%9D%84-%EC%99%B8%EB%B6%80%EB%A1%9C-%EC%95%8C%EB%A6%B0%EB%8B%A4&quot; aria-label=&quot;6단계 브랜딩   탁월함을 외부로 알린다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;마지막 단계는 브랜딩이다. 이렇게 탁월해진 챕터의 활동을 정리해서 외부로 알리는 것이다.&lt;/p&gt;
&lt;p&gt;현재 토스 프론트엔드 챕터는 오픈소스 위원회, Frontend Accelerator 멘토링, Frontend Fundamentals 문서 제작, 모닥불 유튜브 콘텐츠 등 다양한 활동을 통해 탁월함에 대한 브랜드를 구축해나가고 있다.&lt;/p&gt;
&lt;p&gt;예를 들어 오픈소스 위원회는 es-toolkit, es-hangul, overlay-kit 등 여러 라이브러리를 배출해냈는데, 특히 &lt;a href=&quot;https://es-toolkit.dev/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;es-toolkit&lt;/a&gt;의 경우 마이크로소프트와 같은 빅테크에서 사용하기도 했고, Storybook이나 yarn 같은 유명한 도구에서 채택되기도 했다. 현재는 주간 다운로드 수가 900만 건에 달한다.&lt;/p&gt;
&lt;p&gt;또한 &lt;a href=&quot;https://frontend-fundamentals.com/code-quality/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Frontend Fundamentals&lt;/a&gt;와 Frontend Accelerator 멘토링은 프론트엔드 생태계를 더욱 성장시키는 것을 목표로 하는데, 이를 통해 더 탁월한 개발자들이 생태계 내에서 배출되고 이로 인해 토스팀에도 자연스럽게 탁월한 인재들이 유입되는 선순환을 기대하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://toss.tech/article/firesidechat_frontend_10&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;모닥불 유튜브&lt;/a&gt;와 같은 콘텐츠는 상대적으로 적은 비용으로 많은 개발자들에게 좋은 영향력을 만들어낼 수 있는 훌륭한 수단이다. 토스 프론트엔드 챕터가 어떤 기준으로 코드를 작성하는지, 챕터 내에 어떤 개발자들이 있는지 자연스럽게 보여주어 브랜딩 효과를 만들어낸다.&lt;/p&gt;
&lt;p&gt;이 모든 활동들은 “토스 프론트엔드 챕터는 탁월한 조직이다”라는 메시지를 외부에 전달하며, 이 메시지를 보고 성장에 미쳐있는 탁월한 인재들이 다시 토스팀으로 유입된다. 브랜딩이 잘 된다면 다시 1단계인 유입으로 이어지며 플라이휠이 완성된다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;리더로서 필자가 가장 중요하게 생각하는 것은 “내가 없어도 돌아가는 조직”을 만드는 것이다. 역설적으로 들릴 수 있지만, 이것이 진짜 지속 가능성이다.&lt;/p&gt;
&lt;p&gt;개인 의존성을 줄이고, 명확한 기준과 작동하는 시스템을 남기는 것. 필자가 휴가를 가거나, 다른 일에 집중하거나, 심지어 이 역할을 떠나더라도 플라이휠이 계속 돌아가도록 만드는 것. 그래서 필자는 지난 2년 반 동안 사람을 직접 케어하는 것이 아니라 조직을 저절로 탁월하게 만드는 시스템을 구축하는 데 집중해왔다.&lt;/p&gt;
&lt;p&gt;진짜 탁월한 조직은 탁월한 개인을 계속 만들어낼 수 있는 조직이다. 그리고 그 개인들이 다시 조직을 더 탁월하게 만드는 조직이다.&lt;/p&gt;
&lt;p&gt;사실 각 시스템은 아직 개선할 부분이 많다. 스킬트리는 더 정교해져야 하고, Next F-Lead는 더 많은 리드를 배출해야 하고, 인정 시스템은 아직 구축 중이다. 무엇보다 이 모든 것이 정말로 “조직을 더 탁월하게 만들고 있는가”에 대한 명확한 답은 여전히 찾아가는 중이다.&lt;/p&gt;
&lt;p&gt;하지만 방향은 맞다고 확신한다. 작은 성과들이 쌓이고 있고, 챕터원들의 피드백이 계속 들어오고 있으며, 무엇보다 작은 플라이휠은 실제로 돌아가고 있기 때문이다.&lt;/p&gt;
&lt;p&gt;조직 운영은 단기간에 답이 나오는 문제가 아니다. 하지만 명확한 방향성과 작동하는 시스템이 있다면, 시간이 지날수록 플라이휠은 더 빠르게 돌고 토스 프론트엔드 챕터는 지금보다 더 탁월한 조직이 될 것이라 믿는다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Asset Management Is a State Management Problem]]></title><description><![CDATA[In this post, I want to step away from technical topics and talk about something closer to everyday life: asset management. First, let me be clear: I’m not wealthy, and I don’t have some secret formula for making a fortune overnight. What I do have is years of thinking about how an ordinary salaried worker can steadily grow their assets over time.]]></description><link>https://evan-moon.github.io/2026/01/17/assets-management/en/</link><guid isPermaLink="false">20260117-assets-management-en</guid><pubDate>Sat, 17 Jan 2026 03:06:30 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I want to step away from technical topics and talk about something closer to everyday life: asset management.&lt;/p&gt;
&lt;p&gt;First, let me be clear: I’m not wealthy, and I don’t have some secret formula for making a fortune overnight. What I do have is years of thinking about how an ordinary salaried worker can steadily grow their assets over time.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;If you’ve already made serious money through business or investing, this might sound obvious. But for someone like me, managing assets from a fairly average starting point, I think there’s plenty here to relate to. So I’d like to share the framework I’ve built for myself.&lt;/p&gt;
&lt;h2 id=&quot;without-knowing-your-current-state-no-judgment-is-possible&quot; style=&quot;position:relative;&quot;&gt;Without Knowing Your Current State, No Judgment Is Possible&lt;a href=&quot;#without-knowing-your-current-state-no-judgment-is-possible&quot; aria-label=&quot;without knowing your current state no judgment is possible permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the things I consider most important in asset management is knowing where I currently stand. To do this, I’ve been consistently recording my asset data.&lt;/p&gt;
&lt;p&gt;Nobody gets asset management right from the start. Most of us go through trial and error, gradually building our own criteria along the way. But if you don’t even know your current state, it’s impossible to judge whether you’re on the right track.&lt;/p&gt;
&lt;p&gt;I’ve been taking a monthly asset snapshot since 2018, when I started working as a developer. Looking back, this accumulated data now shows the trajectory of my assets at a glance — but at the time, it was often more confusing than clarifying. Some months my assets grew; other months they shrank more than expected.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ee3caeb1f1b5b18d2656441300609777/d698c/chart.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 43.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAq0lEQVR42q2QgQrDMAhE8/+/2zZGE3WnjlI6BoM1cFStvlxs/ugxb8+x1I3pOaAKudL2P9B0uU321beEtl9381myBOnYS3wgl29Aq4E13WSguSMWuJkJMTixqIXmqFp81x0Yi8Ut1QRQNnHtJ3KpoRMeWhfh+a0SwQDXTfkDYHu7TGnGV0XtrjDUjh3LBECEnYjSKDM7j5HxGOQzXAPSe89ehZOIgy0i51ycF6fjyeS7d8mWAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;chart&quot; title=&quot;&quot; src=&quot;/static/ee3caeb1f1b5b18d2656441300609777/6af66/chart.png&quot; srcset=&quot;/static/ee3caeb1f1b5b18d2656441300609777/69538/chart.png 160w,
/static/ee3caeb1f1b5b18d2656441300609777/72799/chart.png 320w,
/static/ee3caeb1f1b5b18d2656441300609777/6af66/chart.png 640w,
/static/ee3caeb1f1b5b18d2656441300609777/d9199/chart.png 960w,
/static/ee3caeb1f1b5b18d2656441300609777/21b4d/chart.png 1280w,
/static/ee3caeb1f1b5b18d2656441300609777/d698c/chart.png 1846w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;With this data accumulated over time, I can see at a glance how my assets reacted to market events, what my monthly asset growth rate looks like, and how much my assets have grown compared to five years ago.&lt;/p&gt;
&lt;p&gt;The thought that came up most often while keeping records was: “Am I heading in the right direction?” What mattered wasn’t whether my assets went up or down in a given month, but whether I managed to stick to my predetermined criteria without being swayed by emotion.&lt;/p&gt;
&lt;p&gt;The numbers I see today are just outcomes. The real value of this data, for me, lies in being able to verify that my current choices remain consistent with my past judgments — even amid uncertainty. Without these records, I would very likely have lost my way somewhere along the line.&lt;/p&gt;
&lt;p&gt;That’s why I don’t use asset data as a tool for predicting the future. I use it only to confirm where I stand right now, and to check that my decision-making criteria haven’t drifted.&lt;/p&gt;
&lt;h2 id=&quot;right-abstraction-matters-more-than-precise-numbers&quot; style=&quot;position:relative;&quot;&gt;Right Abstraction Matters More Than Precise Numbers&lt;a href=&quot;#right-abstraction-matters-more-than-precise-numbers&quot; aria-label=&quot;right abstraction matters more than precise numbers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s widely known that data matters in finance and asset management. The most common starting point is an expense tracker — recording income and expenses to understand your cash flow is certainly meaningful.&lt;/p&gt;
&lt;p&gt;The problem is that this tool doesn’t tend to last very long. When you try to classify dozens or hundreds of transactions each month and get every number exactly right, it starts to feel like a burden. If the numbers don’t balance perfectly, it nags at you, and once you fall behind on recording, you end up abandoning it altogether. I went through this cycle several times before giving up on keeping a detailed expense tracker.&lt;/p&gt;
&lt;p&gt;But if you think about it, the problem can be framed differently.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 270px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f12412c188bfb126bc3bedd4b1a1c470/01bf6/um.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAADWElEQVR42hXLWVMaBwAA4H3v9MFkak0y1IRqwn3usrALy6IcAgsGXEFEQY5ExAtBIHIsyABOgYDGEEysIZomBklaNaRmTNpp69jmpTN5aP9P7ff+AT+/PtiurtaygUrKV0p4SwlPLEBiEi4svAmBHBHIk8AiFJUocQRXoTAsYjL7uHwWYVBnYneBD53jRpmqZf7P8emRtbh7bsosETFgMYMvZEESoUIhRVCpHEOlKCyCBHwBm8NjgiKOSYsCnYPWk1r2ftpfSfqWvOZibCIwqZdCLDbzulLMuDeOF31DWY8u6tQ6jXJMJr7F6L/F7KN/SwN5N4HW7k6jnFrPTidmR60aJOw3Z0K2xYDNYVUGTeBdg3jBwM7ZwXmCHxmRUDaYxJjd3V1Xr3zV090FHL7ab5Soh/nZCYsKEvRRIVtueTyX8KUj43nP4LQepMYVNS8+S0BBAq55scIEyqJdIoW9LNplYG/nUaNCbWRnXKTKPizPhMcucibmSSw5N0Pmx8GBd1nHYcaxtUB8vzTcDJsiVghh9ES1rDG1EPj4/mS7mi2n/YWYi1CDi3dMhfjkRc7Ep0rzxotc9alLblUzPNwIanM2cMYgmFIyEiMyJyEF3r45qJcTD/LBdcrvtWuoiGM1PEZF3dl7nvtRO+WQkSjDpxN858HLbjQ5Kg6axAu3kSkT7CBkwIunW/VKOjLndLtHjtqPzz/sHe9X27vlp/VUmZrRgTSXnO1CWHasP+uAly0i75BwzKIhjYjrtgIorCaHSSumNwiVgyvp0N9nrV+On2wU53/cKyaX7yjZX09iDLukL24VmCW9OKfHYwBDc/6A1xZ0GoABwiRVqZX6IcJuUenwo9b62UmzXlrqvCq3dysQl87q7eLQL+uhG8yrX2Lcazu1HJWK59JznR+qgACRgxiOaNTGUVKC4/l86NPp83opfPrmwec/9u02E/2bK7z+a7RLXyh414vp5aPWHukgGxup8/dNAFYNQkoVPDCIE3pEqwvOu387eba5FvrpeemfP9ubtUw/j6vDYbsRX8tET9++Tq2k1YShs7/5e6cJ3GCwGXwBqtFoLRY6i2226j+fH27XVtrNwr+fDv/6+JJ0OmRKxdyMb+vhenwlLh3QJpOLZ++e/Xq88x9ZGD9eANmthgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;um&quot; title=&quot;&quot; src=&quot;/static/f12412c188bfb126bc3bedd4b1a1c470/01bf6/um.png&quot; srcset=&quot;/static/f12412c188bfb126bc3bedd4b1a1c470/69538/um.png 160w,
/static/f12412c188bfb126bc3bedd4b1a1c470/01bf6/um.png 270w&quot; sizes=&quot;(max-width: 270px) 100vw, 270px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Does it really need to be exact...?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The core issue wasn’t that I stopped recording. It was that I took the premise of precision for granted. We’re not doing corporate accounting or filing tax returns with our personal finances, so is data accurate down to the last dollar really essential?&lt;/p&gt;
&lt;p&gt;What matters more in personal asset management isn’t precise numbers. It’s whether you can simplify the complex reality of finance into something you can actually judge. In this sense, asset management is pretty similar to how developers handle complex systems.&lt;/p&gt;
&lt;p&gt;When we write programs, we don’t manipulate memory addresses directly. We don’t try to solve everything with bit-level operations. Instead, we use abstractions like variables, types, and interfaces. We sacrifice some fine-grained control in exchange for the ability to understand the overall structure and make better decisions.&lt;/p&gt;
&lt;p&gt;I think the same thing happens in asset management. If you try to decompose and categorize every expense precisely, your judgment slows down and emotions have more room to creep in. Conversely, if you summarize the structure into a few key metrics, you can much more quickly assess whether your current state is risky, sustainable, or safe enough for aggressive moves.&lt;/p&gt;
&lt;p&gt;In the end, abstraction matters in asset management not because it’s less work, but because it simplifies your decision-making criteria. What matters more than where you spent an extra $10 is whether you’re in a financially safe state, whether your cash flow is structurally sustainable, and what options you have for reaching your goals.&lt;/p&gt;
&lt;p&gt;I believe asset management is the process of establishing criteria that won’t waver even in uncertain situations. And those criteria are built on well-designed abstractions, not precise data.&lt;/p&gt;
&lt;h2 id=&quot;assets-can-be-summarized-as-flow-and-state&quot; style=&quot;position:relative;&quot;&gt;Assets Can Be Summarized as Flow and State&lt;a href=&quot;#assets-can-be-summarized-as-flow-and-state&quot; aria-label=&quot;assets can be summarized as flow and state permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I mentioned earlier that asset management is a problem of abstraction, not precision. So what information do you actually need to abstract personal assets into something you can make judgments about?&lt;/p&gt;
&lt;p&gt;It turns out you don’t need much. At a high level, two things are sufficient: data on asset flow and data on current state.&lt;/p&gt;
&lt;p&gt;This is similar to the cash flow statement and balance sheet found in corporate financial statements. With just these two reports, you can quickly understand how a company earned and spent its money, and what its current financial position looks like.&lt;/p&gt;
&lt;p&gt;Personal asset management isn’t fundamentally different. You don’t need corporate-level accounting, but you should at least know how money flows in and out, and how your assets are currently structured.&lt;/p&gt;
&lt;p&gt;Asset flow can be tracked through cash flow data — how much you earned this month, how much you spent, and what’s left over. This data determines the speed and direction of your asset management. If the flow isn’t healthy, your assets will eventually stagnate or shrink.&lt;/p&gt;
&lt;p&gt;Asset state, on the other hand, is tracked through snapshot data: how much immediately available cash you have, what forms your assets are tied up in, and how much debt you carry. This data reveals the range of risk you can currently absorb.&lt;/p&gt;
&lt;p&gt;Neither dataset needs to be perfectly accurate. What personal asset management requires isn’t numerical precision but a sense of structure. It matters more to know your rough income-to-expense ratio than to know your exact spending this month. Likewise, knowing the ratio of liquid to illiquid assets matters more than having your net worth accurate to the last ten dollars.&lt;/p&gt;
&lt;p&gt;When you separate flow and state like this, asset management gets simpler. Is the flow stable? Does the state carry excessive risk? Being able to answer just these two questions enables most important financial decisions.&lt;/p&gt;
&lt;p&gt;Rather than trying to look at more data, I’ve focused on consistently checking these two pieces of information. As a result, even when market conditions changed or my assets grew in size, my decision-making criteria remained largely stable.&lt;/p&gt;
&lt;p&gt;Now I’d like to go into more detail about how I approach each of these. Let’s start with cash flow.&lt;/p&gt;
&lt;h3 id=&quot;cash-flow-look-at-ratios-not-detailed-logs&quot; style=&quot;position:relative;&quot;&gt;Cash Flow: Look at Ratios, Not Detailed Logs&lt;a href=&quot;#cash-flow-look-at-ratios-not-detailed-logs&quot; aria-label=&quot;cash flow look at ratios not detailed logs permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Understanding asset flow ultimately comes down to checking how much you earned in a month and how much you kept. When people think of managing cash flow, they usually think of an expense tracker, but I don’t think detailed expense tracking is necessarily the right answer.&lt;/p&gt;
&lt;p&gt;The purpose of an expense tracker isn’t really to record exactly where every dollar went — it’s to understand the structure of your income and spending. But in many cases, the means and the end get reversed. Once the recording itself becomes a burden, understanding your flow becomes impossible, let alone maintaining the habit.&lt;/p&gt;
&lt;p&gt;So when managing cash flow, I use much simpler categories than itemized expenses:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Major Category&lt;/th&gt;
&lt;th&gt;Subcategory&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Income&lt;/td&gt;
&lt;td&gt;Employment&lt;/td&gt;
&lt;td&gt;Salary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Employment&lt;/td&gt;
&lt;td&gt;Business&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Debt&lt;/td&gt;
&lt;td&gt;Loans&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Investment&lt;/td&gt;
&lt;td&gt;Dividends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Sale proceeds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Interest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expenses&lt;/td&gt;
&lt;td&gt;Consumption&lt;/td&gt;
&lt;td&gt;Personal spending&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Fixed costs&lt;/td&gt;
&lt;td&gt;Insurance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Phone/internet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Utilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Housing&lt;/td&gt;
&lt;td&gt;Rent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Maintenance fees&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There’s no single right answer for these categories. What matters isn’t copying someone else’s structure, but understanding why you chose to split things the way you did.&lt;/p&gt;
&lt;p&gt;In my case, I separate employment income from investment income, and I break out fixed costs and housing from general spending. I wanted to see what proportion of my income is passive, and how much of my earnings go to housing. If that information isn’t useful to you, bundling all spending into one category works perfectly fine.&lt;/p&gt;
&lt;p&gt;Even with this rough structure, it’s more than enough to see how much I earned in a month and how much I kept.&lt;/p&gt;
&lt;p&gt;Organizing cash flow this way already reveals a lot, but the single most important metric in my view is the profit margin — roughly what percentage of monthly income I’m keeping.&lt;/p&gt;
&lt;p&gt;This one number contains more information than you’d think. It intuitively shows whether income is growing, whether spending is excessive, or whether your lifestyle is outpacing your asset growth. You might not know where an extra $50 went, but you definitely know whether you kept 30% or 50% of your income this month.&lt;/p&gt;
&lt;p&gt;For reference, as of 2025, the average consumption-to-income ratio for South Korean households is around 67% — meaning on average, people keep about a third of their income. Including loan principal and interest payments, the effective spending ratio is even higher. This isn’t an absolute standard, but rather a reference point for gauging where your cash flow stands relative to the social average.&lt;/p&gt;
&lt;p&gt;If you use the average as a benchmark, keeping more than 30% of your income suggests you’re probably not in a structurally strained position. Of course, this varies by individual circumstances. What matters isn’t the exact percentage but continuously monitoring which direction your cash flow is moving.&lt;/p&gt;
&lt;p&gt;I’m not saying that detailed expense analysis, like traditional expense tracking, is meaningless. Knowing where money is leaking can certainly help reduce spending. But I think it’s better to focus first on improving income structure rather than cutting expenses.&lt;/p&gt;
&lt;p&gt;There’s a hard floor on how much you can cut. You can’t skip rent or eliminate living expenses entirely. No matter how frugal you are, there’s a minimum you’ll hit.&lt;/p&gt;
&lt;p&gt;Income, on the other hand, can expand depending on structure. Salary raises, job changes, investment returns, dividends, side income. Each new channel takes time to build, but the ceiling is open. This difference isn’t just about the dollar amount; it’s about whether you have a strategy that’s sustainable over the long term.&lt;/p&gt;
&lt;p&gt;That’s why when I look at cash flow, I focus on “how much did I keep” rather than “how much did I spend.” If the profit margin stays stable, room to grow assets naturally follows. And that room becomes the foundation for the next set of choices — how to allocate assets and what level of risk to take on.&lt;/p&gt;
&lt;p&gt;Now that I’ve covered the “velocity” of cash flow, it’s time to look at the “state” — how assets are currently structured.&lt;/p&gt;
&lt;h3 id=&quot;asset-state-look-at-structure-not-size&quot; style=&quot;position:relative;&quot;&gt;Asset State: Look at Structure, Not Size&lt;a href=&quot;#asset-state-look-at-structure-not-size&quot; aria-label=&quot;asset state look at structure not size permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If cash flow data shows the “flow” of income and expenses, an asset snapshot shows the current state. I regularly check how much immediately available cash I have and what forms my assets are tied up in. The exact figures for each asset don’t need to be precise — in my case, I consider a margin of error around $1,000 to be perfectly acceptable.&lt;/p&gt;
&lt;p&gt;When constructing an asset snapshot, the same principle applies as with cash flow: what matters is structure, not precision. Here are roughly the categories I use:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Major Category&lt;/th&gt;
&lt;th&gt;Subcategory&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Assets&lt;/td&gt;
&lt;td&gt;Cash&lt;/td&gt;
&lt;td&gt;KRW&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;USD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Savings deposits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Housing subscription savings (Jucheongnyak)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Investments&lt;/td&gt;
&lt;td&gt;Domestic stocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Foreign stocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Real estate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Pension&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Other&lt;/td&gt;
&lt;td&gt;Vehicle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Jeonse deposit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Liabilities&lt;/td&gt;
&lt;td&gt;Short-term&lt;/td&gt;
&lt;td&gt;Credit card&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Long-term&lt;/td&gt;
&lt;td&gt;Loans&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Again, there’s no single right answer. What matters is what questions this breakdown helps you answer. In my case, what I care about most isn’t total asset value — it’s the ratio of liquid assets to illiquid ones.&lt;/p&gt;
&lt;p&gt;Even with the same total assets, the situation changes entirely depending on what form those assets take. If you hold a sufficient proportion of assets that can be quickly converted to cash, like savings or stocks, you retain options even when markets shake. Conversely, if most of your assets are locked up in forms like housing deposits or real estate that can’t be easily moved, even small volatility becomes immediate pressure. This is the benefit that liquidity provides.&lt;/p&gt;
&lt;p&gt;To me, liquidity is closer to optionality than “how quickly can I sell.” With sufficient liquidity, you can afford to wait, and when circumstances change, you can choose to act on opportunities. Without it, even the choice to do nothing becomes difficult — because market volatility transfers directly into psychological pressure.&lt;/p&gt;
&lt;p&gt;From this perspective, an asset snapshot is less about checking how much you own and more about gauging how much risk you can currently handle. That’s why when I look at my snapshot, I check whether the overall structure is putting undue strain on me before looking at any individual asset’s price.&lt;/p&gt;
&lt;p&gt;So what metrics are useful when reviewing asset state? One reference metric I use is monthly asset growth rate. The key point is that I don’t treat this as a target. Rather than setting a goal like “grow assets by X% each month,” I use it as a secondary indicator to check whether the current trajectory is holding.&lt;/p&gt;
&lt;p&gt;According to a &lt;a href=&quot;https://www.korea.kr/news/policyNewsView.do?newsId=148955870&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Ministry of Economy and Finance report&lt;/a&gt; released last year, the average household asset growth rate for 2025 was approximately 4.9% — which works out to roughly 0.4% per month. Of course, assets have far more variability than income, and individual differences are large, so this average doesn’t mean much on its own. But having this number in mind helps you gauge whether your assets are significantly deviating from the overall trend.&lt;/p&gt;
&lt;p&gt;The important thing is that this number isn’t the answer. A high monthly growth rate doesn’t necessarily mean things are going well, and a low one doesn’t mean your choices are wrong. What matters is whether your assets are maintaining a consistent long-term direction, and whether you’re accumulating risks you can’t handle along the way.&lt;/p&gt;
&lt;p&gt;I believe direction matters far more than speed in asset growth. Achieving large returns in a short period matters less than maintaining a consistent direction with modest monthly changes — because that’s what lasts. So at the end of each month, I review my cash flow and asset snapshot together, checking what changed from the previous month and whether any asset is becoming a structural burden.&lt;/p&gt;
&lt;p&gt;This process naturally leads to the next question: how much volatility can the current asset structure withstand? To answer this, I consider the proportion of safe assets alongside my investment strategy.&lt;/p&gt;
&lt;h2 id=&quot;investing-is-a-choice-that-changes-your-state-not-your-returns&quot; style=&quot;position:relative;&quot;&gt;Investing Is a Choice That Changes Your State, Not Your Returns&lt;a href=&quot;#investing-is-a-choice-that-changes-your-state-not-your-returns&quot; aria-label=&quot;investing is a choice that changes your state not your returns permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you’ve been managing assets for a while, you inevitably arrive at the question of how to think about investing. It’s less about chasing higher returns and more about wondering whether the current asset structure can maintain its direction over time.&lt;/p&gt;
&lt;p&gt;Investing is most often discussed in terms of returns — which stock will go up, when to buy and sell, which strategy yields the highest gain. I won’t say these discussions are entirely unimportant. But from my experience, they only matter when one prerequisite is in place:&lt;/p&gt;
&lt;p&gt;Can you handle the volatility?&lt;/p&gt;
&lt;p&gt;Investing inherently involves volatility. Prices can rise, or they can move against your expectations. The problem is that the same volatility doesn’t hit everyone the same way. A 10% drop might be just a number for one person, but for another it’s pressure that shakes their judgment.&lt;/p&gt;
&lt;p&gt;What creates this difference isn’t investment knowledge or stock-picking ability — it’s asset structure and state. Specifically, whether you have regular, predictable cash flow, whether your assets are excessively concentrated in one area, and whether your psychological state can withstand the volatility. These factors have a far greater impact.&lt;/p&gt;
&lt;p&gt;That’s why when I talk about investing, I think the first question should be “In what state am I making this choice?” rather than “How much can I make?” How much risk can you take on, and will that risk translate into real-life financial pressure or emotional decision-making?&lt;/p&gt;
&lt;p&gt;From this perspective, investing and risk management aren’t separate topics. How you handle risk changes the very nature of the investment itself. The same strategy can produce entirely different outcomes depending on the structure it’s built on.&lt;/p&gt;
&lt;p&gt;Let me now discuss how to think about risk management, and the roles that earned income and safe assets play in absorbing that risk.&lt;/p&gt;
&lt;h3 id=&quot;risk-management-is-designing-protection-for-your-judgment&quot; style=&quot;position:relative;&quot;&gt;Risk Management Is Designing Protection for Your Judgment&lt;a href=&quot;#risk-management-is-designing-protection-for-your-judgment&quot; aria-label=&quot;risk management is designing protection for your judgment permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The fundamental skill of investing is actually very simple: buy low, sell high. Almost no one would argue with that statement. The problem is that following this simple principle in practice is far harder than it sounds.&lt;/p&gt;
&lt;p&gt;It’s not hard because the math is complex or because information is lacking. In most cases, the cause of failure is emotion. When prices rise, you feel they’ll keep rising; when they fall, you feel they’ll keep falling. Your mind might judge that now is cheap, but your hand won’t move toward the buy button.&lt;/p&gt;
&lt;p&gt;This emotional pull is especially strong during downturns. More than the drop itself, it’s the anxiety of “Did I make the wrong call?” that surfaces first. That anxiety gradually blurs your criteria. The hypotheses and conditions you originally set get pushed to the back of your mind, and the immediate price movement starts dictating every decision.&lt;/p&gt;
&lt;p&gt;This is where most people feel that investing is hard. But I see this as less of a technique problem and more of a state problem. The question is whether you’re in a state where you can emotionally withstand this volatility.&lt;/p&gt;
&lt;p&gt;Risk management is closer to managing this state. The way I see it, risk management isn’t a technique for avoiding losses — it’s the process of designing an environment where emotions don’t override judgment. It’s about securing enough breathing room that you don’t need to make decisions just because prices are moving, enough time to consider your next move even when you might have been wrong, and enough distance to test the criteria you originally set.&lt;/p&gt;
&lt;p&gt;Only when this environment is in place can the fundamentals of investing actually work. When prices drop, you can revisit your reasoning instead of panicking. When prices rise, you can reexamine your thesis instead of getting excited. The simple principle of buying low and selling high only has meaning on top of a structure that keeps emotions in check.&lt;/p&gt;
&lt;p&gt;That’s why when talking about investing, I always ask “Am I in a state to handle this choice?” before “How much can I make?” The same strategy can yield entirely different results depending on what asset structure, cash flow, and psychological headroom it’s executed on.&lt;/p&gt;
&lt;p&gt;Seen this way, the essence of investing isn’t predicting prices. It’s designing an environment where emotions don’t interfere. The elements that support this environment are more mundane than you’d expect.&lt;/p&gt;
&lt;p&gt;Let me now talk about one of the key components of this risk management environment: earned income — why it matters for investing, and why it’s so often undervalued.&lt;/p&gt;
&lt;h3 id=&quot;earned-income-is-the-most-stable-hedging-layer&quot; style=&quot;position:relative;&quot;&gt;Earned Income Is the Most Stable Hedging Layer&lt;a href=&quot;#earned-income-is-the-most-stable-hedging-layer&quot; aria-label=&quot;earned income is the most stable hedging layer permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;“A salary is meaningless.” “You can’t get rich on earned income.” These statements are repeated so often in investment circles that they’ve become common wisdom.&lt;/p&gt;
&lt;p&gt;They spread especially easily during bull markets. When asset prices are rising fast, a fixed monthly paycheck looks slow and frustrating. Placed side by side with investment returns, it does look modest by comparison. But this statement is only partially true from a returns perspective — from a risk perspective, it’s critically wrong.&lt;/p&gt;
&lt;p&gt;As I mentioned earlier, investing is an act of absorbing volatility before it’s an act of generating returns. Saying prices can go up also means they can come down by the same magnitude. This simple fact is easily forgotten when markets are good. Everyone underestimates risk when numbers are climbing. The real test comes when the decline begins.&lt;/p&gt;
&lt;p&gt;What pressures people in a downturn isn’t the loss itself — it’s the possibility that the loss might spill over into daily life. The moment next month’s living expenses, fixed costs, and planned spending flash through your mind, investing stops being about probability and hypotheses and becomes about survival.&lt;/p&gt;
&lt;p&gt;This is where earned income reveals its true role. Having a predictable monthly cash flow means more than just income. It buys you time — time to be wrong right now and still be okay. Even if prices fall further, even if your judgment is slightly off, the urgency to make an immediate decision disappears. Without this breathing room, buying low and selling high both become impossible. Earned income won’t explosively grow your assets, but it creates the structure that keeps your assets from collapsing under the weight of emotion.&lt;/p&gt;
&lt;p&gt;When you have to cover living expenses solely from investment returns, even small volatility becomes overwhelming pressure. The same 10% drop can be “a period to wait through” for one person and “a crisis that demands selling now” for another. This difference doesn’t come from stock selection or analytical skill. It comes from the stability of cash flow. That’s why viewing earned income as merely “something to eventually escape from” is dangerous. It’s essentially kicking out the floor that makes investing possible.&lt;/p&gt;
&lt;p&gt;Earned income doesn’t compete with investing. Earned income is the last safety net that keeps investing functioning properly. When markets are good, anyone can take an aggressive position. The real difference shows when markets waver. And the people who can maintain their judgment through those moments almost always have stable cash flow. Ironically, the times when a salary seems most meaningless are exactly when its true value is most deeply hidden.&lt;/p&gt;
&lt;h3 id=&quot;safe-assets-are-the-buffer-that-makes-strategy-possible&quot; style=&quot;position:relative;&quot;&gt;Safe Assets Are the Buffer That Makes Strategy Possible&lt;a href=&quot;#safe-assets-are-the-buffer-that-makes-strategy-possible&quot; aria-label=&quot;safe assets are the buffer that makes strategy possible permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I should be honest about one thing at this point.&lt;/p&gt;
&lt;p&gt;My portfolio is far from conservative. A significant portion of my assets is concentrated in TSLA, and I also hold volatile instruments like TSLL (a leveraged TSLA product) and NVDA. In terms of volatility alone, this isn’t a structure I’d recommend to just anyone.&lt;/p&gt;
&lt;p&gt;Yet the reason I maintain these positions isn’t that I take risk lightly. It’s the opposite. I made this choice because I judged that the structure to absorb this level of volatility was already in place.&lt;/p&gt;
&lt;p&gt;Many people talk about aggressive investing as a matter of “conviction” or “guts.” But from my experience, investors who remain emotionally unshaken tend to be the most conservatively prepared. Only when cash flow is stable, safe assets are sufficiently secured, and daily life won’t be disrupted even in the worst case can you begin to accept volatility as part of your strategy.&lt;/p&gt;
&lt;p&gt;For me, safe assets aren’t meant to generate returns. It’s fine if they don’t appreciate, and it’s fine if they sit untouched for years. What matters is that their existence creates options. When prices drop, I can buy more. I can choose to wait and do nothing. If I feel my judgment was wrong, I have the room to unwind part of my position.&lt;/p&gt;
&lt;p&gt;Aggressive investing without this cushion is closer to gambling than investing. In a structure that can’t withstand volatility, no matter what stock you buy, emotions will break down first. Conversely, when safe assets and stable cash flow provide support, volatility transforms from a crisis into a condition for making choices.&lt;/p&gt;
&lt;p&gt;That’s why the more I want to accelerate asset growth, the more attention I pay to my safe asset allocation. It might sound paradoxical, but I believe the most aggressive choices are only possible on top of the most conservative preparation. As long as this structure holds, price fluctuations aren’t emotional noise — they’re signals you can act on.&lt;/p&gt;
&lt;p&gt;Managing your safe asset allocation isn’t a declaration that you want to avoid risk. It’s a choice to maintain a state where you can handle risk. And when that state is maintained, asset growth stops being a question of speed and becomes a question of strategy.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; style=&quot;position:relative;&quot;&gt;Wrapping Up&lt;a href=&quot;#wrapping-up&quot; aria-label=&quot;wrapping up permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The longer I’ve managed my assets, the more I’ve come to think that growing wealth isn’t about picking stocks or predicting markets. What matters more is whether you can build a structure that lets you maintain your judgment even amid uncertainty.&lt;/p&gt;
&lt;p&gt;Markets can shake at any time. Exchange rates, interest rates, political events, none of these are within individual control. In this environment, “managing assets well” isn’t about eliminating external variables. It’s about creating a state where you can absorb their impact.&lt;/p&gt;
&lt;p&gt;That’s why I always check structure first when looking at my assets. Is cash flow stable? Are assets excessively concentrated in one area? And am I in a state where I can emotionally withstand this volatility? As long as these criteria hold, price movements stop being a source of anxiety and become signals for reviewing my judgment.&lt;/p&gt;
&lt;p&gt;Everything I’ve discussed in this post, cash flow, asset snapshots, risk management, earned income, safe asset allocation, converges on the same question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“What choices am I in a state to make right now?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Asset management isn’t a problem that yields answers in the short term. Tiny differences accumulate over time into significant ones. Direction matters more than speed, and maintaining direction requires relying on structure rather than emotion.&lt;/p&gt;
&lt;p&gt;This post doesn’t have specific investment strategies or profit ideas. But if it prompts you to reexamine how you look at your own assets, that’s enough.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[자산 관리는 상태 관리의 문제다]]></title><description><![CDATA[이번 포스팅에서는 기술적인 내용보다는 일상에 가까운 내용에 대해서 한번 이야기해보려고 한다. 바로 자산 관리에 대한 이야기이다. 일단 필자는 부자가 아니며, 일확천금을 만들어 낼 수 있는 투자 비법 같은 것이 있는 것도 아니다. 그렇기에 일반적인 직장인으로서 꾸준히 자산을 늘려갈 수 있는 방법에 대해서 오랫동안 고민해왔다는 점을 이야기하고 싶다.]]></description><link>https://evan-moon.github.io/2026/01/17/assets-management/</link><guid isPermaLink="false">20260117-assets-management</guid><pubDate>Sat, 17 Jan 2026 03:06:30 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 기술적인 내용보다는 일상에 가까운 내용에 대해서 한번 이야기해보려고 한다. 바로 자산 관리에 대한 이야기이다.&lt;/p&gt;
&lt;p&gt;일단 필자는 부자가 아니며, 일확천금을 만들어 낼 수 있는 투자 비법 같은 것이 있는 것도 아니다. 그렇기에 일반적인 직장인으로서 꾸준히 자산을 늘려갈 수 있는 방법에 대해서 오랫동안 고민해왔다는 점을 이야기하고 싶다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;물론 이미 사업이나 투자를 통해 큰 돈을 버신 분들이 보시기에는 다소 뻔한 이야기들일 수 있지만, 필자처럼 평범한 조건에서 자산을 관리해나가야 하는 사람에게는 충분히 공감할 수 있는 이야기라고 생각해, 필자 나름의 기준을 한번 정리해보려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;현재-상태를-모르면-어떤-판단도-할-수-없다&quot; style=&quot;position:relative;&quot;&gt;현재 상태를 모르면, 어떤 판단도 할 수 없다&lt;a href=&quot;#%ED%98%84%EC%9E%AC-%EC%83%81%ED%83%9C%EB%A5%BC-%EB%AA%A8%EB%A5%B4%EB%A9%B4-%EC%96%B4%EB%96%A4-%ED%8C%90%EB%8B%A8%EB%8F%84-%ED%95%A0-%EC%88%98-%EC%97%86%EB%8B%A4&quot; aria-label=&quot;현재 상태를 모르면 어떤 판단도 할 수 없다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자산 관리를 하면서 필자가 가장 중요하게 생각하는 것 중 하나는, 현재 내가 어디에 서 있는지를 아는 것이다. 이를 위해 필자는 자산 데이터를 꾸준히 기록해왔다.&lt;/p&gt;
&lt;p&gt;처음부터 자산 관리를 잘할 수는 없다. 대부분은 시행착오를 겪고, 그 과정에서 조금씩 기준을 만들어간다. 그런데 지금 내 상태가 어떤지조차 알 수 없다면, 잘하고 있는지 아닌지를 판단하는 것 자체가 불가능하다.&lt;/p&gt;
&lt;p&gt;필자는 개발자로 일을 시작했던 2018년부터 매월 말 자산 스냅샷을 기록해오고 있다. 이렇게 쌓인 데이터는 지금에 와서는 자산의 변화 과정을 한눈에 보여주지만, 당시에는 오히려 혼란스러울 때도 많았다. 자산이 늘어난 달도 있었고, 예상보다 크게 줄어든 달도 있었다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ee3caeb1f1b5b18d2656441300609777/d698c/chart.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 43.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAq0lEQVR42q2QgQrDMAhE8/+/2zZGE3WnjlI6BoM1cFStvlxs/ugxb8+x1I3pOaAKudL2P9B0uU321beEtl9381myBOnYS3wgl29Aq4E13WSguSMWuJkJMTixqIXmqFp81x0Yi8Ut1QRQNnHtJ3KpoRMeWhfh+a0SwQDXTfkDYHu7TGnGV0XtrjDUjh3LBECEnYjSKDM7j5HxGOQzXAPSe89ehZOIgy0i51ycF6fjyeS7d8mWAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;chart&quot; title=&quot;&quot; src=&quot;/static/ee3caeb1f1b5b18d2656441300609777/6af66/chart.png&quot; srcset=&quot;/static/ee3caeb1f1b5b18d2656441300609777/69538/chart.png 160w,
/static/ee3caeb1f1b5b18d2656441300609777/72799/chart.png 320w,
/static/ee3caeb1f1b5b18d2656441300609777/6af66/chart.png 640w,
/static/ee3caeb1f1b5b18d2656441300609777/d9199/chart.png 960w,
/static/ee3caeb1f1b5b18d2656441300609777/21b4d/chart.png 1280w,
/static/ee3caeb1f1b5b18d2656441300609777/d698c/chart.png 1846w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;이렇게 데이터를 쌓아두면 시장에 어떤 이슈가 있을 때 내 자산이 어떻게 변동되는지, 월 자산 성장률은 어떻게 되는지, 5년 전에 비해 내 자산이 얼마나 늘어났는지 등을 한번에 볼 수 있다.&lt;/p&gt;
&lt;p&gt;기록을 남기면서 가장 자주 들었던 생각은 “이 방향이 맞는 걸까?”였다. 중요한 것은 자산이 오르거나 내린 사실 자체가 아니라, 그때마다 감정에 휘둘리지 않고 이전에 세워둔 판단 기준을 유지할 수 있었는지였다.&lt;/p&gt;
&lt;p&gt;지금의 수치는 결과적으로 보이는 숫자일 뿐이다. 필자에게 이 데이터의 진짜 가치는, 불확실한 상황 속에서도 현재의 선택이 과거의 판단과 얼마나 일관되어 있는지를 확인할 수 있었다는 점에 있다. 만약 이런 기록이 없었다면, 필자는 중간 어딘가에서 방향을 잃었을 가능성이 크다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 자산 관리에서 데이터를 미래를 예측하기 위한 도구로 사용하지 않는다. 다만 지금 내가 어디에 서 있는지를 확인하고, 판단의 기준이 흐트러지지 않았는지를 점검하기 위한 용도로 활용할 뿐이다.&lt;/p&gt;
&lt;h2 id=&quot;정확한-숫자보다-올바른-추상화가-먼저다&quot; style=&quot;position:relative;&quot;&gt;정확한 숫자보다, 올바른 추상화가 먼저다&lt;a href=&quot;#%EC%A0%95%ED%99%95%ED%95%9C-%EC%88%AB%EC%9E%90%EB%B3%B4%EB%8B%A4-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%B6%94%EC%83%81%ED%99%94%EA%B0%80-%EB%A8%BC%EC%A0%80%EB%8B%A4&quot; aria-label=&quot;정확한 숫자보다 올바른 추상화가 먼저다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사실 금융이나 자산 관리에서 데이터가 중요하다는 점은 이미 많은 사람들이 알고 있다. 그 출발점으로 가장 많이 선택되는 것이 바로 가계부다. 수입과 지출을 기록하면서 내 현금 흐름이 어떻게 움직이는지를 확인하는 것은 분명 의미 있는 일이다.&lt;/p&gt;
&lt;p&gt;문제는 이 가계부라는 도구가 생각보다 오래 가지 않는다는 데 있다. 매달 수십, 수백 건에 달하는 소비 내역을 하나하나 분류하고, 어디에 얼마를 썼는지 정확히 맞추려다 보면 어느 순간부터 부담이 된다. 계산이 조금이라도 어긋나면 괜히 신경이 쓰이고, 기록이 밀리기 시작하면 아예 손을 놓게 된다. 필자 역시 이런 과정을 몇 번 반복하다가 가계부를 꾸준히 쓰는 것은 포기했다.&lt;/p&gt;
&lt;p&gt;근데 잘 생각해보면 문제를 약간 다르게 볼 수 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 270px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f12412c188bfb126bc3bedd4b1a1c470/01bf6/um.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAADWElEQVR42hXLWVMaBwAA4H3v9MFkak0y1IRqwn3usrALy6IcAgsGXEFEQY5ExAtBIHIsyABOgYDGEEysIZomBklaNaRmTNpp69jmpTN5aP9P7ff+AT+/PtiurtaygUrKV0p4SwlPLEBiEi4svAmBHBHIk8AiFJUocQRXoTAsYjL7uHwWYVBnYneBD53jRpmqZf7P8emRtbh7bsosETFgMYMvZEESoUIhRVCpHEOlKCyCBHwBm8NjgiKOSYsCnYPWk1r2ftpfSfqWvOZibCIwqZdCLDbzulLMuDeOF31DWY8u6tQ6jXJMJr7F6L/F7KN/SwN5N4HW7k6jnFrPTidmR60aJOw3Z0K2xYDNYVUGTeBdg3jBwM7ZwXmCHxmRUDaYxJjd3V1Xr3zV090FHL7ab5Soh/nZCYsKEvRRIVtueTyX8KUj43nP4LQepMYVNS8+S0BBAq55scIEyqJdIoW9LNplYG/nUaNCbWRnXKTKPizPhMcucibmSSw5N0Pmx8GBd1nHYcaxtUB8vzTcDJsiVghh9ES1rDG1EPj4/mS7mi2n/YWYi1CDi3dMhfjkRc7Ep0rzxotc9alLblUzPNwIanM2cMYgmFIyEiMyJyEF3r45qJcTD/LBdcrvtWuoiGM1PEZF3dl7nvtRO+WQkSjDpxN858HLbjQ5Kg6axAu3kSkT7CBkwIunW/VKOjLndLtHjtqPzz/sHe9X27vlp/VUmZrRgTSXnO1CWHasP+uAly0i75BwzKIhjYjrtgIorCaHSSumNwiVgyvp0N9nrV+On2wU53/cKyaX7yjZX09iDLukL24VmCW9OKfHYwBDc/6A1xZ0GoABwiRVqZX6IcJuUenwo9b62UmzXlrqvCq3dysQl87q7eLQL+uhG8yrX2Lcazu1HJWK59JznR+qgACRgxiOaNTGUVKC4/l86NPp83opfPrmwec/9u02E/2bK7z+a7RLXyh414vp5aPWHukgGxup8/dNAFYNQkoVPDCIE3pEqwvOu387eba5FvrpeemfP9ubtUw/j6vDYbsRX8tET9++Tq2k1YShs7/5e6cJ3GCwGXwBqtFoLRY6i2226j+fH27XVtrNwr+fDv/6+JJ0OmRKxdyMb+vhenwlLh3QJpOLZ++e/Xq88x9ZGD9eANmthgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;um&quot; title=&quot;&quot; src=&quot;/static/f12412c188bfb126bc3bedd4b1a1c470/01bf6/um.png&quot; srcset=&quot;/static/f12412c188bfb126bc3bedd4b1a1c470/69538/um.png 160w,
/static/f12412c188bfb126bc3bedd4b1a1c470/01bf6/um.png 270w&quot; sizes=&quot;(max-width: 270px) 100vw, 270px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;꼭 정확해야할 필요가 있나...?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;문제의 핵심은 기록을 안 한 데 있는 것이 아니라, 정확해야 한다는 전제를 너무 당연하게 받아들였다는 점에 있었던 것 같다. 우리가 개인 자산을 관리하면서 회계 결산이나 세무 신고를 하는 것도 아닌데, 원 단위까지 맞아떨어지는 데이터가 과연 필수적일까 하는 의문이 들었다.&lt;/p&gt;
&lt;p&gt;필자가 생각하기에 개인 자산 관리에서 더 중요한 것은 정밀한 숫자가 아니라, 금융이라는 복잡한 현실을 판단 가능한 수준으로 단순화해서 바라볼 수 있는가에 가깝다. 이 점에서 자산 관리는 개발자가 복잡한 시스템을 다루는 방식과 꽤 닮아 있다.&lt;/p&gt;
&lt;p&gt;우리는 프로그램을 작성할 때 메모리 주소를 직접 다루지 않는다. 비트 단위의 연산으로 모든 것을 해결하려고도 하지 않는다. 대신 변수와 타입, 인터페이스 같은 추상화된 개념을 사용한다. 세밀한 제어를 일부 포기하는 대신, 전체 구조를 이해하고 더 나은 판단을 내릴 수 있는 여지를 확보하기 위해서다.&lt;/p&gt;
&lt;p&gt;자산 관리에서도 비슷한 일이 벌어진다고 생각한다. 모든 소비를 정확히 분해하고 분류하다 보면 오히려 판단은 느려지고, 감정이 개입될 여지는 커진다. 반대로 몇 개의 핵심 지표로 구조를 요약해두면, 지금 상태가 위험한지, 유지 가능한지, 혹은 공격적인 선택을 해도 되는지에 대한 판단을 훨씬 빠르게 내릴 수 있다.&lt;/p&gt;
&lt;p&gt;결국 자산 관리에서 추상화가 중요한 이유는 귀찮음을 피하기 위해서가 아니라, 판단의 기준을 단순하게 만들기 위해서다. 어디에 1,000원을 더 썼는지보다 중요한 것은 지금 내가 재정적으로 안전한 상태인지, 현재의 현금 흐름이 지속 가능한 구조인지, 그리고 원하는 목표에 도달하기 위해 어떤 선택지를 가지고 있는지다.&lt;/p&gt;
&lt;p&gt;필자는 자산 관리가 숫자를 얼마나 정확하게 맞추느냐의 문제가 아니라, 불확실한 상황에서도 흔들리지 않을 기준을 세우는 과정이라고 생각한다. 그리고 그 기준은 언제나 정밀한 데이터가 아니라, 잘 설계된 추상화 위에서 만들어진다.&lt;/p&gt;
&lt;h2 id=&quot;자산은-흐름과-상태로-요약할-수-있다&quot; style=&quot;position:relative;&quot;&gt;자산은 흐름과 상태로 요약할 수 있다&lt;a href=&quot;#%EC%9E%90%EC%82%B0%EC%9D%80-%ED%9D%90%EB%A6%84%EA%B3%BC-%EC%83%81%ED%83%9C%EB%A1%9C-%EC%9A%94%EC%95%BD%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8B%A4&quot; aria-label=&quot;자산은 흐름과 상태로 요약할 수 있다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 자산 관리는 정밀도의 문제가 아니라 추상화의 문제라고 이야기했다. 그렇다면 개인 자산을 판단 가능한 수준으로 추상화하기 위해서는 어떤 정보들이 필요할까?&lt;/p&gt;
&lt;p&gt;이러한 거시적인 판단들을 내리기 위해 필요한 정보는 생각보다 많지 않은데, 크게는 자산의 흐름과 현재 상태 데이터, 이 두 가지만으로 충분하다.&lt;/p&gt;
&lt;p&gt;이는 마치 기업의 재무제표에 포함되는 현금 흐름표와 재무 상태표와도 유사하다. 기본적으로는 이 두 가지 표만 봐도 해당 기업이 돈을 어떻게 썼고 어떻게 벌었는지, 현재 재무 상태는 어떠한지와 같은 주요 정보들을 빠르게 이해할 수 있다.&lt;/p&gt;
&lt;p&gt;개인의 자산 관리도 크게 다르지 않다고 생각한다. 개인이 기업처럼 복잡한 회계를 할 필요는 없지만, 최소한 지금 돈이 어떤 경로로 들어오고 나가는지, 그리고 현재 자산이 어떤 형태로 구성되어 있는지는 알고 있어야 한다.&lt;/p&gt;
&lt;p&gt;자산의 흐름은 현금 흐름 데이터를 통해 확인할 수 있다. 이번 달에 얼마를 벌었고, 얼마를 썼는지, 그 결과 얼마가 남았는지를 보는 것이다. 이 데이터는 자산 관리의 속도와 방향성을 결정한다. 흐름이 건강하지 않다면 자산은 언젠가 정체되거나 줄어들 수밖에 없다.&lt;/p&gt;
&lt;p&gt;반면 자산의 상태는 스냅샷 데이터로 확인한다. 지금 당장 가용 가능한 현금은 얼마인지, 자산이 어떤 형태로 어디에 묶여 있는지, 부채는 어느 정도인지와 같은 정보들이다. 이 데이터는 현재 내가 감당할 수 있는 리스크의 범위를 보여준다.&lt;/p&gt;
&lt;p&gt;중요한 점은 이 두 데이터 모두 아주 정확할 필요는 없다는 것이다. 개인 자산 관리에서 필요한 것은 숫자의 정밀함이 아니라 구조에 대한 감각이다. 이번 달 지출이 정확히 얼마였는지보다, 대략적인 수입 대비 지출 비율이 어떤지 아는 것이 더 중요하다. 마찬가지로 자산의 현재 가치가 몇 만원 단위까지 맞아떨어지는지보다, 유동성이 높은 자산과 낮은 자산이 어떤 비율로 구성되어 있는지를 아는 것이 더 의미 있다.&lt;/p&gt;
&lt;p&gt;이렇게 흐름과 상태를 분리해서 바라보면, 자산 관리가 훨씬 단순해진다. 흐름이 안정적인지, 상태가 과도한 리스크를 내포하고 있지는 않은지. 이 두 가지 질문에만 답할 수 있어도 대부분의 중요한 의사결정은 가능하다.&lt;/p&gt;
&lt;p&gt;필자는 자산 관리를 하면서 더 많은 데이터를 보려고 애쓰기보다는, 이 두 가지 정보를 꾸준히 확인하는 데 집중해왔다. 그 결과 시장 상황이 바뀌어도, 자산의 규모가 커져도, 판단의 기준 자체는 크게 흔들리지 않았다.&lt;/p&gt;
&lt;p&gt;이제부터는 이 두 가지 정보를 각각 어떻게 바라보고 관리하고 있는지에 대해 조금 더 구체적으로 이야기해보려고 한다. 먼저 현금 흐름부터 살펴보자.&lt;/p&gt;
&lt;h3 id=&quot;현금-흐름-정밀한-로그가-아닌-비율을-본다&quot; style=&quot;position:relative;&quot;&gt;현금 흐름: 정밀한 로그가 아닌 비율을 본다&lt;a href=&quot;#%ED%98%84%EA%B8%88-%ED%9D%90%EB%A6%84-%EC%A0%95%EB%B0%80%ED%95%9C-%EB%A1%9C%EA%B7%B8%EA%B0%80-%EC%95%84%EB%8B%8C-%EB%B9%84%EC%9C%A8%EC%9D%84-%EB%B3%B8%EB%8B%A4&quot; aria-label=&quot;현금 흐름 정밀한 로그가 아닌 비율을 본다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;자산의 흐름을 파악한다는 것은, 결국 내가 한 달 동안 얼마를 벌었고 그중 얼마를 남겼는지를 확인하는 일에 가깝다. 흔히 현금 흐름을 관리한다고 하면 가계부를 떠올리지만, 필자는 가계부를 쓰는 방식이 반드시 정답이라고 생각하지는 않는다.&lt;/p&gt;
&lt;p&gt;가계부의 목적은 어디에 얼마를 썼는지를 정확히 기록하는 데 있다기보다는, 내 수입과 지출의 구조를 이해하는 데 있다. 그런데 많은 경우 이 목적과 수단이 뒤바뀐다. 기록 자체가 부담이 되기 시작하면, 흐름을 이해하기는커녕 기록을 유지하는 것조차 어려워진다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 현금 흐름을 관리할 때 세부 지출 항목보다는 훨씬 단순한 기준을 사용한다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;대카테고리&lt;/th&gt;
&lt;th&gt;중카테고리&lt;/th&gt;
&lt;th&gt;카테고리&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;수입&lt;/td&gt;
&lt;td&gt;근로&lt;/td&gt;
&lt;td&gt;급여&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;근로&lt;/td&gt;
&lt;td&gt;사업&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;부채&lt;/td&gt;
&lt;td&gt;대출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;투자&lt;/td&gt;
&lt;td&gt;배당금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;매도금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;이자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;지출&lt;/td&gt;
&lt;td&gt;소비&lt;/td&gt;
&lt;td&gt;개인소비&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;고정비&lt;/td&gt;
&lt;td&gt;보험&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;통신비&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;공과금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;주거&lt;/td&gt;
&lt;td&gt;집세&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;관리비&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이때 이 카테고리에는 어떤 정답도 없다. 중요한 것은 남들도 이렇게 하니까 따라 하는 것이 아니라, 내가 어떤 데이터를 보고 싶어서 이렇게 나눴는지다.&lt;/p&gt;
&lt;p&gt;예를 들어 필자의 경우 수입에서는 근로와 투자를 구분해두었고, 지출에서는 고정비와 주거를 따로 떼어두었다. 불로소득의 비중이 어느 정도인지, 소득 대비 주거 비용이 얼마나 되는지를 알고 싶었기 때문이다. 만약 이런 정보가 필요 없다면, 소비를 하나의 카테고리로 묶어도 전혀 문제 없다.&lt;/p&gt;
&lt;p&gt;이렇게 대략적인 흐름만 정리해두어도, 한 달 동안 내가 얼마나 벌었고 그중 얼마를 남겼는지는 충분히 파악할 수 있다.&lt;/p&gt;
&lt;p&gt;이렇게 캐시 플로우를 정리하는 것만으로도 많은 정보들을 알 수 있지만 필자가 생각했을 때 가장 중요한 데이터는 바로 이익률, 즉 한 달 수입 중 대략 몇 퍼센트를 남기고 있는지다.&lt;/p&gt;
&lt;p&gt;이 하나의 숫자는 생각보다 많은 정보를 담고 있다. 수입이 늘고 있는지, 지출이 과도한지, 혹은 현재의 생활 수준이 자산 증가 속도에 비해 과한지를 직관적으로 보여준다. 어디에 5만 원을 더 썼는지는 몰라도, 이번 달에 수입의 30%를 남겼는지 50%를 남겼는지는 분명히 알 수 있다.&lt;/p&gt;
&lt;p&gt;참고로 2025년 기준 대한민국 가계의 평균 소득 대비 소비 비율은 약 67% 수준이다. 즉, 평균적으로는 소득의 약 3분의 1 정도를 남기고 있다는 의미다. 대출 원금과 이자까지 포함하면 실제로 체감되는 지출 비율은 이보다 더 높다. 이 수치는 절대적인 기준이라기보다는, 내 현금 흐름이 사회 평균 대비 어느 지점에 있는지를 가늠하기 위한 참고선 정도로 보면 된다.&lt;/p&gt;
&lt;p&gt;이 수치는 절대적인 기준이라기보다는, 내 현금 흐름이 사회 평균 대비 어느 지점에 있는지를 가늠하기 위한 참고선에 가깝다.&lt;/p&gt;
&lt;p&gt;만약 평균을 기준으로 삼는다면, 소득의 30% 이상을 남기고 있다면 최소한 구조적으로 크게 무리한 상태는 아닐 가능성이 높다. 물론 개인의 상황에 따라 이 수치는 얼마든지 달라질 수 있다. 중요한 것은 정확한 퍼센트가 아니라, 내 현금 흐름이 어떤 방향으로 움직이고 있는지를 지속적으로 확인하는 것이다.&lt;/p&gt;
&lt;p&gt;물론 가계부처럼 지출 내역을 세세하게 분석하는 접근이 의미 없다고 생각하지는 않는다. 지출을 줄이기 위해서는 어디에 돈이 새고 있는지를 아는 것이 필요할 수도 있다. 다만 필자는 지출을 줄이는 것보다, 수입 구조를 개선하는 데 먼저 집중하는 편이 낫다고 생각한다.&lt;/p&gt;
&lt;p&gt;어차피 지출을 줄이는 데에는 명확한 한계가 있기 때문이다. 월세를 안 낼 수는 없고, 생활비를 완전히 없앨 수도 없다. 아무리 절약해도 도달할 수 있는 최소치는 정해져 있다.&lt;/p&gt;
&lt;p&gt;반면 수입은 구조에 따라 얼마든지 확장될 수 있다. 연봉 인상이나 이직, 투자 수익, 배당 소득, 부업처럼 수입의 경로를 하나씩 늘려가는 것은 시간이 걸리더라도 상방이 열려 있다. 이 차이는 단순히 금액의 문제가 아니라, 장기적으로 유지 가능한 전략인지의 문제라고 생각한다.&lt;/p&gt;
&lt;p&gt;그래서 필자가 현금 흐름에서 가장 중요하게 보는 것은 “얼마를 썼는가”가 아니라 “얼마를 남겼는가”다. 이익률이 안정적으로 유지된다면, 자산을 늘릴 수 있는 여지는 자연스럽게 따라온다. 그리고 이 여지가 바로 다음 단계의 선택, 즉 자산을 어떻게 배분하고 어떤 리스크를 감당할 수 있을지를 결정하는 기반이 된다.&lt;/p&gt;
&lt;p&gt;이제 현금 흐름이라는 “속도”에 대한 이야기를 했으니, 다음으로는 자산의 “상태”, 즉 현재 자산이 어떤 형태로 구성되어 있는지를 살펴볼 차례다.&lt;/p&gt;
&lt;h3 id=&quot;자산-상태-규모가-아니라-구조를-본다&quot; style=&quot;position:relative;&quot;&gt;자산 상태: 규모가 아니라 구조를 본다&lt;a href=&quot;#%EC%9E%90%EC%82%B0-%EC%83%81%ED%83%9C-%EA%B7%9C%EB%AA%A8%EA%B0%80-%EC%95%84%EB%8B%88%EB%9D%BC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EB%B3%B8%EB%8B%A4&quot; aria-label=&quot;자산 상태 규모가 아니라 구조를 본다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;현금 흐름 데이터가 돈의 수입과 지출이라는 ‘흐름’을 보여준다면, 자산 스냅샷은 말 그대로 현재 상태를 보여주는 데이터다. 필자는 정기적으로 지금 당장 가용 가능한 현금이 얼마인지, 자산이 어떤 형태로 어디에 묶여 있는지를 확인한다. 이때 각 자산의 금액이 정확히 맞아떨어질 필요는 없다고 생각한다. 필자의 경우에는 대략 100만 원 정도의 오차는 충분히 허용 가능한 범위로 보고 있다.&lt;/p&gt;
&lt;p&gt;자산 스냅샷을 구성할 때도 현금 흐름과 마찬가지로 중요한 것은 정밀함이 아니라 구조다. 필자가 사용하는 자산 카테고리는 대략 다음과 같다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;대카테고리&lt;/th&gt;
&lt;th&gt;중카테고리&lt;/th&gt;
&lt;th&gt;카테고리&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;자산&lt;/td&gt;
&lt;td&gt;현금&lt;/td&gt;
&lt;td&gt;KRW&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;USD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;예금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;주택청약&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;투자&lt;/td&gt;
&lt;td&gt;국내주식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;해외주식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;부동산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;연금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;기타&lt;/td&gt;
&lt;td&gt;자동차&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;주택 보증금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;부채&lt;/td&gt;
&lt;td&gt;단기부채&lt;/td&gt;
&lt;td&gt;신용카드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;장기부채&lt;/td&gt;
&lt;td&gt;대출&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이 카테고리 역시 정답이 있는 것은 아니다. 중요한 것은 이 구분을 통해 어떤 질문에 답하고 싶은지다. 필자의 경우에는 자산의 총액보다도, 즉시 유동화가 가능한 자산과 그렇지 않은 자산이 어떤 비율로 구성되어 있는지를 가장 중요하게 본다.&lt;/p&gt;
&lt;p&gt;같은 금액의 자산을 가지고 있더라도, 그 자산이 어떤 형태로 묶여 있는지에 따라 상황은 전혀 다르게 전개된다. 현금이나 주식처럼 비교적 빠르게 현금화할 수 있는 자산의 비중이 충분하다면, 시장이 흔들릴 때도 선택지가 남아 있다. 반대로 대부분의 자산이 보증금이나 부동산처럼 쉽게 움직일 수 없는 형태로 묶여 있다면, 작은 변동성도 곧바로 압박으로 다가온다. 이 차이가 바로 유동성이 가져다주는 혜택이다.&lt;/p&gt;
&lt;p&gt;유동성은 단순히 “얼마나 빨리 팔 수 있는가”의 문제가 아니다. 필자가 느끼기에 유동성은 선택권에 가깝다. 유동성이 충분한 상태에서는 기다릴 수 있고, 상황이 바뀌면 기회를 선택할 수도 있다. 반면 유동성이 부족한 상태에서는 아무것도 하지 않는 선택조차 쉽지 않다. 시장의 변동성이 그대로 개인의 심리적 부담으로 전이되기 때문이다.&lt;/p&gt;
&lt;p&gt;이런 관점에서 보면 자산 스냅샷은 단순히 자산 규모를 확인하기 위한 수단이 아니라, 현재 내가 감당할 수 있는 리스크의 범위를 가늠하기 위한 도구에 가깝다. 그래서 필자는 자산 스냅샷을 볼 때 특정 자산의 가격 자체보다는, 전체 구조가 지금의 나에게 과도한 부담을 주고 있지는 않은지를 먼저 확인한다.&lt;/p&gt;
&lt;p&gt;그렇다면 자산 상태를 점검할 때 참고할 만한 지표는 무엇일까. 필자가 하나의 참고 지표로 사용하는 것은 월 자산 성장률이다. 여기서 중요한 점은 이 수치를 목표로 삼지 않는다는 것이다. 매달 자산을 몇 퍼센트씩 늘려야 한다는 식의 기준을 세우기보다는, 지금의 방향성이 유지되고 있는지를 확인하기 위한 보조 지표로 활용한다.&lt;/p&gt;
&lt;p&gt;작년에 발표된 &lt;a href=&quot;https://www.korea.kr/news/policyNewsView.do?newsId=148955870&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;기획 재정부 뉴스&lt;/a&gt;에 따르면, 2025년 한 해 동안 가구당 평균 자산 증가율은 약 4.9% 수준이었다고 한다. 이를 단순히 월 단위로 환산하면 대략 0.4% 정도다. 물론 자산은 소득보다 변수의 폭이 훨씬 넓고, 개인 간 편차도 크기 때문에 이 평균값 자체에 큰 의미를 두기는 어렵다. 다만 이런 수치를 알고 있으면, 내 자산이 사회 전체의 흐름과 비교했을 때 크게 벗어나고 있는지 정도는 가늠해볼 수 있다.&lt;/p&gt;
&lt;p&gt;여기서 중요한 것은 이 숫자가 정답이 아니라는 점이다. 월 성장률이 높다고 해서 반드시 좋은 상태라고 볼 수도 없고, 낮다고 해서 잘못된 선택을 하고 있다고 단정할 수도 없다. 중요한 것은 자산이 장기적으로 같은 방향을 유지하고 있는지, 그리고 그 과정에서 내가 감당하기 어려운 리스크를 쌓아가고 있지는 않은지다.&lt;/p&gt;
&lt;p&gt;필자는 자산 성장에서 속도보다 방향성이 훨씬 중요하다고 생각한다. 단기간에 큰 수익을 내는 것보다, 매달 크지 않은 변화라도 일관된 방향을 유지하는 것이 결국 더 오래 갈 수 있는 방식이기 때문이다. 그래서 매월 말 현금 흐름과 자산 스냅샷을 함께 정리하면서, 지난달과 비교해 어떤 변화가 있었는지, 어떤 자산이 구조적으로 부담이 되고 있는지를 점검한다.&lt;/p&gt;
&lt;p&gt;그리고 이 과정에서 자연스럽게 다음 질문으로 이어진다. 지금의 자산 구조는 어느 정도의 변동성을 견딜 수 있는 상태인가. 이 질문에 답하기 위해서 필자는 안전자산의 비중과 투자 전략을 함께 고민하게 된다.&lt;/p&gt;
&lt;h2 id=&quot;투자는-수익이-아니라-상태를-바꾸는-선택이다&quot; style=&quot;position:relative;&quot;&gt;투자는 수익이 아니라 상태를 바꾸는 선택이다&lt;a href=&quot;#%ED%88%AC%EC%9E%90%EB%8A%94-%EC%88%98%EC%9D%B5%EC%9D%B4-%EC%95%84%EB%8B%88%EB%9D%BC-%EC%83%81%ED%83%9C%EB%A5%BC-%EB%B0%94%EA%BE%B8%EB%8A%94-%EC%84%A0%ED%83%9D%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;투자는 수익이 아니라 상태를 바꾸는 선택이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자산 관리를 어느 정도 해오다 보면, 결국 투자를 어떻게 바라볼 것인가라는 질문에 도달하게 된다. 더 많은 수익을 얻기 위해서라기보다는, 지금의 자산 구조가 시간이 지나도 같은 방향을 유지할 수 있을지에 대한 고민에 가깝다.&lt;/p&gt;
&lt;p&gt;많은 경우 투자는 수익률의 문제로 이야기된다. 어떤 종목이 더 오를지, 언제 사고 언제 팔아야 할지, 혹은 어떤 전략이 더 높은 수익을 낼 수 있는지에 대한 이야기들이다. 물론 이런 논의들이 전혀 중요하지 않다고 말할 수는 없다. 다만 필자가 경험해온 바로는, 이런 이야기들은 모두 하나의 전제가 깔려 있을 때에만 의미를 갖는다.&lt;/p&gt;
&lt;p&gt;바로, 그 변동성을 감당할 수 있는 상태인가라는 전제다.&lt;/p&gt;
&lt;p&gt;투자는 본질적으로 변동성을 동반한다. 가격은 오를 수도 있고, 예상과 다르게 움직일 수도 있다. 문제는 이 변동성이 누구에게나 같은 의미로 다가오지 않는다는 점이다. 같은 10%의 하락이라도 어떤 사람에게는 단순한 숫자의 변화일 수 있지만, 어떤 사람에게는 판단을 뒤흔드는 압박으로 작용한다.&lt;/p&gt;
&lt;p&gt;이 차이를 만드는 것은 투자 지식이나 종목 선택 능력보다는, 자산 구조와 상태에 가깝다고 생각한다. 특히 정기적이고 예측 가능한 현금 흐름이 있는지, 자산이 한쪽으로 과도하게 쏠려 있지는 않은지, 그리고 지금의 생활과 심리 상태가 이 변동성을 견딜 수 있는지와 같은 요소들이 훨씬 더 큰 영향을 미친다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 투자를 이야기할 때, 먼저 “얼마를 벌 수 있는가”보다 “어떤 상태에서 이 선택을 하고 있는가”를 먼저 점검해야 한다고 생각한다. 리스크를 얼마나 감수할 수 있는지, 그리고 그 리스크가 현실적인 생활 압박이나 감정적인 판단으로 이어지지는 않는지 말이다.&lt;/p&gt;
&lt;p&gt;이 관점에서 보면, 투자와 리스크 관리는 서로 분리된 주제가 아니다. 오히려 리스크를 어떻게 다루느냐에 따라, 투자라는 행위의 성격 자체가 달라진다. 같은 전략이라도 어떤 구조 위에서 실행하느냐에 따라 전혀 다른 결과로 이어질 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;이제부터는 이 관점에서, 리스크 관리를 어떻게 이해해야 하는지, 그리고 그 리스크를 흡수하는 데 있어 근로소득과 안전자산이 어떤 역할을 하는지에 대해 차례대로 이야기해보려고 한다.&lt;/p&gt;
&lt;h3 id=&quot;리스크-관리는-판단을-보호하기-위한-설계다&quot; style=&quot;position:relative;&quot;&gt;리스크 관리는 판단을 보호하기 위한 설계다&lt;a href=&quot;#%EB%A6%AC%EC%8A%A4%ED%81%AC-%EA%B4%80%EB%A6%AC%EB%8A%94-%ED%8C%90%EB%8B%A8%EC%9D%84-%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%9C-%EC%84%A4%EA%B3%84%EB%8B%A4&quot; aria-label=&quot;리스크 관리는 판단을 보호하기 위한 설계다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 생각하는 투자의 기본기는 사실 굉장히 단순하다. 싸게 사서 비싸게 파는 것이다. 이 문장을 부정할 수 있는 사람은 거의 없을 것이다. 문제는 이 단순한 원칙을 실제로 지키는 것이 생각보다 매우 어렵다는 데 있다.&lt;/p&gt;
&lt;p&gt;이게 어려운 이유는 계산이 복잡해서도, 정보가 부족해서도 아니다. 대부분의 경우 실패의 원인은 감정이다. 가격이 오를 때는 더 오를 것 같고, 가격이 떨어질 때는 더 떨어질 것 같다는 생각이 자연스럽게 든다. 머리로는 지금이 싸다고 판단하면서도, 손은 매수 버튼 위에서 쉽게 움직이지 않는다.&lt;/p&gt;
&lt;p&gt;특히 하락 구간에서는 이 감정이 더 강하게 작용한다. 가격이 내려간다는 사실보다도, “혹시 내가 틀린 선택을 한 건 아닐까”라는 불안이 먼저 올라온다. 그리고 이 불안은 판단의 기준을 조금씩 흐리게 만든다. 원래 세워두었던 가설이나 조건은 점점 뒷전으로 밀리고, 당장의 가격 움직임이 모든 의사결정을 지배하게 된다.&lt;/p&gt;
&lt;p&gt;이 지점에서 많은 사람들이 투자가 어렵다고 느낀다. 하지만 필자는 이 문제를 투자 기법의 문제라기보다는, 상태의 문제라고 생각한다. 지금의 내가 이 변동성을 감정적으로 견딜 수 있는 상태인가에 대한 문제다.&lt;/p&gt;
&lt;p&gt;리스크 관리는 바로 이 상태를 다루는 일에 가깝다. 필자가 생각하는 리스크 관리는 손실을 피하는 기술이 아니라, 감정이 판단을 덮어버리지 않도록 환경을 설계하는 과정이다. 가격이 흔들려도 당장 결정을 내려야 할 이유가 없는 여유, 판단이 틀렸을 가능성을 인정하더라도 다음 선택을 할 수 있는 시간, 그리고 처음 세워둔 기준을 끝까지 검증해볼 수 있는 심리적 거리감을 확보하는 일이다.&lt;/p&gt;
&lt;p&gt;이런 환경이 갖춰져 있을 때에야 비로소 투자의 기본기가 작동하기 시작한다. 가격이 떨어졌을 때 공포가 아니라 근거를 다시 점검할 수 있고, 가격이 올랐을 때도 흥분이 아니라 원래의 가설을 되짚어볼 수 있다. 싸게 사서 비싸게 판다는 단순한 원칙은, 감정을 통제할 수 있는 구조 위에서만 의미를 갖는다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 투자를 이야기할 때 “얼마를 벌 수 있는가”보다 “이 선택을 감당할 수 있는 상태인가”를 먼저 묻는 편이다. 같은 전략이라도 어떤 자산 구조, 어떤 현금 흐름, 어떤 심리적 여유 위에서 실행되느냐에 따라 결과는 전혀 달라질 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;이렇게 보면 투자의 본질은 결국 가격을 맞히는 능력이 아니라, 감정이 개입되지 않도록 환경을 설계하는 일에 가깝다. 그리고 이 환경을 실제로 떠받치고 있는 요소들은 생각보다 훨씬 현실적인 것들이다.&lt;/p&gt;
&lt;p&gt;이제부터는 이 관점에서, 이러한 리스크 관리 환경을 구성하는 핵심 요소 중 하나인 근로소득이 투자에서 어떤 역할을 하는지, 그리고 왜 이 요소가 자주 과소평가되는지에 대해 이야기해보려고 한다.&lt;/p&gt;
&lt;h3 id=&quot;근로소득은-가장-안정적인-헷징-레이어다&quot; style=&quot;position:relative;&quot;&gt;근로소득은 가장 안정적인 헷징 레이어다&lt;a href=&quot;#%EA%B7%BC%EB%A1%9C%EC%86%8C%EB%93%9D%EC%9D%80-%EA%B0%80%EC%9E%A5-%EC%95%88%EC%A0%95%EC%A0%81%EC%9D%B8-%ED%97%B7%EC%A7%95-%EB%A0%88%EC%9D%B4%EC%96%B4%EB%8B%A4&quot; aria-label=&quot;근로소득은 가장 안정적인 헷징 레이어다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;“월급은 의미 없다”, “근로소득으로는 부자가 될 수 없다”는 말은 투자 이야기를 할 때 거의 상식처럼 소비된다.&lt;/p&gt;
&lt;p&gt;특히 시장이 좋았던 시기에는 이런 말이 더 쉽게 퍼졌다. 자산 가격이 빠르게 오르는 구간에서, 매달 고정적으로 들어오는 월급은 느리고 답답해 보인다. 투자 수익과 나란히 놓고 보면 상대적으로 초라해 보이는 것도 사실이다. 하지만 이 문장은 수익의 관점에서만 부분적으로 맞을 뿐, 리스크의 관점에서는 결정적으로 틀린 말이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 언급했듯이 투자는 수익을 만드는 행위이기 이전에 변동성을 감당하는 행위다. 가격이 오를 수 있다는 말은, 같은 크기로 내려갈 수도 있다는 뜻이다. 이 단순한 사실은 시장이 좋을 때는 쉽게 잊힌다. 숫자가 늘어나는 구간에서는 누구나 리스크를 과소평가한다. 문제는 하락이 시작됐을 때다.&lt;/p&gt;
&lt;p&gt;이때 사람을 압박하는 것은 손실 그 자체가 아니라, 손실이 생활로 번질 수 있다는 가능성이다. 다음 달 생활비, 고정비, 예정된 지출이 머릿속에 떠오르는 순간부터 투자는 확률과 가설의 문제가 아니라 생존의 문제로 바뀐다.&lt;/p&gt;
&lt;p&gt;여기서 근로소득의 역할이 드러난다. 매달 예측 가능한 현금 흐름이 있다는 사실은 단순한 수입 이상의 의미를 가진다. 이는 “지금 당장 틀려도 괜찮다”는 시간을 벌어준다. 가격이 더 내려가도, 판단이 조금 늦어져도, 당장 결정을 내려야 할 이유가 사라진다. 이 여유가 없는 상태에서는 싸게 사는 것도, 비싸게 파는 것도 모두 불가능해진다. 근로소득은 자산을 폭발적으로 키워주지는 않지만, 자산이 감정 때문에 무너지는 것을 막아주는 구조를 만든다.&lt;/p&gt;
&lt;p&gt;투자 수익만으로 생활을 감당해야 하는 상태에서는 작은 변동성조차 과도한 압박으로 작용한다. 같은 10% 하락이라도, 누군가에게는 “기다릴 수 있는 구간”이고 누군가에게는 “지금 팔아야 하는 위기”가 된다. 이 차이는 종목 선택이나 분석 능력에서 나오지 않는다. 현금 흐름의 안정성에서 나온다. 그래서 근로소득을 “언젠가는 벗어나야 할 것”으로만 바라보는 관점은 위험하다. 그것은 투자를 가능하게 만드는 바닥을 스스로 걷어차는 일에 가깝다.&lt;/p&gt;
&lt;p&gt;근로소득은 투자와 경쟁하는 대상이 아니다. 근로소득은 투자가 정상적으로 작동하도록 버텨주는 마지막 안전망이다. 시장이 좋을 때는 누구나 공격적인 포지션을 취할 수 있다. 진짜 차이는 시장이 흔들릴 때 드러난다. 그리고 그 순간 끝까지 판단을 유지할 수 있는 사람은, 대부분 안정적인 현금 흐름을 가진 사람이다. 월급이 의미 없어 보일 때야말로, 월급의 진짜 가치는 가장 깊이 가려져 있는 시기다.&lt;/p&gt;
&lt;h3 id=&quot;안전자산은-전략을-가능하게-만드는-버퍼다&quot; style=&quot;position:relative;&quot;&gt;안전자산은 전략을 가능하게 만드는 버퍼다&lt;a href=&quot;#%EC%95%88%EC%A0%84%EC%9E%90%EC%82%B0%EC%9D%80-%EC%A0%84%EB%9E%B5%EC%9D%84-%EA%B0%80%EB%8A%A5%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%B2%84%ED%8D%BC%EB%8B%A4&quot; aria-label=&quot;안전자산은 전략을 가능하게 만드는 버퍼다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;사실 이 지점에서 한 가지는 솔직하게 밝혀두는 편이 좋을 것 같다.&lt;/p&gt;
&lt;p&gt;필자의 포트폴리오는 결코 보수적이지 않다. 자산의 상당 부분이 TSLA를 중심으로 구성되어 있고, 레버리지 상품인 TSLL이나 NVDA 같은 변동성이 큰 자산도 함께 들고 있다. 변동성만 놓고 보면 누구에게나 추천할 만한 구조는 아니다.&lt;/p&gt;
&lt;p&gt;그럼에도 불구하고 이런 선택을 유지하고 있는 이유는, 필자가 리스크를 가볍게 보고 있어서가 아니다. 오히려 그 반대다. 이 정도의 변동성을 감당할 수 있는 구조가 만들어져 있다고 판단했기 때문에 가능한 선택이다.&lt;/p&gt;
&lt;p&gt;많은 사람들이 공격적인 투자를 “확신”이나 “배짱”의 문제로 이야기한다. 하지만 필자가 경험한 바로는, 감정적으로 흔들리지 않는 투자자일수록 준비가 훨씬 보수적이다. 현금 흐름이 안정적이고, 안전자산이 충분히 확보되어 있으며, 최악의 경우에도 생활이 흔들리지 않는 상태일 때에야 비로소 변동성을 전략의 일부로 받아들일 수 있다.&lt;/p&gt;
&lt;p&gt;필자에게 안전자산은 수익을 내기 위한 자산이 아니다. 가격이 오르지 않아도 상관없고, 몇 년간 그대로 있어도 괜찮다. 중요한 것은 이 자산이 존재함으로써 선택지가 생긴다는 점이다. 가격이 내려갔을 때 추가로 매수할 수 있고, 아무것도 하지 않고 기다릴 수도 있으며, 판단이 틀렸다고 느껴지면 일부를 정리할 여유도 생긴다.&lt;/p&gt;
&lt;p&gt;이 여유가 없는 상태에서의 공격적인 투자는 투자라기보다는 도박에 가깝다. 변동성을 견딜 수 없는 구조에서는, 어떤 종목을 사든 결국 감정이 먼저 무너진다. 반대로 안전자산과 안정적인 현금 흐름이 받쳐주는 구조에서는, 변동성은 위기가 아니라 선택의 조건으로 바뀐다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 자산 증가 속도를 높이고 싶을수록, 오히려 안전자산의 비중을 더 신경 쓴다. 역설적으로 들릴 수 있지만, 가장 공격적인 선택은 항상 가장 보수적인 준비 위에서만 가능하다고 생각한다. 이 구조가 유지되는 한, 가격의 등락은 감정을 자극하는 소음이 아니라 판단을 실행할 수 있는 신호에 가깝다.&lt;/p&gt;
&lt;p&gt;결국 안전자산의 비중을 관리한다는 것은 위험을 피하겠다는 선언이 아니다. 위험을 감당할 수 있는 상태를 유지하겠다는 선택이다. 그리고 이 상태가 유지될 때, 자산 증가는 속도의 문제가 아니라 전략의 문제로 바뀐다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자산 관리를 하면서 필자가 점점 확신하게 된 것은, 자산 증식이 어떤 종목을 고르는 능력이나 시장을 예측하는 감각의 문제가 아니라는 점이다. 오히려 불확실한 상황 속에서도 스스로의 판단을 유지할 수 있는 구조를 만들 수 있는지가 훨씬 중요하다고 느꼈다.&lt;/p&gt;
&lt;p&gt;시장은 언제든 흔들릴 수 있고, 가격은 내가 원하지 않는 방향으로 움직일 수 있다. 환율도, 금리도, 정치적 이슈도 개인이 통제할 수 있는 영역은 아니다. 이런 환경에서 자산 관리를 “잘한다”는 것은, 외부 변수를 제거하는 일이 아니라 그 영향을 감당할 수 있는 상태를 만들어두는 일에 가깝다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 자산을 볼 때 항상 구조부터 확인한다. 현금 흐름이 안정적인지, 자산이 한쪽으로 과도하게 쏠려 있지는 않은지, 그리고 지금의 내가 이 변동성을 감정적으로 견딜 수 있는 상태인지 말이다. 이 기준이 유지되는 한, 가격의 등락은 불안을 자극하는 요소가 아니라 판단을 점검하는 신호로 바뀐다.&lt;/p&gt;
&lt;p&gt;이 글에서 이야기한 현금 흐름, 자산 스냅샷, 리스크 관리, 근로소득, 안전자산 비중은 모두 같은 질문으로 수렴한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“지금의 나는 어떤 선택을 할 수 있는 상태인가?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;자산 관리는 단기간에 답이 나오는 문제가 아니다. 오히려 시간이 지날수록 아주 작은 차이가 누적되어 큰 차이를 만들어내는 영역에 가깝다. 그래서 더더욱 속도보다 방향성이 중요하고, 방향성을 유지하기 위해서는 감정이 아니라 구조에 의존해야 한다고 생각한다.&lt;/p&gt;
&lt;p&gt;이 글이 어떤 투자 전략이나 수익 아이디어를 제공하지는 못했을지도 모른다. 다만 자신의 자산을 바라보는 기준을 한 번쯤 점검해보는 계기가 된다면, 필자에게는 그걸로 충분하다. 적어도 필자는 이런 방식으로, 지금까지의 선택을 이어올 수 있었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[From State to Relationships: The Declarative Overlay Pattern]]></title><description><![CDATA[In this post, continuing from my previous one, I want to dig deeper into how declarative programming manifests in real-world code. Just…]]></description><link>https://evan-moon.github.io/2025/10/07/declarative-overlay-pattern-with-overlay-kit/en/</link><guid isPermaLink="false">20251007-declarative-overlay-pattern-with-overlay-kit-en</guid><pubDate>Tue, 07 Oct 2025 02:10:27 GMT</pubDate><content:encoded>&lt;p&gt;In this post, continuing from my previous one, I want to dig deeper into how declarative programming manifests in real-world code.&lt;/p&gt;
&lt;p&gt;Just explaining theory would be boring, so let’s explore declarative programming in more detail through &lt;a href=&quot;https://overlay-kit.slash.page/en&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;overlay-kit&lt;/a&gt;, a library that makes it easy to manage overlay elements like modals and toasts in React.&lt;/p&gt;
&lt;!--more --&gt;
&lt;h2 id=&quot;the-essence-of-declarative-programming&quot; style=&quot;position:relative;&quot;&gt;The essence of declarative programming&lt;a href=&quot;#the-essence-of-declarative-programming&quot; aria-label=&quot;the essence of declarative programming permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I previously wrote about &lt;a href=&quot;/2025/09/07/declarative-programming-misconceptions-and-essence/en&quot;&gt;the essence of declarative programming&lt;/a&gt;. Using array methods like &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt; doesn’t automatically make your code declarative. True declarative thinking focuses on “What” instead of “How”, on relationships, not procedures.&lt;/p&gt;
&lt;p&gt;But most React developers still haven’t escaped the procedural mindset of a decade ago when it comes to handling elements like modals and toasts.&lt;/p&gt;
&lt;p&gt;We still use &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt; to create state, wire up event handlers, and manage the sequence of state changes. This is procedural thinking: focusing on temporal order. “First open the dialog, then wait for confirmation, and finally call the API.”&lt;/p&gt;
&lt;p&gt;Just as you can think procedurally while using &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, using &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt; doesn’t make your code declarative.&lt;/p&gt;
&lt;h3 id=&quot;state-space-and-cognitive-load&quot; style=&quot;position:relative;&quot;&gt;State space and cognitive load&lt;a href=&quot;#state-space-and-cognitive-load&quot; aria-label=&quot;state space and cognitive load permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Remember the async data state example from the previous post? Managing &lt;code class=&quot;language-text&quot;&gt;loading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt; as independent boolean states creates logically impossible state combinations. The exact same problem occurs in overlay management.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsOpen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isLoading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsLoading&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setResult&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;confirmed&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Logically impossible state combinations&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// { isOpen: false, isLoading: true, result: null }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// → Closed but loading&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// { isOpen: false, isLoading: false, result: &apos;confirmed&apos; }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// → Closed but has a result&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// { isOpen: true, isLoading: true, result: &apos;confirmed&apos; }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// → Loading but already has a result&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Three independent state variables theoretically produce &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2³ = 8&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; combinations, but the number of logically valid combinations is far fewer. Every time developers write code, they must mentally verify: “Is this combination possible?”&lt;/p&gt;
&lt;p&gt;The fundamental reason this is problematic is the increase in cognitive load. According to psychologist John Sweller’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Cognitive_load&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;cognitive load theory&lt;/a&gt;, human working memory is limited, with a finite amount of information it can process simultaneously. George Miller’s “magic number 7±2” comes from the same line of thinking.&lt;/p&gt;
&lt;p&gt;So the problem with the overlay management pattern above is that you must track &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt;, &lt;em&gt;and&lt;/em&gt; the valid combinations between them just to understand how the overlay behaves. Right now it’s only 8 possible combinations, but as more states are added, the amount of information a developer must remember grows exponentially.&lt;/p&gt;
&lt;p&gt;But this situation isn’t inherent complexity of the problem itself. It’s extraneous cognitive load created by the way we’ve chosen to express it. Just as a complex mathematical expression becomes easier to understand when rewritten with better notation, a small shift in approach can let us express overlays in a much simpler way.&lt;/p&gt;
&lt;h3 id=&quot;the-relationship-between-input-and-output&quot; style=&quot;position:relative;&quot;&gt;The relationship between input and output&lt;a href=&quot;#the-relationship-between-input-and-output&quot; aria-label=&quot;the relationship between input and output permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The key point I emphasized in my previous post was that declarative code expresses relationships, not the flow of time.&lt;/p&gt;
&lt;p&gt;Recall the linear function &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y = 2x + 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. This isn’t an instruction to “multiply &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; by 2 and add 1” — it declares the relationship between &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. This relationship is a timeless truth. Whenever &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is 3, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is 7 — always, everywhere.&lt;/p&gt;
&lt;p&gt;The essence of overlays is the same. Look at the browser’s native API, &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;confirm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Are you sure you want to delete this?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt; has the side effect of displaying UI, so it’s not a pure function. But the important thing is that this function doesn’t expose state management to the caller. There’s no &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt; state, no &lt;code class=&quot;language-text&quot;&gt;handleConfirm&lt;/code&gt; handler. How it’s implemented internally, what order things render in, all of that is hidden behind the abstraction. The developer can focus solely on the relationship: “what goes in, what comes out.”&lt;/p&gt;
&lt;p&gt;In mathematics, a function represents a correspondence between sets. When we write &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f:A→B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, we declare how each element of set &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; corresponds to an element of set &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. This isn’t about computation — it’s about the relationship between structures.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt; works the same way. It represents a correspondence from the set of message strings to the set of &lt;code class=&quot;language-text&quot;&gt;boolean&lt;/code&gt; values.&lt;/p&gt;
&lt;h2 id=&quot;the-declarative-overlay-pattern&quot; style=&quot;position:relative;&quot;&gt;The declarative overlay pattern&lt;a href=&quot;#the-declarative-overlay-pattern&quot; aria-label=&quot;the declarative overlay pattern permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what should we do? The answer is surprisingly simple: don’t treat overlays as state — treat them as functions.&lt;/p&gt;
&lt;p&gt;The declarative overlay pattern brings the functional essence that &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt; demonstrated into the React ecosystem.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ConfirmDialog&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;onConfirm&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;onCancel&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt; is a function that returns a &lt;code class=&quot;language-text&quot;&gt;Promise&amp;lt;T&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you’ve used Promises, you already know this pattern. Call an API, get a Promise back, await the result. &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt; works identically. Open an overlay, get a Promise back, wait for the user to respond. The only difference is that the response comes from a user instead of an API server.&lt;/p&gt;
&lt;p&gt;In other words, it declares the relationship: “show an overlay and receive the user’s response.”&lt;/p&gt;
&lt;p&gt;In this section, I want to examine three aspects of why the declarative overlay pattern is better than traditional state management.&lt;/p&gt;
&lt;h3 id=&quot;from-state-to-relationships&quot; style=&quot;position:relative;&quot;&gt;From state to relationships&lt;a href=&quot;#from-state-to-relationships&quot; aria-label=&quot;from state to relationships permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the previous post, I covered how to prevent impossible state combinations — explicitly enumerating possible states and letting the type system block invalid combinations.&lt;/p&gt;
&lt;p&gt;But the declarative overlay pattern takes a different approach. Instead of constraining state combinations, it abstracts away the state itself.&lt;/p&gt;
&lt;p&gt;Traditional state management deals with snapshots: “Is the dialog open right now?”, “Is it loading right now?”, “Is there a result right now?” It tracks the state at the current point in time and changes these states one by one to produce the desired behavior. It’s like creating animation by stitching together individual photographs.&lt;/p&gt;
&lt;p&gt;But think about it. What we actually want to know is whether the user clicked “confirm” in the dialog, not whether the dialog is currently open or closed.&lt;/p&gt;
&lt;p&gt;The intermediate states are just means to an end. We don’t care about the current state — we want the final result.&lt;/p&gt;
&lt;p&gt;The declarative overlay pattern eliminates this intermediate process. What used to require managing multiple complex states is expressed as a single action, opening an overlay, and the focus is solely on receiving the result.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Open the dialog&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Somewhere later, close the dialog and set the result&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;confirmed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Express only the relationship between action and result&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Why is this better?&lt;/p&gt;
&lt;p&gt;First, the code directly expresses intent. The intention “I want to get user confirmation” is right there in the code. There’s no need for a developer to mentally combine three state variables and deduce “ah, this is trying to get confirmation.”&lt;/p&gt;
&lt;p&gt;Second, there’s less room for errors. The first approach has plenty of openings for human error — forgetting to set &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt; back to &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;, setting &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt; without closing the dialog, and so on. Abstracting these operations into a function makes such mistakes structurally impossible.&lt;/p&gt;
&lt;p&gt;Third, you can focus on the result of a change rather than the process of change. It expresses &lt;em&gt;what happens&lt;/em&gt;, not &lt;em&gt;how state changes&lt;/em&gt;. In other words, it’s declarative.&lt;/p&gt;
&lt;p&gt;Put another way, the declarative overlay pattern replaces tracking what values individual state variables hold (state snapshots) with expressing what result comes from what action (input-output relationships).&lt;/p&gt;
&lt;h3 id=&quot;redistribution-of-cognitive-load&quot; style=&quot;position:relative;&quot;&gt;Redistribution of cognitive load&lt;a href=&quot;#redistribution-of-cognitive-load&quot; aria-label=&quot;redistribution of cognitive load permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Code readability is often considered a matter of subjective taste. But psychologist John Sweller’s cognitive load theory shows that it’s not just taste. It’s a matter of cognitive science.&lt;/p&gt;
&lt;p&gt;Look at the traditional state management approach again. Developers must simultaneously track multiple state variables like &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt;. To understand how the module behaves, they must mentally simulate what order these variables change in and which combinations are valid.&lt;/p&gt;
&lt;p&gt;In cognitive load theory, this is called extraneous load. Extraneous load in code isn’t the inherent complexity of the problem — it’s unnecessary complexity created by the way we’ve chosen to express it. The essential problem of showing an overlay and getting user confirmation is simple, but expressing this through multiple state variables artificially inflates the complexity.&lt;/p&gt;
&lt;p&gt;Recall George Miller’s “magic number 7±2.” Humans can only hold about 7 items in working memory at once. But with just three state variables, the possible combinations already reach 8, and tracking which of those are valid pushes us to our cognitive limits.&lt;/p&gt;
&lt;p&gt;The declarative overlay pattern removes this extraneous load. Developers no longer need to remember combinations across multiple state variables. They only need to remember one function call and the relationship between input and output.&lt;/p&gt;
&lt;p&gt;I believe that expressing the same problem with less cognitive load — removing unnecessary complexity so developers can focus on the essential problem — is the essence of writing readable code.&lt;/p&gt;
&lt;p&gt;But there’s something important not to misunderstand: the complexity hasn’t disappeared — it’s merely been redistributed.&lt;/p&gt;
&lt;p&gt;The implementers of the overlay-kit library still have to deal with complex logic like Promise management and state synchronization. But this tedious implementation only needs to be done once.&lt;/p&gt;
&lt;p&gt;Through the contributions of a few, countless developers can work with overlays at low cognitive load. This is the value that abstraction gives us.&lt;/p&gt;
&lt;h3 id=&quot;composition-and-control-flow&quot; style=&quot;position:relative;&quot;&gt;Composition and control flow&lt;a href=&quot;#composition-and-control-flow&quot; aria-label=&quot;composition and control flow permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider a situation where you need to collect user input through multiple overlays. With the traditional approach, the logic looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateUserFlow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;step&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setStep&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setInfo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;preference&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setPreference&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleInfoSubmit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setStep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handlePreferenceSubmit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setPreference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setStep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleConfirm&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;preference &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setStep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setPreference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;step &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserInfoForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleInfoSubmit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;step &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PreferenceForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handlePreferenceSubmit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;step &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ConfirmDialog&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onConfirm&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleConfirm&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a simple flow that collects user info, preferences, and a final confirmation before calling an API. But the information flow is scattered throughout the code. Developers must follow how &lt;code class=&quot;language-text&quot;&gt;step&lt;/code&gt; state changes, what each handler does, and what conditions control the JSX rendering — all just to understand the overall flow.&lt;/p&gt;
&lt;p&gt;Now look at the same logic implemented with overlay-kit’s &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserInfoForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; preference &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PreferenceForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmCreation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; preference&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;preference &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The biggest difference is that the information flow is linear. The first line collects user info, the second line collects preferences, and the third line gets confirmation before calling the API. The order you read the code from top to bottom &lt;em&gt;is&lt;/em&gt; the execution order.&lt;/p&gt;
&lt;p&gt;This is possible because &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt; returns a Promise. Promises let you wait for an asynchronous operation to complete. Wait for the first overlay to close, then open the second. When the second closes, move to the third. Each step executes sequentially, and information flows from top to bottom.&lt;/p&gt;
&lt;p&gt;Each step is also independent, meaning the concerns have low coupling and high cohesion. The user info form only collects user info, the preference form only collects preferences, and how to stitch them together is decided by the &lt;code class=&quot;language-text&quot;&gt;createUser&lt;/code&gt; function. Each component simply calls &lt;code class=&quot;language-text&quot;&gt;close&lt;/code&gt; and doesn’t need to know where the result goes.&lt;/p&gt;
&lt;p&gt;And since &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt; is just a function that returns a value, it integrates naturally with standard control flow. Need conditional logic? Use &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt;. Need error handling? Use &lt;code class=&quot;language-text&quot;&gt;try/catch&lt;/code&gt;. Need iteration? Use &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt;. The control flow you learned in Programming 101 works as-is. No special overlay patterns to learn.&lt;/p&gt;
&lt;p&gt;Thanks to these function characteristics, reusing specific UX flows is also straightforward:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ConfirmDialog&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;onConfirm&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;onCancel&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Are you sure you want to delete this?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Reset your settings?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resetSettings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is the power of treating overlays as functions. Information flow is linear, standard control flow like &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;try/catch&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; just works, and reuse is as simple as extracting a function.&lt;/p&gt;
&lt;h2 id=&quot;extending-declarative-thinking&quot; style=&quot;position:relative;&quot;&gt;Extending declarative thinking&lt;a href=&quot;#extending-declarative-thinking&quot; aria-label=&quot;extending declarative thinking permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 2013, React freed us from direct DOM manipulation and introduced a world where we could declaratively express the structural relationship between data and UI through JSX.&lt;/p&gt;
&lt;p&gt;But sadly, within the same React codebase, we write components declaratively while handling overlays procedurally.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Components: declarative&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserProfile&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Overlays: procedural&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsOpen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleOpen&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleClose&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Why did this split happen? Because overlays &lt;em&gt;appear&lt;/em&gt; to be bound to time. A user clicks a button, a dialog opens, then the user clicks confirm, an API is called, and the response arrives, the dialog closes. So we thought we needed state to manage this sequence.&lt;/p&gt;
&lt;p&gt;But look at &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt; again:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;confirm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Are you sure you want to delete this?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;deleteItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, the effect this code produces also involves temporal ordering — waiting for the user to click confirm in the dialog. But we don’t express this as a flow of time in the code. We express it as a function that takes a string and returns a boolean — a relationship between a string and a boolean.&lt;/p&gt;
&lt;p&gt;This is exactly what the declarative overlay pattern does. It transforms temporal sequences into relationships between conditions and results.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Procedural: &quot;first open, wait, close, then...&quot;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ... somewhere else&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ... and then&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;deleteItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Declarative: &quot;if confirmed, delete&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;deleteItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can extend React’s declarative philosophy to overlays. Just as components declare the relationship between data and UI, overlays declare the relationship between user responses and the next action.&lt;/p&gt;
&lt;p&gt;And this consistency matters. If you think declaratively when reading components but must switch to procedural thinking for overlays, you’re constantly context-switching. But with the declarative overlay pattern, the entire codebase is unified under a single way of thinking.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://overlay-kit.slash.page/en&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;overlay-kit&lt;/a&gt; is a library that implements this pattern.&lt;/p&gt;
&lt;p&gt;Its value isn’t in reducing lines of code. It’s in bringing the simplicity that &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt; demonstrated into the React ecosystem. It simply makes something that was easy 10 years ago but got complicated along the way easy again.&lt;/p&gt;
&lt;p&gt;In my previous post, I said declarative programming is a way of thinking, not a tool. Just as using &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt; doesn’t make code declarative, using &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt; doesn’t make it procedural either. What matters is what you’re expressing.&lt;/p&gt;
&lt;p&gt;The declarative overlay pattern discussed in this post is the same. What matters isn’t the &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt; API — it’s “do you see overlays as state, or as relationships?”&lt;/p&gt;
&lt;p&gt;See them as state, and you must track variables like &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt;. See them as relationships, and you only need to think about input and output. Expressing the same problem differently is enough to change the cognitive load.&lt;/p&gt;
&lt;p&gt;Removing unnecessary complexity so developers can focus on the essential problem is what good abstraction does.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[상태에서 관계로: 선언적 오버레이 패턴(Declarative Overlay Pattern)]]></title><description><![CDATA[…]]></description><link>https://evan-moon.github.io/2025/10/07/declarative-overlay-pattern-with-overlay-kit/</link><guid isPermaLink="false">20251007-declarative-overlay-pattern-with-overlay-kit</guid><pubDate>Tue, 07 Oct 2025 02:10:27 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 지난 포스팅에 이어 선언적 프로그래밍이 현실에 어떤 형태로 구현되는지에 대해서 조금 더 자세한 이야기를 해보려고 한다.&lt;/p&gt;
&lt;p&gt;그냥 이론적인 설명만 하면 너무 재미가 없으니 리액트에서 오버레이 요소들을 쉽게 다룰 수 있도록 도와주는 &lt;a href=&quot;https://overlay-kit.slash.page/ko&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;overlay-kit&lt;/a&gt;이라는 라이브러리를 통해 선언적 프로그래밍에 대해 조금 더 자세히 알아보겠다.&lt;/p&gt;
&lt;!--more --&gt;
&lt;h2 id=&quot;선언적-프로그래밍의-본질&quot; style=&quot;position:relative;&quot;&gt;선언적 프로그래밍의 본질&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98-%EB%B3%B8%EC%A7%88&quot; aria-label=&quot;선언적 프로그래밍의 본질 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자는 이전에 &lt;a href=&quot;/2025/09/07/declarative-programming-misconceptions-and-essence/&quot;&gt;선언적 프로그래밍의 본질&lt;/a&gt;에 대해 이야기한 바 있다. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt; 같은 배열 메소드를 쓴다고 해서 무조건 선언적인 것이 아니며, 진정한 선언적 사고는 “어떻게(How)“가 아닌 “무엇을(What)”, 절차가 아닌 관계에 집중하는 것이라고 말했다.&lt;/p&gt;
&lt;p&gt;하지만 React를 사용하는 대부분의 개발자들은 여전히 모달이나 토스트와 같은 요소를 다룰 때 만큼은 10년 전의 절차적 사고에서 벗어나지 못하고 있다.&lt;/p&gt;
&lt;p&gt;우리는 여전히 &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt;를 사용해 상태를 만들고, 이벤트 핸들러를 연결하고, 상태 변화의 순서를 관리한다. 이것은 “먼저 다이얼로그를 열고, 그 다음 확인을 기다리고, 마지막에 API를 호출한다”는 시간적 순서에 집중하는 절차적 사고라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;마치 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;을 사용하면서도 절차적으로 사고할 수 있는 것처럼, &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt;를 사용한다고 해서 선언적인 코드가 되는 것은 아니다.&lt;/p&gt;
&lt;h3 id=&quot;상태-공간과-인지적-부하&quot; style=&quot;position:relative;&quot;&gt;상태 공간과 인지적 부하&lt;a href=&quot;#%EC%83%81%ED%83%9C-%EA%B3%B5%EA%B0%84%EA%B3%BC-%EC%9D%B8%EC%A7%80%EC%A0%81-%EB%B6%80%ED%95%98&quot; aria-label=&quot;상태 공간과 인지적 부하 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이전 글에서 다뤘던 비동기 데이터 상태를 기억하는가? &lt;code class=&quot;language-text&quot;&gt;loading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;를 독립적인 boolean 상태로 관리하면 논리적으로 불가능한 상태 조합이 발생한다는 이야기였다. 오버레이 관리에서도 똑같은 문제가 발생한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsOpen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isLoading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsLoading&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setResult&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;confirmed&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 논리적으로 불가능한 상태 조합들&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// { isOpen: false, isLoading: true, result: null }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// → 닫혀있는데 로딩 중&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// { isOpen: false, isLoading: false, result: &apos;confirmed&apos; }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// → 닫혀있는데 결과가 있음&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// { isOpen: true, isLoading: true, result: &apos;confirmed&apos; }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// → 로딩 중인데 이미 결과가 있음&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;세 개의 독립적인 상태 변수는 이론적으로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2³ = 8&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가지 조합을 만들지만, 실제로 논리적으로 유효한 조합은 그보다 훨씬 적다. 개발자는 코드를 작성할 때마다 “이 조합이 가능한가?”를 머릿속으로 검증해야 한다.&lt;/p&gt;
&lt;p&gt;이러한 상황이 문제가 되는 근본적인 이유는 바로 인지적 부하의 증가다. 심리학자 존 스웰러(John Sweller)의 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%A7%80_%EB%B6%80%ED%95%98&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;인지 부하 이론&lt;/a&gt;에 따르면, 인간의 작업 기억은 제한적이며, 동시에 처리할 수 있는 정보의 양에는 한계가 있다고 한다. 조지 밀러(George Miller)가 제시한 “매직 넘버 7±2”도 이와 동일한 맥락에서 나온 이야기이다.&lt;/p&gt;
&lt;p&gt;그래서 위 예시의 오버레이 관리 패턴을 보면 &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt;, 그리고 이들 사이의 유효한 조합까지 추적해야만 오버레이의 동작을 유추할 수 있다는 점이 문제인 것이다. 그나마 지금은 8가지 경우의 수 밖에 되지 않지만, 필요한 상태가 늘어날 수록 개발자가 기억해야할 정보의 양도 기하급수적으로 늘어날 것이다.&lt;/p&gt;
&lt;p&gt;하지만 이 상황은 문제 자체의 복잡도가 아니라, 표현 방식이 만들어낸 외재적 인지 부하이기 때문에 충분히 해결해볼 수 있는 문제이다. 수학에서 복잡한 식을 적절한 표기법으로 바꾸면 이해가 쉬워지는 것처럼, 약간의 접근 방법만 바꾸면 오버레이도 더 간단한 방식으로 표현할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;입력과-출력의-관계&quot; style=&quot;position:relative;&quot;&gt;입력과 출력의 관계&lt;a href=&quot;#%EC%9E%85%EB%A0%A5%EA%B3%BC-%EC%B6%9C%EB%A0%A5%EC%9D%98-%EA%B4%80%EA%B3%84&quot; aria-label=&quot;입력과 출력의 관계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 이전 글에서 강조했던 핵심은 선언적 코드는 시간의 흐름이 아닌 관계를 표현한다는 것이었다.&lt;/p&gt;
&lt;p&gt;한번 일차 함수를 나타내는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y = 2x + 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;을 떠올려보자. 이것은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 2를 곱하고 1을 더하라는 계산 절차를 의미하는 것이 아니라 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 사이의 관계를 선언하는 것이다. 이 관계는 시간과 무관한 영원한 진리다. 언제 어디서나 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 3이라면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 7이기 때문이다.&lt;/p&gt;
&lt;p&gt;오버레이의 본질도 마찬가지다. 브라우저 네이티브 API인 &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;을 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;confirm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;정말 삭제하시겠습니까?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;은 UI를 띄우는 부수 효과를 가지므로 순수 함수는 아니다. 하지만 중요한 것은 이 함수가 상태 관리를 호출자에게 노출하지 않는다는 점이다. &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt; 같은 상태도, &lt;code class=&quot;language-text&quot;&gt;handleConfirm&lt;/code&gt; 같은 핸들러도 필요하지 않다. 내부적으로 어떻게 구현했는지, 어떤 순서로 렌더링하는지는 추상화 뒤로 숨겨져 있다. 개발자는 오직 “무엇을 넣으면 무엇이 나오는가”라는 관계에만 집중할 수 있다.&lt;/p&gt;
&lt;p&gt;수학에서 함수는 집합 간의 대응 관계를 나타낸다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f:A→B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라고 쓸 때, 우리는 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 각 원소가 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 원소와 어떻게 대응되는지를 선언한다. 이것은 계산 과정이 아니라 구조 간의 관계다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;도 마찬가지다. 메시지 문자열이라는 집합에서 &lt;code class=&quot;language-text&quot;&gt;boolean&lt;/code&gt; 값이라는 집합으로의 대응 관계를 나타낸다.&lt;/p&gt;
&lt;h2 id=&quot;선언적-오버레이-패턴declarative-overlay-pattern&quot; style=&quot;position:relative;&quot;&gt;선언적 오버레이 패턴(Declarative Overlay Pattern)&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81-%EC%98%A4%EB%B2%84%EB%A0%88%EC%9D%B4-%ED%8C%A8%ED%84%B4declarative-overlay-pattern&quot; aria-label=&quot;선언적 오버레이 패턴declarative overlay pattern permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;그렇다면 어떻게 해야 할까? 답은 의외로 간단하다. 오버레이를 상태로 다루지 말고 함수로 다루면 된다.&lt;/p&gt;
&lt;p&gt;선언적 오버레이 패턴은 &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;이 보여준 함수적 본질을 React 생태계로 가져온다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ConfirmDialog&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;onConfirm&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;onCancel&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;Promise&amp;lt;T&gt;&lt;/code&gt;를 반환하는 함수다.&lt;/p&gt;
&lt;p&gt;Promise를 써본 개발자라면 이미 이 패턴을 알고 있다. API를 호출하면 Promise가 반환되고, await로 결과를 기다린다. &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;도 동일하다. 오버레이를 열면 Promise가 반환되고, 사용자가 응답할 때까지 기다린다. 다만 API 서버 대신 사용자에게서 응답을 받을 뿐이다.&lt;/p&gt;
&lt;p&gt;즉, “오버레이를 보여주고 사용자 응답을 받는다”는 관계를 선언하는 것이다.&lt;/p&gt;
&lt;p&gt;이번 섹션에서는 선언적 오버레이 패턴이 왜 전통적인 상태 관리보다 나은지 세 가지 측면에서 살펴보려고 한다.&lt;/p&gt;
&lt;h3 id=&quot;상태에서-관계로&quot; style=&quot;position:relative;&quot;&gt;상태에서 관계로&lt;a href=&quot;#%EC%83%81%ED%83%9C%EC%97%90%EC%84%9C-%EA%B4%80%EA%B3%84%EB%A1%9C&quot; aria-label=&quot;상태에서 관계로 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이전 글에서 불가능한 상태 조합을 막는 방법을 다뤘다. 가능한 상태들을 명시적으로 열거하고, 타입 시스템이 불가능한 조합을 차단하도록 하는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 선언적 오버레이 패턴은 다른 접근을 취한다. 상태 조합을 제한하는 대신, 상태 자체를 추상화한다.&lt;/p&gt;
&lt;p&gt;전통적인 상태 관리는 스냅샷을 다룬다. “지금 다이얼로그가 열려있는가?”, “지금 로딩 중인가?”, “지금 결과가 있는가?” 같은 현재 시점의 상태를 추적한다. 그리고 이 상태들을 하나씩 바꿔나가며 원하는 동작을 만든다. 이는 마치 사진 여러 장을 이어붙여 애니메이션을 만드는 것과 비슷하다.&lt;/p&gt;
&lt;p&gt;하지만 잘 생각해보면 우리는 사용자가 다이얼로그에서 확인을 눌렀는지 아닌지를 알고 싶은 것이지 다이얼로그가 현재 열려있는지 닫혀있는지를 알고 싶은게 아니다.&lt;/p&gt;
&lt;p&gt;즉, 중간 과정의 상태들은 사실 그 결과를 얻기 위한 수단일 뿐, 현재 상태가 아니라 최종 결과를 알고 싶은 것이다.&lt;/p&gt;
&lt;p&gt;선언적 오버레이 패턴은 이 중간 과정을 제거한다. 기존에는 복잡하게 다루었던 여러 상태들을 오버레이를 연다는 하나의 동작으로 표현하고, 그 결과를 받는 것에만 집중한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 다이얼로그를 열고&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 나중에 어딘가에서 다이얼로그를 닫으며 결과를 입력한다.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;confirmed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 동작과 결과와의 관계만 표현해서 깔끔해졌다&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;왜 이것이 더 나을까?&lt;/p&gt;
&lt;p&gt;첫째, 코드가 의도를 직접 표현한다. “사용자 확인을 받고 싶다”는 의도가 코드에 그대로 드러난다. 개발자가 머릿속으로 상태 변수 세 개를 조합해서 “아, 이게 확인을 받으려는 동작이구만”이라고 유추할 필요가 없다.&lt;/p&gt;
&lt;p&gt;둘째, 에러를 만들 여지가 줄어든다. 첫 번째 방법은 isOpen을 true로 바꿨는데 나중에 false로 바꾸는 걸 깜빡한다거나, &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt;를 설정했는데 다이얼로그를 닫지 않는다거나 하는 휴먼 에러의 구멍이 많다. 이러한 동작들을 추상화해서 함수로 표현하면 이런 실수들이 구조적으로 불가능해진다.&lt;/p&gt;
&lt;p&gt;셋째, 변화의 과정이 아니라 변화의 결과에 집중할 수 있다. 상태가 어떻게 바뀌는지가 아니라 무엇이 일어나는지를 표현한다. 즉, 선언적이다.&lt;/p&gt;
&lt;p&gt;다시 말해, 선언적 오버레이 패턴은 개별 상태 변수들이 어떤 값을 가지고 있는지(상태의 스냅샷)를 다루는 대신, 어떤 동작을 하면 어떤 결과가 나오는지(입출력의 관계)를 다루는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;인지적-부하의-재분배&quot; style=&quot;position:relative;&quot;&gt;인지적 부하의 재분배&lt;a href=&quot;#%EC%9D%B8%EC%A7%80%EC%A0%81-%EB%B6%80%ED%95%98%EC%9D%98-%EC%9E%AC%EB%B6%84%EB%B0%B0&quot; aria-label=&quot;인지적 부하의 재분배 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;코드의 가독성은 종종 주관적인 취향의 문제로 여겨진다. 하지만 심리학자 존 스웰러(John Sweller)의 인지 부하 이론은 이것이 단순한 취향이 아니라 인지 과학의 문제임을 보여준다.&lt;/p&gt;
&lt;p&gt;전통적인 상태 관리 방식을 다시 보자. 개발자는 &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt; 같은 여러 상태 변수를 동시에 추적해야 한다. 개발자가 모듈의 동작을 이해하기 위해 이 변수들이 어떤 순서로 바뀌는지, 어떤 조합이 유효한지를 머릿속으로 시뮬레이션해야 한다는 의미이다.&lt;/p&gt;
&lt;p&gt;이것을 인지 부하 이론에서는 외재적 부하(Extraneous Load)라고 부른다. 코드에서 발생하는 외재적 부하는 문제 자체의 복잡도가 아니라 표현 방식이 만들어낸 불필요한 복잡도라고 볼 수 있다. 오버레이를 띄워 사용자 확인을 받는다는 본질적인 문제는 단순하지만, 이 행위를 여러 개의 상태 변수로 표현하면서 복잡도가 인위적으로 증가한 것이다.&lt;/p&gt;
&lt;p&gt;조지 밀러(George Miller)가 제시한 “매직 넘버 7±2”를 떠올려보자. 인간은 동시에 약 7개 정도의 정보만 작업 기억에 유지할 수 있다. 하지만 상태 변수가 세 개만 되어도 가능한 조합은 8가지가 되고, 이 중 유효한 조합이 무엇인지까지 추적하면 이미 인지적 한계에 다다른다.&lt;/p&gt;
&lt;p&gt;선언적 오버레이 패턴은 이 외재적 부하를 제거한다. 개발자는 더 이상 여러 개의 상태 변수 간의 조합을 기억할 필요가 없고, 하나의 함수 호출, 즉 오직 입력과 출력의 관계만 기억하면 되기 때문에 부하가 줄어든다.&lt;/p&gt;
&lt;p&gt;필자는 이렇게 같은 문제를 더 적은 인지 부하로 표현하는 것, 개발자가 본질적인 문제에 집중할 수 있도록 불필요한 복잡도를 제거하는 것이 가독성 높은 코드를 만드는 본질이라고 생각한다.&lt;/p&gt;
&lt;p&gt;하지만 오해하지 말아야 할 점이 있다. 복잡도가 사라진 것이 아니라 그저 재분배되었을 뿐이다.&lt;/p&gt;
&lt;p&gt;overlay-kit 라이브러리 구현자는 여전히 Promise 관리, 상태 동기화와 같은 복잡한 로직을 다뤄야 하지만, 이런 짜치는 구현은 한 번만 하면 된다.&lt;/p&gt;
&lt;p&gt;소수의 기여를 통해 수많은 개발자들이 낮은 인지 부하로 오버레이라는 동작을 다룰 수 있는 것, 이것이 추상화가 우리에게 선물해주는 가치이다.&lt;/p&gt;
&lt;h3 id=&quot;조합과-제어-흐름&quot; style=&quot;position:relative;&quot;&gt;조합과 제어 흐름&lt;a href=&quot;#%EC%A1%B0%ED%95%A9%EA%B3%BC-%EC%A0%9C%EC%96%B4-%ED%9D%90%EB%A6%84&quot; aria-label=&quot;조합과 제어 흐름 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;여러 오버레이를 통해 사용자 입력을 받아야 하는 상황을 생각해보자. 전통적인 방법에서는 아래와 같은 코드로 해당 로직을 구현하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateUserFlow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;step&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setStep&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setInfo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;preference&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setPreference&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleInfoSubmit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setStep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handlePreferenceSubmit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setPreference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setStep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleConfirm&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;preference &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setStep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setPreference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;step &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserInfoForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleInfoSubmit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;step &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PreferenceForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handlePreferenceSubmit&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;step &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ConfirmDialog&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onConfirm&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleConfirm&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드는 사용자 정보, 선호도, 최종 확인을 받은 후 API를 호출하는 간단한 플로우다. 하지만 정보의 흐름이 코드 곳곳에 흩어져 있기 때문에 개발자는 &lt;code class=&quot;language-text&quot;&gt;step&lt;/code&gt; 상태가 어떻게 바뀌는지, 각 핸들러가 무엇을 하는지, JSX에서 어떤 조건으로 렌더링되는지를 모두 따라가야 전체 흐름을 이해할 수 있다.&lt;/p&gt;
&lt;p&gt;이제 같은 로직을 overlay-kit의 &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;로 구현한 모습을 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserInfoForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; preference &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PreferenceForm&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmCreation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; preference&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;preference &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;가장 큰 차이점은 정보의 흐름이 선형적이라는 점이다. 첫 번째 줄에서 사용자 정보를 입력받고, 두 번째 줄에서 선호도를 입력받고, 세 번째 줄에서 확인을 거쳐 API를 호출한다. 코드를 위에서 아래로 읽는 순서가 곧 실행 순서다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;가 Promise를 반환하기 때문에 이것이 가능하다. Promise는 비동기 작업의 완료를 기다릴 수 있게 해준다. 첫 번째 오버레이가 닫힐 때까지 기다렸다가 두 번째 오버레이를 연다. 두 번째가 닫히면 세 번째로 넘어간다. 각 단계가 순차적으로 실행되면서 정보가 위에서 아래로 흐른다.&lt;/p&gt;
&lt;p&gt;또한 각 단계는 독립적이기 때문에 각 관심사의 결합도가 낮고 응집도가 높다. 사용자 정보를 받는 폼은 사용자 정보만 받고 선호도를 받는 폼은 선호도만 받으며, 최종적으로 이들을 어떻게 이어붙일지는 &lt;code class=&quot;language-text&quot;&gt;createUser&lt;/code&gt; 함수가 결정한다. 각 컴포넌트는 그저 &lt;code class=&quot;language-text&quot;&gt;close&lt;/code&gt; 함수를 호출할 뿐이고, 이 결과가 어디로 가는지는 알 필요가 없다.&lt;/p&gt;
&lt;p&gt;게다가 &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;는 그저 값을 반환하는 함수이기에 일반적인 제어 흐름에 자연스럽게 통합된다. 조건부 로직이 필요하면 &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; 문을 쓰면 되고, 에러 처리가 필요하면 &lt;code class=&quot;language-text&quot;&gt;try/catch&lt;/code&gt;를 쓰면 되며, 반복이 필요하면 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 쓰면 된다. 프로그래밍 101에서 배우는 제어 흐름이 그대로 작동하며, 오버레이를 위한 특별한 패턴을 배울 필요가 없다.&lt;/p&gt;
&lt;p&gt;이러한 함수의 특성 덕에 특정 UX 흐름에 대한 재사용도 간단한 편이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ConfirmDialog&lt;/span&gt;&lt;/span&gt; 
      &lt;span class=&quot;token attr-name&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;isOpen&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; 
      &lt;span class=&quot;token attr-name&quot;&gt;onConfirm&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;onCancel&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;정말 삭제하시겠습니까?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;confirmAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;설정을 초기화하시겠습니까?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resetSettings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것이 오버레이를 함수로 다루는 힘이다. 정보의 흐름을 선형적으로 표현할 수 있고, &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;try/catch&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 같은 일반적인 제어 흐름에 자연스럽게 통합되며, 재사용은 별도 함수로 빼는 것만으로 충분하다.&lt;/p&gt;
&lt;h2 id=&quot;선언적-사고의-확장&quot; style=&quot;position:relative;&quot;&gt;선언적 사고의 확장&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81-%EC%82%AC%EA%B3%A0%EC%9D%98-%ED%99%95%EC%9E%A5&quot; aria-label=&quot;선언적 사고의 확장 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;2013년, 우리는 React를 통해 직접적인 DOM 조작에서 벗어나 JSX로 데이터와 UI의 구조적 관계를 표현하며 선언적으로 UI를 다루는 세상을 접하게 되었다.&lt;/p&gt;
&lt;p&gt;하지만 슬프게도 우리는 같은 React 코드베이스에서 컴포넌트는 선언적으로 작성하면서 오버레이만큼은 절차적으로 다루고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 컴포넌트는 선언적으로&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserProfile&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 오버레이는 절차적으로&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isOpen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsOpen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleOpen&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleClose&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;왜 이런 분열이 생긴 걸까? 그 이유는 오버레이가 마치 시간에 종속된 것처럼 보이기 때문이다. 사용자가 버튼을 누르면 다이얼로그가 열리고, 그 이후 확인 버튼을 누르면 API를 호출하고, 응답이 오면 다시 다이얼로그를 닫는 것처럼 말이다. 그래서 우리는 상태로 이 순서를 관리해야 한다고 생각했다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;을 다시 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;confirm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;정말 삭제하시겠습니까?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;deleteItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 이 코드가 발생시키는 이펙트에도 사용자가 다이얼로그 내에서 확인을 누르기 까지 기다려야한다는 시간적 순서는 존재한다. 하지만 우리는 이것을 코드 상에서 시간의 흐름으로 표현하지 않으며, 문자열을 인자로 받아 boolean 값을 반환하는 함수, 즉 문자열과 boolean의 관계로만 표현한다.&lt;/p&gt;
&lt;p&gt;선언적 오버레이 패턴이 하는 일이 바로 이것이다. 시간적 순서를 조건과 결과의 관계로 바꾼다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 절차적: &quot;먼저 열고, 기다리고, 닫고, 그 다음...&quot;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ... 어딘가에서&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setIsOpen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ... 그 다음에&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;deleteItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 선언적: &quot;확인받으면 삭제한다&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; overlay&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;deleteItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 우리는 React의 선언적 철학을 오버레이에도 적용할 수 있다. 컴포넌트가 데이터와 UI의 관계를 선언하듯, 오버레이도 사용자 응답과 다음 동작의 관계를 선언한다.&lt;/p&gt;
&lt;p&gt;그리고 이 통일성이 중요하다. 컴포넌트를 읽을 때는 선언적으로 사고하다가, 오버레이를 읽을 때는 절차적으로 사고해야 한다면 인지적 분열이 발생한다. 하지만 선언적 오버레이 패턴을 사용하면 전체 코드베이스가 하나의 사고방식으로 통일된다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://overlay-kit.slash.page/ko&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;overlay-kit&lt;/a&gt;은 이 패턴을 구현한 라이브러리다.&lt;/p&gt;
&lt;p&gt;이 라이브러리의 가치는 코드 줄 수를 줄이는 것이 아니라, &lt;code class=&quot;language-text&quot;&gt;window.confirm&lt;/code&gt;이 보여준 단순함을 React 생태계로 가져오는 것이다. 10년 전에는 간단했지만 복잡해진 무언가를 다시 간단하게 만드는 것 뿐이다.&lt;/p&gt;
&lt;p&gt;필자는 이전 글에서 선언적 프로그래밍이 도구가 아니라 사고방식이라고 말했다. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt;를 쓴다고 선언적인 것이 아니듯, &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt;를 쓴다고 절차적인 것도 아니다. 중요한 것은 무엇을 표현하는가였다.&lt;/p&gt;
&lt;p&gt;이 글에서 다룬 선언적 오버레이 패턴도 마찬가지다. 중요한 것은 &lt;code class=&quot;language-text&quot;&gt;openAsync&lt;/code&gt;라는 API가 아니라 “오버레이를 상태로 볼 것인가, 관계로 볼 것인가”이다.&lt;/p&gt;
&lt;p&gt;상태로 보면 &lt;code class=&quot;language-text&quot;&gt;isOpen&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;result&lt;/code&gt; 같은 변수들을 추적해야 한다. 관계로 보면 입력과 출력만 생각하면 된다. 같은 문제를 다르게 표현하는 것만으로 인지 부하가 달라진다.&lt;/p&gt;
&lt;p&gt;그리고 필자는 이렇게 개발자가 본질적인 문제에 집중할 수 있도록 불필요한 복잡도를 제거하는 것이 좋은 추상화의 본질이라고 생각한다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Misconceptions About Declarative Programming]]></title><description><![CDATA[When conducting technical interviews, I often ask candidates about the reasoning behind their decisions in take-home assignments. A common answer I hear is “because this approach is more declarative.” But when I follow up with “What makes it declarative?” or “What does declarative code actually mean?”, clear answers are surprisingly rare. So in this post, I want to share my thoughts on what it truly means for code to be declarative.]]></description><link>https://evan-moon.github.io/2025/09/07/declarative-programming-misconceptions-and-essence/en/</link><guid isPermaLink="false">20250907-declarative-programming-misconceptions-and-essence-en</guid><pubDate>Sun, 07 Sep 2025 07:16:53 GMT</pubDate><content:encoded>&lt;p&gt;When conducting technical interviews, I often ask candidates about the reasoning behind their decisions in take-home assignments.&lt;/p&gt;
&lt;p&gt;A common answer I hear is “because this approach is more declarative.” But when I follow up with “What makes it declarative?” or “What does declarative code actually mean?”, clear answers are surprisingly rare.&lt;/p&gt;
&lt;p&gt;So in this post, I want to share my thoughts on what it truly means for code to be declarative.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Many developers believe they’re writing declarative code, but they often miss the essence, confusing the use of a specific tool or syntax with being declarative.&lt;/p&gt;
&lt;p&gt;In my view, declarative programming isn’t about tools. It’s a fundamental shift in how you think.&lt;/p&gt;
&lt;h2 id=&quot;the-most-common-misconception-about-declarative-programming&quot; style=&quot;position:relative;&quot;&gt;The most common misconception about declarative programming&lt;a href=&quot;#the-most-common-misconception-about-declarative-programming&quot; aria-label=&quot;the most common misconception about declarative programming permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first trap many developers fall into is the belief that “abstracting procedural behavior into functions makes it declarative.” But using functions doesn’t automatically make your code declarative.&lt;/p&gt;
&lt;p&gt;Let’s start with a simple example. Here’s a procedural way to fetch user information:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUserInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; connection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;connectDB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userRow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;SELECT * FROM users WHERE id = ?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; permissionRows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;SELECT * FROM permissions WHERE user_id = ?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userRow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userRow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userRow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    permissions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; permissionRows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permission_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;displayName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code uses a function, but it focuses on temporal sequencing: “first fetch the user from the DB, then add permissions, and finally format the data.” Using a function doesn’t free you from procedural thinking.&lt;/p&gt;
&lt;p&gt;Declarative code shifts focus away from temporal ordering and toward describing the &lt;em&gt;relationships&lt;/em&gt; between operations.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Declarative approach — focus on data transformation relationships&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getUserInfo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    fetchUserFromDB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    addUserPermissions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    formatUserData
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Or more explicitly&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getUserInfo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;formatUserData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;addUserPermissions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;fetchUserFromDB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code declares the relationship “user ID → formatted user info.” It focuses on the relationships between data transformations, not on execution order.&lt;/p&gt;
&lt;p&gt;The distinction is clear. Procedural code focuses on “How — step by step.” Declarative code focuses on “What — what relationship do we want?”&lt;/p&gt;
&lt;p&gt;This misconception is especially common with array methods. Many people assume that using &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;reduce&lt;/code&gt; automatically makes code declarative.&lt;/p&gt;
&lt;p&gt;But you can absolutely think procedurally while using array methods:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Array methods used with procedural thinking&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; items
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;basePrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; finalPrice&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;finalPrice &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A declarative approach, by contrast, focuses exclusively on describing the business relationships each transformation represents:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Truly declarative approach&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;processItems&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  items
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;applyDiscount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addTax&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatPrice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasValidPrice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;applyDiscount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;basePrice &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;addTax&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;formatPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;finalPrice&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hasValidPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;finalPrice &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first version uses array methods but still focuses on step-by-step processing. The second version clearly declares the business relationship each transformation represents.&lt;/p&gt;
&lt;p&gt;What matters is proper abstraction — each function clearly expressing what it does.&lt;/p&gt;
&lt;p&gt;Functions are neutral tools. You can wrap procedural thinking in a function, or express relational thinking through one. The essence of declarative programming isn’t whether you use functions — it’s what kind of abstraction those functions provide.&lt;/p&gt;
&lt;p&gt;These rough examples might not fully convey the idea, so let’s dig into the fundamentals.&lt;/p&gt;
&lt;h2 id=&quot;declarative-programming-from-a-mathematical-perspective&quot; style=&quot;position:relative;&quot;&gt;Declarative programming from a mathematical perspective&lt;a href=&quot;#declarative-programming-from-a-mathematical-perspective&quot; aria-label=&quot;declarative programming from a mathematical perspective permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To properly understand declarative programming, we first need to understand the concept of “declaration” itself. The easiest way is to start with everyday examples.&lt;/p&gt;
&lt;p&gt;Think about a cooking recipe. The procedural approach is like a recipe: “Boil 2 cups of water, add the noodles and cook for 3 minutes, add the seasoning and cook for 1 more minute, serve in a bowl.” It’s a set of instructions that follow a timeline.&lt;/p&gt;
&lt;p&gt;The declarative approach expresses relationships: “Ramen = cooked noodles + seasoning + hot water.” It describes the essential relationships between ingredients.&lt;/p&gt;
&lt;p&gt;A recipe is a set of instructions ordered by time. A relational declaration describes the essential relationships between components. This difference is the fundamental distinction between procedural and declarative thinking.&lt;/p&gt;
&lt;p&gt;Let’s look at a clearer example from math. Consider the linear function &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x) = 2x + 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; that we all learned in school. This expression is not a command telling a computer to “multiply &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; by 2 and add 1.” It’s a declaration that “this relationship exists between &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.”&lt;/p&gt;
&lt;p&gt;This declaration is a timeless truth because it describes a relationship. Whenever &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is 3, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is 7 — always, everywhere. The computation process or execution order doesn’t matter. What matters is the relationship between &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; itself.&lt;/p&gt;
&lt;p&gt;What mathematicians focus on when defining functions is precisely these invariant relationships. A function isn’t a computation algorithm — it’s a correspondence between structures. When we define the trigonometric function &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;sin&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sin(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, we’re declaring the relationship between an angle and the &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;-coordinate on the unit circle, not prescribing how to calculate it.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ce883bea384b4c39d034555b129d50a2/151cf/image1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdxYEj//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAEFAl//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAYEAADAQEAAAAAAAAAAAAAAAAAEBEBQf/aAAgBAQABPyHqwhF//9oADAMBAAIAAwAAABCzz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABsQAAIDAQEBAAAAAAAAAAAAAAERACExQVGR/9oACAEBAAE/EGSd4Zo0ivZnuxW2fsVdgFT/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;image1&quot; title=&quot;&quot; src=&quot;/static/ce883bea384b4c39d034555b129d50a2/c08c5/image1.jpg&quot; srcset=&quot;/static/ce883bea384b4c39d034555b129d50a2/0913d/image1.jpg 160w,
/static/ce883bea384b4c39d034555b129d50a2/cb69c/image1.jpg 320w,
/static/ce883bea384b4c39d034555b129d50a2/c08c5/image1.jpg 640w,
/static/ce883bea384b4c39d034555b129d50a2/6a068/image1.jpg 960w,
/static/ce883bea384b4c39d034555b129d50a2/151cf/image1.jpg 1181w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Memorizing the trigonometry table means memorizing the relationships that sin, cos, and tan express&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The same applies to programming. Declarative code doesn’t order a computer to do something — it expresses “the essence of this problem lies in these relationships.” From this perspective, programming becomes not about dictating computation steps, but about discovering and expressing the mathematical structure of a problem domain.&lt;/p&gt;
&lt;h2 id=&quot;procedural-vs-declarative-a-difference-in-thinking&quot; style=&quot;position:relative;&quot;&gt;Procedural vs. declarative: a difference in thinking&lt;a href=&quot;#procedural-vs-declarative-a-difference-in-thinking&quot; aria-label=&quot;procedural vs declarative a difference in thinking permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now let’s look at concrete examples that approach the same functionality from both mindsets. Procedural thinking focuses on changes that happen over time: “First do this, then do that…” — a sequential execution model.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Procedural programming — focused on How&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Step 1: Iterate through each item&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Step 2: Validate&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Step 3: Calculate base price&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; itemPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Step 4: Apply discount&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        itemPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; itemPrice &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itemPrice &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Step 5: Accumulate total&lt;/span&gt;
      total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; itemPrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; total&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code focuses on temporal order and state changes. You have to track what happens at each step and how variables mutate.&lt;/p&gt;
&lt;p&gt;Declarative thinking, on the other hand, focuses on timeless logical relationships. It declares: “total price = the sum of discounted prices of valid items.”&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Declarative programming — focused on What&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;calculateTotalPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  items
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasValidQuantity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;calculateItemPrice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hasValidQuantity&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;calculateItemPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code declares data transformation relationships. Each function represents a specific transformation, and their composition solves the whole problem.&lt;/p&gt;
&lt;p&gt;In programming, this difference manifests in the &lt;em&gt;kind&lt;/em&gt; of abstraction the code expresses. Procedural code abstracts over the computer’s execution process — memory allocation, loop execution, conditional branching — wrapping mechanical operations in variables and control structures. Declarative code abstracts over the logical structure of the problem domain — expressing conceptual relationships like business rules, data relationships, and state transformations through functions and types.&lt;/p&gt;
&lt;p&gt;So why does this relational thinking matter? The fundamental reason is human cognitive limitations. According to psychologist George Miller’s research, human short-term memory can only handle about 7±2 units of information simultaneously.&lt;/p&gt;
&lt;p&gt;In procedural thinking, you must track all state changes over time, and as programs grow complex, the combinations of states explode exponentially. With 10 variables, there are &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1024&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^{10} = 1024&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; possible states, and at each step you need to consider all of them. Tracking all these changes is nearly impossible for human memory.&lt;/p&gt;
&lt;p&gt;With relational thinking, you manage complexity through composition of invariant relationships. It’s the same principle as expressing a complex function as a composition of simpler ones in math. In &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;h(x) = f(g(x))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, you don’t need to know the internals of both &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to understand &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;h&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; — you only need to understand each one’s input-output relationship.&lt;/p&gt;
&lt;p&gt;This relational thinking lets us chunk complex states into manageable pieces, greatly helping us understand complex code.&lt;/p&gt;
&lt;h2 id=&quot;why-is-jsx-declarative&quot; style=&quot;position:relative;&quot;&gt;Why is JSX declarative?&lt;a href=&quot;#why-is-jsx-declarative&quot; aria-label=&quot;why is jsx declarative permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s now look at JSX, a declarative tool we encounter daily. I want to address the question “Why is specific code declarative?” through the lens of JSX.&lt;/p&gt;
&lt;p&gt;One pattern I frequently see in interviews is answering “What is declarative code?” with “It’s using tools like JSX or React.” When I follow up with “So why is JSX declarative?”, the answer is often “Because using JSX lets you write declarative code” — a textbook circular argument.&lt;/p&gt;
&lt;p&gt;The real reason JSX is declarative lies in how it expresses structural relationships. Let’s compare two approaches:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; container &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;div&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;user-profile&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nameElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;h2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  nameElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nameElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;p&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  emailElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; avatarElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;img&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    avatarElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    avatarElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;alt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;s avatar&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;avatarElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; container&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;user-profile&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;s avatar&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first version focuses on the order of creating and manipulating DOM elements: “First create a container, then create a name element and append it, then create an email element and append it…” Temporal order matters — changing the order of &lt;code class=&quot;language-text&quot;&gt;appendChild&lt;/code&gt; calls changes the result.&lt;/p&gt;
&lt;p&gt;The JSX version focuses solely on declaring: “A UserProfile is a structure composed of a name, email, and optionally an avatar.” What matters here is the containment and hierarchy between elements — temporal order is irrelevant.&lt;/p&gt;
&lt;h3 id=&quot;the-correspondence-between-data-and-ui&quot; style=&quot;position:relative;&quot;&gt;The correspondence between data and UI&lt;a href=&quot;#the-correspondence-between-data-and-ui&quot; aria-label=&quot;the correspondence between data and ui permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JSX’s real power lies in its ability to intuitively express the correspondence between data structures and UI structures.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;TodoList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todos &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;todo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TodoItem&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;completed&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at this code, you can immediately read the relationship: each item in the &lt;code class=&quot;language-text&quot;&gt;todos&lt;/code&gt; array corresponds to a &lt;code class=&quot;language-text&quot;&gt;TodoItem&lt;/code&gt; component. The structure of the data &lt;em&gt;becomes&lt;/em&gt; the structure of the UI.&lt;/p&gt;
&lt;p&gt;The same behavior written imperatively looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createTodoList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ul &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ul&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; li &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;li&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    li&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      li&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;completed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    ul&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;li&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ul&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the imperative version, procedural steps — data iteration, element creation, attribute setting, DOM insertion — are all tangled together. To understand the relationship between the data structure and the final UI, you have to read the entire code and mentally execute it.&lt;/p&gt;
&lt;h3 id=&quot;expressing-structural-relationships&quot; style=&quot;position:relative;&quot;&gt;Expressing structural relationships&lt;a href=&quot;#expressing-structural-relationships&quot; aria-label=&quot;expressing structural relationships permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JSX is similar to how mathematics expresses set relationships. When we write &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A = \{a, b, c\}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, we declare that set &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is composed of elements &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a, b, c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. This relationship is independent of the order in which elements were added.&lt;/p&gt;
&lt;p&gt;JSX works the same way. When we write code like this, we declare “UserCard is composed of Avatar and UserInfo.” This relationship is conceptually separate from the order in which components are rendered.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Declaration of structural relationships&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;UserCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;user-card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Avatar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserInfo&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It focuses solely on declaring “a user card is a combination of an avatar and user info.” How each component is implemented and in what order they’re added to the DOM are separate concerns.&lt;/p&gt;
&lt;p&gt;From this perspective, JSX is declarative not merely because it hides complex processes, but because it lets you directly express the essential relationships between data and UI.&lt;/p&gt;
&lt;p&gt;Now that we understand why JSX is declarative, a question might arise:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“But JSX ultimately compiles to &lt;code class=&quot;language-text&quot;&gt;createElement&lt;/code&gt;, and React’s reconciliation is procedural code too, right? Is it really declarative then?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;declarative-and-procedural-are-relative&quot; style=&quot;position:relative;&quot;&gt;Declarative and procedural are relative&lt;a href=&quot;#declarative-and-procedural-are-relative&quot; aria-label=&quot;declarative and procedural are relative permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a critical point when understanding abstraction and declarative programming — treating these concepts as absolutes leads to serious misconceptions.&lt;/p&gt;
&lt;p&gt;In reality, the same code can be declarative or procedural depending on your vantage point and level of abstraction. “Declarative” and “procedural” aren’t absolute categories. They’re relative concepts.&lt;/p&gt;
&lt;p&gt;Let’s examine this relativity through a React Query example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Application level — declarative&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isLoading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isLoading&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Loading...&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;An error occurred&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From the application developer’s perspective, this code is completely declarative. It declares a relationship: “a query that fetches user data for a given &lt;code class=&quot;language-text&quot;&gt;userId&lt;/code&gt;.” Complex logic like caching, retries, and error handling is all abstracted away.&lt;/p&gt;
&lt;p&gt;But the &lt;a href=&quot;https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;QueryClient implementation code&lt;/a&gt; behind &lt;code class=&quot;language-text&quot;&gt;useQuery&lt;/code&gt; is procedural — cache checks, network requests, state updates, and retry logic are all laid out explicitly.&lt;/p&gt;
&lt;p&gt;This relativity becomes especially clear at domain boundaries. Looking at an order processing function at the business logic level:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Business logic level — declarative&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; validatedOrder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;validatedOrder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scheduleShipment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;validatedOrder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createOrderConfirmation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;validatedOrder&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; payment&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shipment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function is declarative from a business logic perspective — it clearly expresses the relationships: “validate the order, process payment, and schedule shipping.” But the infrastructure-level functions underneath, like payment processing, are procedural:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Infrastructure level — procedural&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentGateway &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PAYMENT_API_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentRequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      currency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;currency&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      source&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;paymentMethod
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; paymentGateway&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paymentRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;succeeded&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;payments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        orderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        paymentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;completed&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; paymentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Payment processing failed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; orderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The concept of “declarative” is relative depending on which layer you’re observing from. The point of declarative code is how well the abstracted parts are expressed so you need to inspect the procedurally written parts less.&lt;/p&gt;
&lt;p&gt;Another common prejudice is that “procedural code is bad and should always be avoided.” This too is misguided. Even the most elegant functional code ultimately runs as procedural CPU instructions.&lt;/p&gt;
&lt;p&gt;What matters is providing the right abstraction at the right level.&lt;/p&gt;
&lt;p&gt;Understanding this relativity reveals that finding appropriate abstractions at each level is what’s important. Not everything needs to be declarative. At the business logic level, a declarative approach works well because the focus should be on expressing the essential relationships of the domain. At the infrastructure level, procedural code is perfectly fine because efficient, safe implementation matters more.&lt;/p&gt;
&lt;p&gt;The key is to draw clear boundaries and match the level of abstraction. It must be clear which level handles which concerns. In a good design, the business level declaratively expresses the shopping cart’s structure, while the infrastructure level uses procedural calculation logic — and that’s perfectly fine.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Good example: Clear level separation&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Business level — declarative&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;ShoppingCart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onCheckout &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shopping-cart&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ItemList&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TotalPrice&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CheckoutButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onCheckout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Presentation level — declarative&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;ItemList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; items &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ItemCard&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Infrastructure level — procedural is OK&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalWithTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    subtotal &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From this perspective, declarative programming isn’t about “making all code declarative” — it’s about “having the right expressiveness at the right level of abstraction.”&lt;/p&gt;
&lt;h2 id=&quot;code-that-looks-declarative-vs-code-that-actually-is&quot; style=&quot;position:relative;&quot;&gt;Code that looks declarative vs. code that actually is&lt;a href=&quot;#code-that-looks-declarative-vs-code-that-actually-is&quot; aria-label=&quot;code that looks declarative vs code that actually is permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now let’s concretely answer the core question: “What makes specific code declarative?” The essence of declarative code is clearly defining the &lt;em&gt;relationships between possible states&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Just as mathematics defines the domain of a function precisely, a program should first declare “which state combinations are logically possible.”&lt;/p&gt;
&lt;p&gt;Consider asynchronous data requests. In reality, only states like idle, loading, success (with data), and error (with an error message) are logically possible. A state that is “loading while simultaneously having data and an error” is a contradictory combination that can’t happen in reality.&lt;/p&gt;
&lt;p&gt;Let’s examine this through handling async data in a React + TypeScript environment.&lt;/p&gt;
&lt;h3 id=&quot;code-that-looks-declarative--focused-on-state-change-processes&quot; style=&quot;position:relative;&quot;&gt;Code that looks declarative — focused on state change processes&lt;a href=&quot;#code-that-looks-declarative--focused-on-state-change-processes&quot; aria-label=&quot;code that looks declarative  focused on state change processes permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An async data hook written with a procedural approach focuses on &lt;em&gt;how&lt;/em&gt; state changes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Procedural approach — focused on how state changes&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setData&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setLoading&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setError&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Step 1: Transition to loading state&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setLoading&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Step 2: Transition to success state&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setLoading&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Step 3: Transition to error state&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setLoading&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;truly-declarative-code--focused-on-state-relationships&quot; style=&quot;position:relative;&quot;&gt;Truly declarative code — focused on state relationships&lt;a href=&quot;#truly-declarative-code--focused-on-state-relationships&quot; aria-label=&quot;truly declarative code  focused on state relationships permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The declarative approach focuses on &lt;em&gt;what&lt;/em&gt; the possible states are:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Declarative approach — focused on what states are possible&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setState&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;why-is-the-first-version-procedural&quot; style=&quot;position:relative;&quot;&gt;Why is the first version procedural?&lt;a href=&quot;#why-is-the-first-version-procedural&quot; aria-label=&quot;why is the first version procedural permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first version focuses on the sequence and process of state changes: “First set loading to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;, reset error to &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;, reset data to &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;…” — a series of procedural commands.&lt;/p&gt;
&lt;p&gt;The more critical problem is that impossible state combinations are permitted at the type level. TypeScript can’t prevent a nonsensical state like &lt;code class=&quot;language-text&quot;&gt;{ data: someUserData, loading: true, error: &quot;Network Error&quot; }&lt;/code&gt;. Having data while simultaneously loading and having an error is a logical contradiction. But with the first approach, the developer must manually guarantee the validity of all state combinations.&lt;/p&gt;
&lt;p&gt;You have to check at every &lt;code class=&quot;language-text&quot;&gt;setState&lt;/code&gt; call whether the other states are properly reset — and this easily leads to human error. For instance, forgetting &lt;code class=&quot;language-text&quot;&gt;setLoading(false)&lt;/code&gt; on success, or omitting &lt;code class=&quot;language-text&quot;&gt;setData(null)&lt;/code&gt; on error.&lt;/p&gt;
&lt;h3 id=&quot;why-is-the-second-version-declarative&quot; style=&quot;position:relative;&quot;&gt;Why is the second version declarative?&lt;a href=&quot;#why-is-the-second-version-declarative&quot; aria-label=&quot;why is the second version declarative permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The second version declares the essential state relationships of the “async data request” domain. Through a union type, it expresses the invariant relationship “exactly one of these four states can exist” at the type level.&lt;/p&gt;
&lt;p&gt;The key point is that impossible states are blocked at the source. The TypeScript compiler prevents contradictory combinations like “loading and success at the same time” at compile time. This follows the same principle as clearly defining a function’s domain in mathematics. In &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f: A \rightarrow B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is the domain of function &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is undefined for values outside &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Let’s look more concretely at the safety guarantees union types provide:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Safety enforced by TypeScript at compile time&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;handleAsyncState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Not started yet&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Loading...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Accessing state.data or state.error here causes a compile error&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Data: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.data is guaranteed to exist here&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Accessing state.error causes a compile error&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.error is guaranteed to exist here&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Accessing state.data causes a compile error&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// TypeScript verifies all cases are handled&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exhaustiveCheck&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; exhaustiveCheck&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In each case, only the properties valid for that state are accessible — attempting to access other properties results in a compile error. The &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; type in the &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt; case lets the compiler verify that all cases have been covered.&lt;/p&gt;
&lt;h3 id=&quot;differences-in-component-usage&quot; style=&quot;position:relative;&quot;&gt;Differences in component usage&lt;a href=&quot;#differences-in-component-usage&quot; aria-label=&quot;differences in component usage permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using the first approach requires the developer to manually handle all combinations:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// First approach — manual handling of all combinations&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;DataDisplay&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fetcher&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Developer must manually consider every combination&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;LoadingSpinner&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ErrorMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// How do we handle unexpected state combinations?&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// What about { loading: true, data: someData, error: null }?&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Unknown state&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The second approach lets the types guarantee complete coverage:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Second approach — types guarantee all cases&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;DataDisplay&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fetcher&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// TypeScript verifies all cases are handled&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Ready...&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;LoadingSpinner&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.data is guaranteed to be of type T&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.error is guaranteed to exist&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ErrorMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// TypeScript verifies at compile time that all cases are covered&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Adding a new state triggers a compile error for unhandled cases&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;TypeScript verifies that all cases are handled and guarantees that the relevant properties exist in each case. When a new state is added, compile errors surface any missed spots.&lt;/p&gt;
&lt;h3 id=&quot;differences-in-extensibility&quot; style=&quot;position:relative;&quot;&gt;Differences in extensibility&lt;a href=&quot;#differences-in-extensibility&quot; aria-label=&quot;differences in extensibility permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider a scenario where you need to add new states. With the first approach, you must modify multiple variables:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// First approach — must modify multiple variables&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;retrying&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setRetrying&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;stale&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setStale&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Each state change requires considering combinations with all other states&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Of 16 boolean combinations, how many are logically valid?&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the second approach, you simply extend the type definition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Second approach — just extend the type definition&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;retrying&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; previousError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; attempt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; stale&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// TypeScript forces handling of new cases at all usage sites&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Compile errors surface any missed spots&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Adding a new state makes TypeScript enforce handling at every usage site. Compile errors reliably surface anything you’ve missed, allowing safe extension.&lt;/p&gt;
&lt;p&gt;The essence of declarative thinking in this example is defining “what is possible” first. Just as mathematics defines a function’s domain and range precisely, we explicitly declare the possible states of an async request.&lt;/p&gt;
&lt;p&gt;Procedural approaches focus on “how to change state,” while declarative approaches first declare “which states are logically possible in this problem domain.” This shift in perspective is the essence of declarative programming.&lt;/p&gt;
&lt;h2 id=&quot;practical-guidelines&quot; style=&quot;position:relative;&quot;&gt;Practical guidelines&lt;a href=&quot;#practical-guidelines&quot; aria-label=&quot;practical guidelines permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now let’s distill the theory into concrete criteria for real-world application. Here are practical guidelines for when to choose procedural vs. declarative approaches.&lt;/p&gt;
&lt;h3 id=&quot;when-should-you-take-a-declarative-approach&quot; style=&quot;position:relative;&quot;&gt;When should you take a declarative approach?&lt;a href=&quot;#when-should-you-take-a-declarative-approach&quot; aria-label=&quot;when should you take a declarative approach permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Business logic and state management benefit from a declarative approach. As with the async data state example above, when complex state combinations are possible, it’s important to block impossible states at the type level:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Reusing the AsyncDataState example from above&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;UI structure is also a natural fit for the declarative approach. As we saw with JSX, you can directly express the structural relationship between data and UI:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Reusing the JSX example — clearly declaring structural relationships&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;UserProfile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;user-profile&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;s avatar&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Data transformation pipelines also benefit from a declarative approach when each step can be independently defined and tested:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Clearly declaring transformation relationships&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;processUserData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawUsers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RawUser&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  rawUsers
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isActiveUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;normalizeUserData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addComputedFields&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;byLastLoginDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;when-is-a-procedural-approach-acceptable&quot; style=&quot;position:relative;&quot;&gt;When is a procedural approach acceptable?&lt;a href=&quot;#when-is-a-procedural-approach-acceptable&quot; aria-label=&quot;when is a procedural approach acceptable permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Infrastructure-level code and performance optimization are well suited to procedural approaches.&lt;/p&gt;
&lt;p&gt;As discussed in the relativity section, when efficiency and performance matter, procedural implementation is natural:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Reusing the calculation logic example from above&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalWithTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    subtotal &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Complex state management and optimization in library code, like React Query’s internals, also calls for procedural approaches. Cache checks, network requests, state updates, and retry logic are more efficiently implemented procedurally.&lt;/p&gt;
&lt;p&gt;System-level code with complex error handling is another good fit:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Complex error handling and retry logic&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;retryWithBackoff&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  maxAttempts&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; lastError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; attempt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; attempt &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; maxAttempts&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; attempt&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      lastError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attempt &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; maxAttempts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; lastError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; delay &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; attempt &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delay&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; lastError&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Declarative programming isn’t about using specific syntax or tools. It’s a shift in thinking, from “how” to “what,” from procedures to relationships.&lt;/p&gt;
&lt;p&gt;The core ideas: relational thinking over temporal sequences. Declaring possible states upfront and blocking impossible ones at the type level. Providing the right abstraction at the right level. And remembering that “declarative” is always relative to the layer you’re looking at.&lt;/p&gt;
&lt;p&gt;Declarative programming is a way of thinking, not a tool. When you internalize that, the code you write starts to look different.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[선언적 프로그래밍에 대한 착각과 오해]]></title><description><![CDATA[필자는 평소 기술 인터뷰를 진행하며 지원자 분들이 과제를 작성하면서 내렸던 의사결정에 대한 근거를 물어보는 경우가 잦다. 이때 이에 대한 근거로 “이런 방식이 보다 선언적이기 때문이다”라는 답변을 많이 해주시는데, 정작 그 방식이 왜 선언적인 것인지, 선언적인 코드란 무엇인지 여쭤보면 시원한 답변을 해주시는 경우는 많지 않았던 것 같다. 그래서 이번 포스팅에서는 필자가 생각하는 선언적이라는 것이 무엇인지, 그리고 선언적인 코드란 무엇인지에 대해서 한번 간략하게 이야기해보려고 한다.]]></description><link>https://evan-moon.github.io/2025/09/07/declarative-programming-misconceptions-and-essence/</link><guid isPermaLink="false">20250907-declarative-programming-misconceptions-and-essence</guid><pubDate>Sun, 07 Sep 2025 07:16:53 GMT</pubDate><content:encoded>&lt;p&gt;필자는 평소 기술 인터뷰를 진행하며 지원자 분들이 과제를 작성하면서 내렸던 의사결정에 대한 근거를 물어보는 경우가 잦다.&lt;/p&gt;
&lt;p&gt;이때 이에 대한 근거로 “이런 방식이 보다 선언적이기 때문이다”라는 답변을 많이 해주시는데, 정작 그 방식이 왜 선언적인 것인지, 선언적인 코드란 무엇인지 여쭤보면 시원한 답변을 해주시는 경우는 많지 않았던 것 같다.&lt;/p&gt;
&lt;p&gt;그래서 이번 포스팅에서는 필자가 생각하는 선언적이라는 것이 무엇인지, 그리고 선언적인 코드란 무엇인지에 대해서 한번 간략하게 이야기해보려고 한다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;많은 개발자들이 스스로 선언적인 코드를 작성한다고 생각하지만 실제로는 본질을 놓치고 있는 경우가 종종 있으며, 단지 특정한 도구를 사용하거나 문법을 사용하는 것이 선언적인 것이라고 착각하고는 한다.&lt;/p&gt;
&lt;p&gt;하지만 필자가 생각하는 선언적 프로그래밍은 도구의 문제가 아니라 사고방식의 근본적 전환이다.&lt;/p&gt;
&lt;h2 id=&quot;선언적-프로그래밍에-대한-가장-흔한-착각&quot; style=&quot;position:relative;&quot;&gt;선언적 프로그래밍에 대한 가장 흔한 착각&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%80%EC%9E%A5-%ED%9D%94%ED%95%9C-%EC%B0%A9%EA%B0%81&quot; aria-label=&quot;선언적 프로그래밍에 대한 가장 흔한 착각 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;많은 개발자들이 빠지는 첫 번째 함정은 “절차적인 동작을 함수로 추상화하면 선언적”이라는 착각이다. 하지만 함수를 사용한다고 해서 무조건 선언적인 프로그래밍을 구사하는 것은 아니다.&lt;/p&gt;
&lt;p&gt;가장 간단한 예부터 살펴보자. 사용자 정보를 가져오는 함수를 절차적으로 작성하면 이렇게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUserInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; connection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;connectDB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userRow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;SELECT * FROM users WHERE id = ?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; permissionRows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;SELECT * FROM permissions WHERE user_id = ?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userRow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userRow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userRow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    permissions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; permissionRows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permission_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;displayName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드는 함수를 사용하고는 있지만 “먼저 DB에서 사용자를 가져오고, 그 다음 권한을 추가하고, 마지막에 포맷팅한다”는 시간적 순서에 집중하고 있다. 즉, 함수를 사용했다고 해서 절차적 사고에서 벗어난 것이 아니다.&lt;/p&gt;
&lt;p&gt;선언적인 코드는 동작의 시간적 순서에서 벗어나 동작 간의 관계를 기술하는 것에 집중해야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 선언적 접근 - 데이터 변환 관계에 집중&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getUserInfo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; 
  &lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    fetchUserFromDB&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    addUserPermissions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    formatUserData
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 또는 더 명확하게&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getUserInfo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; 
  &lt;span class=&quot;token function&quot;&gt;formatUserData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;addUserPermissions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;fetchUserFromDB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 “사용자 ID → 포맷된 사용자 정보”라는 관계를 선언한다. 실행 순서가 아니라 데이터 변환의 관계에 집중하고 있다.&lt;/p&gt;
&lt;p&gt;여기서 핵심 구분 기준은 명확하다. 절차적 코드는 “어떻게(How) 단계별로 실행할 것인가”에 집중하고, 선언적 코드는 “무엇을(What) 원하는 관계인가”에 집중한다.&lt;/p&gt;
&lt;p&gt;이런 착각은 특히 배열 메소드를 사용할 때 자주 발생한다. &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;filter&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;reduce&lt;/code&gt; 같은 메소드를 쓰면 자동으로 선언적 코드가 된다고 생각하는 경우가 많다.&lt;/p&gt;
&lt;p&gt;하지만 마찬가지로 배열 메소드를 사용하더라도 얼마든지 절차적인 사고가 가능하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 배열 메소드를 사용했지만 절차적 사고&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; items
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;basePrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; finalPrice&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;finalPrice &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반면 선언적인 접근은 각각의 변환이 나타내는 비즈니스 관계에만 집중하여 기술한다는 차이점이 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 진정한 선언적 접근&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;processItems&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  items
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;applyDiscount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addTax&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatPrice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasValidPrice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;applyDiscount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;basePrice &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;addTax&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;formatPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;finalPrice&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hasValidPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;finalPrice &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 코드는 배열 메소드를 사용했지만 여전히 단계별 처리 과정에 집중하고 있지만, 두 번째 코드는 각각의 변환이 나타내는 비즈니스 관계를 명확히 선언하고 있다.&lt;/p&gt;
&lt;p&gt;중요한 것은 그 함수가 무엇을 하는지를 명확하게 표현하는 올바른 추상화까지 곁들여야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;결국 함수 자체는 중립적인 도구다. 절차적 사고를 함수로 포장할 수도 있고, 관계적 사고를 함수로 표현할 수도 있다. 선언적 프로그래밍의 핵심은 함수 사용 여부가 아니라, 그 함수가 어떤 추상화를 제공하느냐에 따라 달라진다.&lt;/p&gt;
&lt;p&gt;대략적인 예시만으로는 이해가 쉽지 않을 수 있으니 이제 본질적인 부분을 살펴보도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;수학적-관점에서-본-선언적-프로그래밍&quot; style=&quot;position:relative;&quot;&gt;수학적 관점에서 본 선언적 프로그래밍&lt;a href=&quot;#%EC%88%98%ED%95%99%EC%A0%81-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EB%B3%B8-%EC%84%A0%EC%96%B8%EC%A0%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot; aria-label=&quot;수학적 관점에서 본 선언적 프로그래밍 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;선언적 프로그래밍을 제대로 이해하려면 먼저 “선언”이라는 개념 자체를 이해해야 한다. 이를 가장 쉽게 이해할 수 있는 방법은 일상의 예시부터 시작하는 것이다.&lt;/p&gt;
&lt;p&gt;우리가 요리 레시피를 생각해보자. 절차적 접근은 레시피와 같다. “물 2컵을 끓인다, 면을 넣고 3분간 끓인다, 스프를 넣고 1분간 더 끓인다, 그릇에 담는다”라는 시간의 흐름에 따른 행동 지침이다.&lt;/p&gt;
&lt;p&gt;반면 선언적 접근은 관계를 표현한다. “라면 = 삶은 면 + 스프 + 뜨거운 물의 조합”이라는 재료들 사이의 본질적 관계를 나타낸다.&lt;/p&gt;
&lt;p&gt;레시피는 시간의 흐름에 따른 행동 지침이고, 관계적 선언은 재료들 사이의 본질적 관계를 나타낸다. 이 차이가 바로 절차적 사고와 선언적 사고의 본질적 차이다.&lt;/p&gt;
&lt;p&gt;수학에서 더 명확한 예를 살펴보자. 우리가 중학교 때 배운 일차함수 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x) = 2x + 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;을 생각해보자. 이 수식은 컴퓨터에게 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 2를 곱하고 1을 더하라”는 명령이 아니다. 이는 ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 사이에는 이런 관계가 있다”는 사실을 선언한 것이다.&lt;/p&gt;
&lt;p&gt;이 선언은 관계에 대한 기술이기 때문에 시간과 무관한 영원한 진리다. 언제 어디서나 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 3이라면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 7이라는 것이다. 여기서 계산 과정이나 실행 순서는 중요하지 않다. 중요한 것은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 관계 그 자체다.&lt;/p&gt;
&lt;p&gt;수학자들이 함수를 정의할 때 주목하는 것은 바로 이런 불변적 관계다. 함수는 계산 알고리즘이 아니라 구조 간의 대응 관계를 나타내는 것이다. 우리가 삼각함수 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;sin&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sin(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 정의할 때, 우리는 단위원에서 각도와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;좌표 사이의 관계를 선언하는 것이지, 어떻게 계산할지를 지시하는 것이 아닌 것과 마찬가지이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ce883bea384b4c39d034555b129d50a2/151cf/image1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdxYEj//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAEFAl//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAYEAADAQEAAAAAAAAAAAAAAAAAEBEBQf/aAAgBAQABPyHqwhF//9oADAMBAAIAAwAAABCzz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABsQAAIDAQEBAAAAAAAAAAAAAAERACExQVGR/9oACAEBAAE/EGSd4Zo0ivZnuxW2fsVdgFT/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;image1&quot; title=&quot;&quot; src=&quot;/static/ce883bea384b4c39d034555b129d50a2/c08c5/image1.jpg&quot; srcset=&quot;/static/ce883bea384b4c39d034555b129d50a2/0913d/image1.jpg 160w,
/static/ce883bea384b4c39d034555b129d50a2/cb69c/image1.jpg 320w,
/static/ce883bea384b4c39d034555b129d50a2/c08c5/image1.jpg 640w,
/static/ce883bea384b4c39d034555b129d50a2/6a068/image1.jpg 960w,
/static/ce883bea384b4c39d034555b129d50a2/151cf/image1.jpg 1181w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;우리가 삼각비 표를 외우는 것은 sin, cos, tan 함수가 나타내는 관계를 외우는 것이다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;프로그래밍에서도 마찬가지다. 선언적 코드는 컴퓨터에게 어떤 일을 할지 주문하는 것이 아니라 “이 문제의 본질은 이런 관계에 있다”는 것을 표현한다. 이런 관점에서 보면, 프로그래밍은 계산 과정을 지시하는 것이 아니라 문제 도메인의 수학적 구조를 발견하고 표현하는 행위가 된다.&lt;/p&gt;
&lt;h2 id=&quot;절차적-vs-선언적-사고방식의-차이&quot; style=&quot;position:relative;&quot;&gt;절차적 vs 선언적: 사고방식의 차이&lt;a href=&quot;#%EC%A0%88%EC%B0%A8%EC%A0%81-vs-%EC%84%A0%EC%96%B8%EC%A0%81-%EC%82%AC%EA%B3%A0%EB%B0%A9%EC%8B%9D%EC%9D%98-%EC%B0%A8%EC%9D%B4&quot; aria-label=&quot;절차적 vs 선언적 사고방식의 차이 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제 같은 기능을 두 가지 사고방식으로 접근한 구체적 예시를 통해 차이점을 명확히 해보자. 절차적 사고는 시간의 흐름 속에서 일어나는 변화에 집중한다. “먼저 이것을 하고, 그 다음에 저것을 하고…”라는 순차적 실행 모델이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 절차적 프로그래밍 - 어떻게(How) 할 것인가에 집중&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// 단계 1: 각 아이템을 순회&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 단계 2: 유효성 검사&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 단계 3: 기본 가격 계산&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; itemPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token comment&quot;&gt;// 단계 4: 할인 적용&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        itemPrice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; itemPrice &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itemPrice &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      
      &lt;span class=&quot;token comment&quot;&gt;// 단계 5: 총합에 누적&lt;/span&gt;
      total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; itemPrice&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; total&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 시간적 순서와 상태 변화에 집중한다. 각 단계에서 무엇이 일어나는지, 변수가 어떻게 변하는지를 추적해야 한다.&lt;/p&gt;
&lt;p&gt;반면 선언적 사고는 시간을 초월한 논리적 관계에 집중한다. “총 가격 = 유효한 아이템들의 할인된 가격들의 합”이라는 관계를 선언한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 선언적 프로그래밍 - 무엇을(What) 원하는가에 집중&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;calculateTotalPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  items
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasValidQuantity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;calculateItemPrice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hasValidQuantity&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;calculateItemPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; 
  item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;discount &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 데이터 변환의 관계를 선언한다. 각 함수는 특정한 변환 관계를 나타내고, 이들의 합성으로 전체 문제를 해결한다.&lt;/p&gt;
&lt;p&gt;프로그래밍에서 이 차이는 코드가 표현하는 추상화의 종류로 드러난다. 절차적 코드는 컴퓨터의 실행 과정을 추상화한다. 메모리 할당, 루프 실행, 조건 분기 같은 기계적 연산을 변수와 제어 구조로 포장한다. 선언적 코드는 문제 도메인의 논리적 구조를 추상화한다. 비즈니스 규칙, 데이터 관계, 상태 변환 같은 개념적 관계를 함수와 타입으로 표현한다.&lt;/p&gt;
&lt;p&gt;그렇다면 왜 이런 관계적 사고가 중요할까? 근본적인 이유는 인간의 인지적 한계 때문이다. 심리학자 조지 밀러(George Miller)의 연구에 따르면, 인간의 단기 기억은 동시에 7±2개의 정보 단위만 처리할 수 있다고 한다.&lt;/p&gt;
&lt;p&gt;그러나 절차적 사고에서는 시간의 흐름에 따른 상태 변화를 모두 추적해야 하며 프로그램이 복잡해질수록 이런 상태들의 조합이 기하급수적으로 증가한다. 10개의 변수가 있다면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1024&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^{10} = 1024&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가지의 가능한 상태가 있고, 각 단계에서 이 모든 경우의 수를 고려해야 한다는 의미이다. 인간의 기억력으로 이 모든 변화를 추적하는 것은 불가능에 가깝다.&lt;/p&gt;
&lt;p&gt;반면 관계적 사고에서는 불변적 관계의 합성으로 복잡성을 관리한다. 수학에서 복잡한 함수를 간단한 함수들의 합성으로 표현하는 것과 같은 원리다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;h(x) = f(g(x))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;h&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 이해하기 위해 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 내부 구현을 모두 알 필요가 없고 각각의 입출력 관계만 이해하면 되는 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;이러한 관계적 사고로 인해 복잡한 상태들을 몇 개의 청크로 나누어 기억할 수 있게 되고, 이는 우리가 복잡한 코드를 이해하는 데 큰 도움을 준다.&lt;/p&gt;
&lt;h2 id=&quot;jsx는-왜-선언적일까&quot; style=&quot;position:relative;&quot;&gt;JSX는 왜 선언적일까?&lt;a href=&quot;#jsx%EB%8A%94-%EC%99%9C-%EC%84%A0%EC%96%B8%EC%A0%81%EC%9D%BC%EA%B9%8C&quot; aria-label=&quot;jsx는 왜 선언적일까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제 평소에 우리가 자주 접하는 대표적인 선언적 도구인 JSX를 예시로 한번 살펴보자. 앞서 제기한 “왜 특정 코드가 선언적인가?”라는 질문에 대해 JSX를 통해 한번 알아보려고 한다.&lt;/p&gt;
&lt;p&gt;필자가 인터뷰에서 자주 보는 광경 중 하나는 바로 “선언적인 코드란 무엇인가?”라는 질문에 “JSX나 React 같은 도구를 사용하는 것”이라고 답하는 것이다. 이때 “그럼 JSX는 왜 선언적인가요?”라고 물어보면 “JSX를 사용하면 선언적인 코드를 작성할 수 있어서요”라고 답변하는, 전형적인 순환논법에 빠지는 경우가 많았다.&lt;/p&gt;
&lt;p&gt;JSX가 선언적인 진짜 이유는 구조적 관계를 표현하는 방식에 있다. 두 가지 접근법을 비교해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-javascript line-numbers&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; container &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;div&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;className &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;user-profile&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nameElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;h2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  nameElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nameElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;p&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  emailElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; avatarElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;img&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    avatarElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    avatarElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;alt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;의 아바타&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;avatarElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; container&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;user-profile&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;의 아바타&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 코드는 DOM 요소를 생성하고 조작하는 순서에 집중한다. “먼저 컨테이너를 만들고, 그 다음 이름 요소를 만들어서 추가하고, 이메일 요소를 만들어서 추가하고…” 라는 시간적 순서가 중요하다. 심지어 각 &lt;code class=&quot;language-text&quot;&gt;appendChild&lt;/code&gt; 호출의 순서를 바꾸면 결과도 달라진다.&lt;/p&gt;
&lt;p&gt;반면 JSX로 작성된 두 번째 코드는 “UserProfile은 이름, 이메일, 그리고 선택적으로 아바타로 구성된 구조다”라는 관계를 선언하는 것에만 집중한다. 여기서는 요소들 사이의 포함 관계와 계층 구조가 중요하며 시간적 순서는 전혀 중요하지 않다.&lt;/p&gt;
&lt;h3 id=&quot;데이터와-ui의-대응-관계&quot; style=&quot;position:relative;&quot;&gt;데이터와 UI의 대응 관계&lt;a href=&quot;#%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-ui%EC%9D%98-%EB%8C%80%EC%9D%91-%EA%B4%80%EA%B3%84&quot; aria-label=&quot;데이터와 ui의 대응 관계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JSX의 진짜 힘은 데이터 구조와 UI 구조 사이의 대응 관계를 직관적으로 표현할 수 있다는 점에 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;TodoList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todos &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;todo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TodoItem&lt;/span&gt;&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;completed&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드를 보면 &lt;code class=&quot;language-text&quot;&gt;todos&lt;/code&gt; 배열의 각 항목이 &lt;code class=&quot;language-text&quot;&gt;TodoItem&lt;/code&gt; 컴포넌트와 대응된다는 관계가 즉시 읽힌다. 데이터의 구조가 곧 UI의 구조가 되는 것이다.&lt;/p&gt;
&lt;p&gt;같은 동작을 명령형으로 작성하면 이렇게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createTodoList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ul &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ul&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; li &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;li&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    li&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      li&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;completed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    ul&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;li&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ul&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;명령형 코드에서는 데이터 순회, 요소 생성, 속성 설정, DOM 추가 등의 절차적 단계들이 섞여 있다. 데이터의 구조와 최종 UI의 구조 사이의 관계를 파악하려면 전체 코드를 읽고 머릿속으로 실행해봐야 한다.&lt;/p&gt;
&lt;h3 id=&quot;구조적-관계의-표현&quot; style=&quot;position:relative;&quot;&gt;구조적 관계의 표현&lt;a href=&quot;#%EA%B5%AC%EC%A1%B0%EC%A0%81-%EA%B4%80%EA%B3%84%EC%9D%98-%ED%91%9C%ED%98%84&quot; aria-label=&quot;구조적 관계의 표현 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JSX는 수학에서 집합의 관계를 표현하는 것과 비슷하다. 수학에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A = \{a, b, c\}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라고 쓸 때, 우리는 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 원소 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a, b, c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 구성된다는 관계를 선언한다. 이 관계는 원소들을 어떤 순서로 집합에 넣었는지와는 무관하다.&lt;/p&gt;
&lt;p&gt;JSX도 마찬가지다. 아래와 같은 코드를 쓸 때, 우리는 ”&lt;code class=&quot;language-text&quot;&gt;UserCard&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;Avatar&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;UserInfo&lt;/code&gt;로 구성된다”는 구조적 관계를 선언한다. 이 관계는 컴포넌트들이 어떤 순서로 렌더링되는지와는 개념적으로 분리되어 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 구조적 관계의 선언&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;UserCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;user-card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Avatar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserInfo&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, “사용자 카드는 아바타, 사용자 정보의 조합이다”라는 관계를 선언하는 것에만 집중하고 각 컴포넌트가 어떻게 구현되는지, 어떤 순서로 DOM에 추가되는지는 이 관계 선언과는 별개의 관심사다.&lt;/p&gt;
&lt;p&gt;이런 관점에서 보면, JSX가 선언적인 이유는 복잡한 과정을 숨겨주는 것 뿐 아니라, 데이터와 UI 사이의 본질적 관계를 직접적으로 표현할 수 있게 해주기 때문이다.&lt;/p&gt;
&lt;p&gt;JSX가 선언적인 이유를 이해했다면, 이제 한 가지 의문이 들 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“그런데 JSX도 결국 &lt;code class=&quot;language-text&quot;&gt;createElement&lt;/code&gt;로 변환되고, React의 reconciliation도 절차적 코드 아닌가? 그럼 이게 정말 선언적인 건가?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;선언적과-절차적은-상대적이다&quot; style=&quot;position:relative;&quot;&gt;선언적과 절차적은 상대적이다&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81%EA%B3%BC-%EC%A0%88%EC%B0%A8%EC%A0%81%EC%9D%80-%EC%83%81%EB%8C%80%EC%A0%81%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;선언적과 절차적은 상대적이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이는 추상화나 선언적인 프로그래밍을 이해할 때 매우 핵심적인 부분인데, 이 개념들을 절대적인 무언가로 이해하면 치명적인 오개념이 생길 수 있다.&lt;/p&gt;
&lt;p&gt;실제로는 같은 코드라도 관찰하는 관점과 추상화 레벨에 따라 선언적일 수도, 절차적일 수도 있다. “선언적”과 “절차적”은 절대적인 구분이 아니라 상대적인 개념이다.&lt;/p&gt;
&lt;p&gt;React Query를 사용한 예시로 이런 상대성을 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 애플리케이션 레벨 - 선언적&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isLoading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useUserData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isLoading&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;로딩 중...&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;에러가 발생했습니다&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;애플리케이션 개발자의 관점에서 보면 이 코드는 완전히 선언적이다. ”&lt;code class=&quot;language-text&quot;&gt;userId&lt;/code&gt;에 해당하는 사용자 데이터를 가져오는 쿼리”라는 관계를 선언하고 있다. 캐싱, 재시도, 에러 처리 같은 복잡한 로직은 모두 추상화되어 있다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;code class=&quot;language-text&quot;&gt;useQuery&lt;/code&gt;의 핵심 로직인 &lt;a href=&quot;https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;QueryClient를 구현하는 코드&lt;/a&gt;는 절차적이다. 캐시 확인, 네트워크 요청, 상태 업데이트, 재시도 로직 등 복잡한 절차적 과정들이 모두 드러나 있다.&lt;/p&gt;
&lt;p&gt;이런 상대성은 도메인 경계에서 특히 명확하게 드러난다. 비즈니스 로직 레벨에서 주문을 처리하는 함수를 보면 이렇다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 비즈니스 로직 레벨 - 선언적&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; validatedOrder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateOrder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; payment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;validatedOrder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scheduleShipment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;validatedOrder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createOrderConfirmation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;validatedOrder&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; payment&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shipment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 비즈니스 로직 관점에서는 선언적이다. “주문을 검증하고, 결제를 처리하고, 배송을 스케줄링한다”는 관계를 명확히 표현한다. 하지만 그 아래 결제 처리 같은 인프라 레벨 함수들은 절차적이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 인프라 레벨 - 절차적&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentGateway &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PAYMENT_API_KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentRequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      currency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;currency&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      source&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;paymentMethod
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; paymentGateway&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paymentRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;succeeded&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;payments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        orderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        paymentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;completed&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; paymentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Payment processing failed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; orderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 선언적이라는 개념은 어떤 계층에서 바라보냐에 따라 상대적일 수 밖에 없다. 결국 선언적인 코드의 포인트는 절차적으로 작성된 부분을 얼마나 덜 확인할 수 있도록 추상화된 부분을 잘 표현해주는 것이냐에 따라 달려있다.&lt;/p&gt;
&lt;p&gt;또한 “절차적 코드는 나쁘고 무조건 피해야 할 것”이라는 편견도 흔히 볼 수 있는데, 이 역시 잘못된 생각이다. 가장 우아한 함수형 코드도 결국 CPU의 절차적 명령어로 실행되기 때문이다.&lt;/p&gt;
&lt;p&gt;중요한 것은 적절한 레벨에서 적절한 추상화를 제공하는 것이다.&lt;/p&gt;
&lt;p&gt;이런 상대성을 이해하면 각 레벨에서 적절한 추상화를 찾는 것이 중요하다는 것을 알 수 있다. 모든 것을 선언적으로 만들려고 할 필요는 없다. 비즈니스 로직 레벨에서는 선언적으로 접근하는 것이 좋다. 도메인의 본질적 관계를 표현하는 데 집중해야 하기 때문이다. 반면 인프라 레벨에서는 절차적이어도 괜찮다. 효율적이고 안전한 구현이 더 중요하기 때문이다.&lt;/p&gt;
&lt;p&gt;핵심은 경계를 명확히 하고 추상화의 레벨을 맞춰주는 것이다. 어느 레벨에서 어떤 관심사를 다루는지 분명히 구분해야 한다. 좋은 예를 보면, 비즈니스 레벨에서는 선언적으로 쇼핑카트의 구조를 표현하고, 인프라 레벨에서는 절차적인 계산 로직을 사용해도 문제없다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 좋은 예: 명확한 레벨 분리&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 비즈니스 레벨 - 선언적&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;ShoppingCart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onCheckout &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shopping-cart&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ItemList&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TotalPrice&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CheckoutButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onCheckout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 프레젠테이션 레벨 - 선언적&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;ItemList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; items &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ItemCard&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 인프라 레벨 - 절차적이어도 OK&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalWithTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    subtotal &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 관점에서 보면, 선언적 프로그래밍은 “모든 코드를 선언적으로 만드는 것”이 아니라 “적절한 추상화 레벨에서 적절한 표현력을 갖는 것”이라고 할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;선언적인-코드라고-착각하는-코드-vs-진짜-선언적인-코드&quot; style=&quot;position:relative;&quot;&gt;선언적인 코드라고 착각하는 코드 vs 진짜 선언적인 코드&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81%EC%9D%B8-%EC%BD%94%EB%93%9C%EB%9D%BC%EA%B3%A0-%EC%B0%A9%EA%B0%81%ED%95%98%EB%8A%94-%EC%BD%94%EB%93%9C-vs-%EC%A7%84%EC%A7%9C-%EC%84%A0%EC%96%B8%EC%A0%81%EC%9D%B8-%EC%BD%94%EB%93%9C&quot; aria-label=&quot;선언적인 코드라고 착각하는 코드 vs 진짜 선언적인 코드 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제 앞서 제기한 핵심 질문인 “왜 특정 코드가 선언적인가?”에 구체적으로 답해보자. 선언적 코드의 핵심은 “가능한 상태들 간의 관계”를 명확히 정의하는 것이다.&lt;/p&gt;
&lt;p&gt;수학에서 함수의 정의역을 명확히 하는 것처럼, 프로그램에서도 “어떤 상태 조합이 논리적으로 가능한가”를 먼저 선언해야 한다.&lt;/p&gt;
&lt;p&gt;비동기 데이터 요청을 생각해보면, 실제로는 아직 시작하지 않음(idle), 요청 중(loading), 성공(데이터 있음), 실패(에러 있음) 같은 상태들만 논리적으로 가능하다. “로딩 중이면서 동시에 데이터도 있고 에러도 있는” 상태는 현실에서는 일어날 수 없는 모순된 조합이다.&lt;/p&gt;
&lt;p&gt;React + TypeScript 환경에서 비동기 데이터를 다루는 상황을 통해 이런 선언적 사고의 본질을 구체적으로 살펴보자.&lt;/p&gt;
&lt;h3 id=&quot;착각하는-코드---상태-변화-과정에-집중&quot; style=&quot;position:relative;&quot;&gt;착각하는 코드 - 상태 변화 과정에 집중&lt;a href=&quot;#%EC%B0%A9%EA%B0%81%ED%95%98%EB%8A%94-%EC%BD%94%EB%93%9C---%EC%83%81%ED%83%9C-%EB%B3%80%ED%99%94-%EA%B3%BC%EC%A0%95%EC%97%90-%EC%A7%91%EC%A4%91&quot; aria-label=&quot;착각하는 코드   상태 변화 과정에 집중 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;절차적 접근으로 작성된 비동기 데이터 훅을 보면 상태가 어떻게 변하는지에 집중하고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 절차적 접근 - 상태가 어떻게 변하는지에 집중&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setData&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setLoading&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setError&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 1단계: 로딩 상태로 전환&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setLoading&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 2단계: 성공 상태로 전환&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setLoading&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 3단계: 에러 상태로 전환&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setLoading&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;선언적인-코드---상태-관계에-집중&quot; style=&quot;position:relative;&quot;&gt;선언적인 코드 - 상태 관계에 집중&lt;a href=&quot;#%EC%84%A0%EC%96%B8%EC%A0%81%EC%9D%B8-%EC%BD%94%EB%93%9C---%EC%83%81%ED%83%9C-%EA%B4%80%EA%B3%84%EC%97%90-%EC%A7%91%EC%A4%91&quot; aria-label=&quot;선언적인 코드   상태 관계에 집중 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;선언적 접근으로 작성하면 가능한 상태가 무엇인지에 집중한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 선언적 접근 - 가능한 상태가 무엇인지에 집중&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setState&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;왜-첫-번째-코드가-절차적인가&quot; style=&quot;position:relative;&quot;&gt;왜 첫 번째 코드가 절차적인가?&lt;a href=&quot;#%EC%99%9C-%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EC%BD%94%EB%93%9C%EA%B0%80-%EC%A0%88%EC%B0%A8%EC%A0%81%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;왜 첫 번째 코드가 절차적인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;첫 번째 코드는 상태 변화의 순서와 과정에 집중한다. “먼저 로딩을 &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;로 설정하고, 에러를 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;로 초기화하고, 데이터를 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;로 리셋하고…” 같은 절차적 명령의 나열이다.&lt;/p&gt;
&lt;p&gt;더 중요한 문제는 불가능한 상태 조합이 타입 수준에서 허용된다는 점이다. TypeScript가 &lt;code class=&quot;language-text&quot;&gt;{ data: someUserData, loading: true, error: &quot;Network Error&quot; }&lt;/code&gt;라는 말이 안 되는 상태를 막아주지 못한다. 데이터가 있으면서 동시에 로딩 중이고 에러도 있다는 것은 논리적으로 모순이다. 하지만 첫 번째 방식에서는 개발자가 모든 상태 조합의 유효성을 수동으로 보장해야 한다.&lt;/p&gt;
&lt;p&gt;각 &lt;code class=&quot;language-text&quot;&gt;setState&lt;/code&gt; 호출마다 다른 상태들을 올바르게 초기화했는지 일일이 확인해야 하고, 이는 휴먼 에러로 이어지기 쉽다. 예를 들어 성공 시에 &lt;code class=&quot;language-text&quot;&gt;setLoading(false)&lt;/code&gt;를 깜빡하거나, 에러 시에 &lt;code class=&quot;language-text&quot;&gt;setData(null)&lt;/code&gt;을 빼먹을 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;두-번째-코드는-왜-선언적인가&quot; style=&quot;position:relative;&quot;&gt;두 번째 코드는 왜 선언적인가?&lt;a href=&quot;#%EB%91%90-%EB%B2%88%EC%A7%B8-%EC%BD%94%EB%93%9C%EB%8A%94-%EC%99%9C-%EC%84%A0%EC%96%B8%EC%A0%81%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;두 번째 코드는 왜 선언적인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;두 번째 코드는 “비동기 데이터 요청”이라는 도메인의 본질적 상태 관계를 선언한다. Union Type을 통해 “이 네 가지 상태 중 정확히 하나만 존재할 수 있다”는 불변적 관계를 타입 수준에서 표현한다.&lt;/p&gt;
&lt;p&gt;여기서 핵심은 불가능한 상태를 원천적으로 차단한다는 점이다. TypeScript 컴파일러가 로딩 중이면서 동시에 성공 상태 같은 모순된 조합을 컴파일 타임에 방지해준다. 이는 수학에서 집합의 정의역을 명확히 하는 것과 같은 원리다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f: A \rightarrow B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 함수 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 정의역이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 속하지 않는 값에 대해서는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 정의되지 않는다.&lt;/p&gt;
&lt;p&gt;Union Type이 제공하는 안전장치를 더 구체적으로 살펴보면, TypeScript가 컴파일 타임에 강제하는 안전성을 확인할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// TypeScript가 컴파일 타임에 강제하는 안전성&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;handleAsyncState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;아직 시작하지 않음&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;로딩 중...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 여기서 state.data나 state.error 접근 시 컴파일 에러&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;데이터: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 여기서는 state.data가 확실히 존재&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.error 접근 시 컴파일 에러&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;에러: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 여기서는 state.error가 확실히 존재&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.data 접근 시 컴파일 에러&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// TypeScript가 모든 case를 다뤘는지 검증&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exhaustiveCheck&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; exhaustiveCheck&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;각 case에서는 해당 상태에서만 유효한 속성에만 접근할 수 있고, 다른 속성에 접근하려고 하면 컴파일 에러가 발생한다. 또한 &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt; 케이스의 &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; 타입을 통해 모든 경우를 다뤘는지 컴파일러가 검증해준다.&lt;/p&gt;
&lt;h3 id=&quot;컴포넌트에서-사용할-때의-차이&quot; style=&quot;position:relative;&quot;&gt;컴포넌트에서 사용할 때의 차이&lt;a href=&quot;#%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%95%8C%EC%9D%98-%EC%B0%A8%EC%9D%B4&quot; aria-label=&quot;컴포넌트에서 사용할 때의 차이 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;첫 번째 방식을 사용하면 개발자가 모든 조합을 수동으로 처리해야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 첫 번째 방식 - 모든 조합을 수동으로 처리&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;DataDisplay&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fetcher&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;token function-variable function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 개발자가 모든 경우의 수를 수동으로 고려해야 함&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;LoadingSpinner&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ErrorMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// 예상치 못한 상태 조합들은 어떻게 처리할까?&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// { loading: true, data: someData, error: null } 같은 경우는?&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;알 수 없는 상태&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반면 두 번째 방식을 사용하면 타입이 모든 경우를 보장한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 두 번째 방식 - 타입이 모든 경우를 보장&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;DataDisplay&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fetcher&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token function-variable function&quot;&gt;fetcher&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;token function-variable function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useAsyncData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetcher&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// TypeScript가 모든 case를 처리했는지 검증&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;준비 중...&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;LoadingSpinner&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.data가 확실히 T 타입으로 존재&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// state.error가 확실히 존재&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ErrorMessage&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
    &lt;span class=&quot;token comment&quot;&gt;// TypeScript가 모든 case를 다뤘는지 컴파일 타임에 검증&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 새로운 상태가 추가되면 컴파일 에러로 알려줌&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;TypeScript가 모든 case를 처리했는지 검증하고, 각 case에서 해당 속성이 확실히 존재함을 보장한다. 새로운 상태가 추가되면 컴파일 에러를 통해 놓친 부분을 알려준다.&lt;/p&gt;
&lt;h3 id=&quot;확장성-측면에서의-차이&quot; style=&quot;position:relative;&quot;&gt;확장성 측면에서의 차이&lt;a href=&quot;#%ED%99%95%EC%9E%A5%EC%84%B1-%EC%B8%A1%EB%A9%B4%EC%97%90%EC%84%9C%EC%9D%98-%EC%B0%A8%EC%9D%B4&quot; aria-label=&quot;확장성 측면에서의 차이 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;새로운 상태를 추가해야 하는 상황을 생각해보자. 첫 번째 방식에서는 여러 변수를 모두 수정해야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 첫 번째 방식 - 여러 변수를 모두 수정해야 함&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;retrying&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setRetrying&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;stale&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setStale&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 각 상태 변화마다 다른 모든 상태들과의 조합을 고려해야 함&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 16가지 boolean 조합 중 논리적으로 말이 되는 것은 몇 개일까?&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반면 두 번째 방식에서는 타입 정의만 확장하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 두 번째 방식 - 타입 정의만 확장&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;retrying&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; previousError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; attempt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; stale&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// TypeScript가 모든 사용처에서 새로운 case 처리를 강제&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 컴파일 에러를 통해 놓친 부분을 알려줌&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;새로운 상태를 추가하면 TypeScript가 모든 사용처에서 새로운 case를 처리하도록 강제한다. 컴파일 에러를 통해 놓친 부분을 확실히 알려주기 때문에 안전하게 확장할 수 있다.&lt;/p&gt;
&lt;p&gt;이 예시에서 보는 선언적 사고의 핵심은 “무엇이 가능한가”를 먼저 정의하는 것이다. 수학에서 함수의 정의역과 치역을 명확히 하는 것처럼, 비동기 요청의 가능한 상태들을 명시적으로 선언한다.&lt;/p&gt;
&lt;p&gt;절차적 접근은 “어떻게 상태를 변경할 것인가”에 집중하지만, 선언적 접근은 “이 문제 도메인에서 어떤 상태들이 논리적으로 가능한가”를 먼저 선언한다. 이런 관점 전환이 바로 선언적 프로그래밍의 본질이다.&lt;/p&gt;
&lt;h2 id=&quot;실무-적용-가이드라인&quot; style=&quot;position:relative;&quot;&gt;실무 적용 가이드라인&lt;a href=&quot;#%EC%8B%A4%EB%AC%B4-%EC%A0%81%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9C%EB%9D%BC%EC%9D%B8&quot; aria-label=&quot;실무 적용 가이드라인 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제 앞서 살펴본 이론을 실무에 적용할 수 있는 구체적인 기준을 정리해보자. 언제 절차적 접근을 택하고 언제 선언적 접근을 택할 것인가에 대한 실용적 가이드라인이다.&lt;/p&gt;
&lt;h3 id=&quot;언제-선언적-접근을-해야-하는가&quot; style=&quot;position:relative;&quot;&gt;언제 선언적 접근을 해야 하는가?&lt;a href=&quot;#%EC%96%B8%EC%A0%9C-%EC%84%A0%EC%96%B8%EC%A0%81-%EC%A0%91%EA%B7%BC%EC%9D%84-%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94%EA%B0%80&quot; aria-label=&quot;언제 선언적 접근을 해야 하는가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;비즈니스 로직과 상태 관리&lt;/strong&gt;에서는 선언적 접근이 유리하다.&lt;/p&gt;
&lt;p&gt;앞서 다룬 비동기 데이터 상태 예시처럼, 복잡한 상태 조합이 가능한 경우에는 타입 수준에서 불가능한 상태를 차단하는 것이 중요하다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 앞서 다룬 AsyncDataState 예시 재활용&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AsyncDataState&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;idle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;loading&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;UI 구조 표현&lt;/strong&gt;에서도 선언적 접근이 자연스럽다. JSX 예시에서 봤듯이 데이터와 UI 사이의 구조적 관계를 직접 표현할 수 있다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-jsx line-numbers&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// JSX 예시 재활용 - 구조적 관계를 명확히 선언&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;UserProfile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;user-profile&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;avatar&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;의 아바타&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;데이터 변환 파이프라인&lt;/strong&gt;에서도 각 단계가 독립적으로 정의되고 테스트 가능할 때 선언적 접근이 효과적이다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 변환 관계를 명확히 선언&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;processUserData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawUsers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RawUser&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  rawUsers
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isActiveUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;normalizeUserData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addComputedFields&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;byLastLoginDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;언제-절차적-접근을-해도-되는가&quot; style=&quot;position:relative;&quot;&gt;언제 절차적 접근을 해도 되는가?&lt;a href=&quot;#%EC%96%B8%EC%A0%9C-%EC%A0%88%EC%B0%A8%EC%A0%81-%EC%A0%91%EA%B7%BC%EC%9D%84-%ED%95%B4%EB%8F%84-%EB%90%98%EB%8A%94%EA%B0%80&quot; aria-label=&quot;언제 절차적 접근을 해도 되는가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;인프라 레벨과 성능 최적화&lt;/strong&gt;에서는 절차적 접근이 적절하다.&lt;/p&gt;
&lt;p&gt;앞서 상대성 섹션에서 다룬 계산 로직처럼, 효율성과 성능이 중요한 경우에는 절차적 구현이 자연스럽다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 앞서 다룬 계산 로직 예시 재활용&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalWithTax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    subtotal &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tax &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; taxRate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; subtotal &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tax&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;React Query 내부 구현처럼 &lt;strong&gt;복잡한 상태 관리와 최적화&lt;/strong&gt;가 필요한 라이브러리 코드에서도 절차적 접근이 필요하다. 캐시 확인, 네트워크 요청, 상태 업데이트, 재시도 로직 등은 절차적으로 구현하는 것이 효율적이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;에러 처리가 복잡한 시스템 레벨 코드&lt;/strong&gt;에서도 절차적 접근이 적합하다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 복잡한 에러 처리와 재시도 로직&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;retryWithBackoff&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  maxAttempts&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; lastError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; attempt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; attempt &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; maxAttempts&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; attempt&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      lastError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;attempt &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; maxAttempts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; lastError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; delay &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; attempt &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delay&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; lastError&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;선언적 프로그래밍은 단순히 특정 문법이나 도구를 사용하는 것이 아니다. 그것은 “어떻게”에서 “무엇”으로, 절차에서 관계로 사고하는 방식의 전환이다.&lt;/p&gt;
&lt;p&gt;이번 포스팅에서 다룬 핵심 내용을 정리해보면, 선언적 프로그래밍의 본질은 관계적 사고에 있다. 시간적 순서가 아닌 논리적 관계에 집중하는 것이다. 또한 상태 모델링을 통해 가능한 상태를 먼저 선언하고 불가능한 상태를 원천 차단하는 것이 중요하다. 적절한 추상화를 통해 각 레벨에서 적합한 표현력을 제공해야 하며, 이는 절대적 구분이 아닌 관점과 레벨에 따른 상대적 개념이라는 점을 이해해야 한다.&lt;/p&gt;
&lt;p&gt;진정한 선언적 코드의 특징을 보면, 비즈니스 의도가 코드 구조에서 직접 읽힌다. 기술적 복잡성은 적절한 추상화 뒤로 숨겨지고, 각 부분이 독립적으로 이해 가능하면서도 안전하게 합성된다. 그리고 불가능한 상태가 타입 수준에서 방지된다.&lt;/p&gt;
&lt;p&gt;선언적 프로그래밍은 하루아침에 습득할 수 있는 기술이 아니다. 하지만 꾸준히 연습하고 적절한 추상화 레벨을 찾아가는 과정에서, 더 읽기 쉽고 유지보수하기 쉬운 코드를 작성할 수 있게 될 것이다.&lt;/p&gt;
&lt;p&gt;코드는 컴퓨터를 위한 것이 아니라 사람을 위한 것이다. 선언적 프로그래밍은 바로 그 사람들이 복잡한 문제를 더 쉽게 이해하고 다룰 수 있게 도와주는 강력한 도구다.&lt;/p&gt;
&lt;p&gt;선언적 프로그래밍은 도구가 아니라 사고방식이며, 문법이 아니라 철학이다. 이 철학을 이해하고 실무에 적용할 때, 우리는 더 나은 코드를 작성할 수 있게 된다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Unconditional Respect for Diversity Is an Illusion: Wisdom from Buddhist Dependent Origination for Running Organizations]]></title><description><![CDATA[In modern organizations, “diversity” is treated as a given. The belief that people from diverse backgrounds create synergy and that…]]></description><link>https://evan-moon.github.io/2025/07/06/diversity-illusion-leadership/en/</link><guid isPermaLink="false">20250706-diversity-illusion-leadership-en</guid><pubDate>Sun, 06 Jul 2025 07:09:54 GMT</pubDate><content:encoded>&lt;p&gt;In modern organizations, “diversity” is treated as a given. The belief that people from diverse backgrounds create synergy and that different perspectives drive innovation has become common wisdom. In the tech industry especially, Diversity &amp;#x26; Inclusion has established itself as a core keyword of organizational culture.&lt;/p&gt;
&lt;p&gt;But when you actually work as a leader, you realize that these idealistic principles create surprisingly complex dilemmas. Should we unconditionally respect every kind of diversity? When an individual’s choices clash with the organization’s goals, what criteria should a leader use to make decisions?&lt;/p&gt;
&lt;p&gt;In this post, I want to share a specific dilemma I faced while working as a chapter lead in a frontend organization of about 100 people, and the wisdom I found within the limits of respecting diversity.&lt;/p&gt;
&lt;p&gt;Along the way, I’ll explore how Buddhist philosophy, particularly dependent origination and the Middle Way, can offer practical insights for running modern organizations.&lt;/p&gt;
&lt;h2 id=&quot;where-the-dilemma-begins&quot; style=&quot;position:relative;&quot;&gt;Where the dilemma begins&lt;a href=&quot;#where-the-dilemma-begins&quot; aria-label=&quot;where the dilemma begins permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a leader striving to build an excellent organization, I need to support and encourage my team members’ growth. But with 100 people in the group, there are inevitably those who think differently.&lt;/p&gt;
&lt;p&gt;Recently, one team member sent me into deep contemplation. They had outstanding technical skills, executed their current responsibilities flawlessly, and earned the trust of their colleagues. From my perspective, they’d be a perfect fit for a lead role. But they declined any such additional responsibility.&lt;/p&gt;
&lt;p&gt;Whenever I suggested new challenges for their growth, they would calmly respond:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I’m not really thinking about that right now.”&lt;/p&gt;
&lt;p&gt;“I’d rather focus on other things.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If they had been underperforming while also refusing to grow, it would have been a clear-cut problem. But the fact that they were already doing excellent work made it all the more ambiguous.&lt;/p&gt;
&lt;p&gt;This experience raised fundamental questions for me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Is it right to set higher goals for someone who’s already doing well enough?”&lt;/p&gt;
&lt;p&gt;And: “How far should the principle of respecting individual diversity and choice extend?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I’m sure many of you have wrestled with similar dilemmas. Facing this kind of situation, we tend to oscillate between two extremes: “We must unconditionally respect diversity” on one side, and “The organization’s goals require uniformity” on the other.&lt;/p&gt;
&lt;p&gt;Through this experience, I realized I needed a perspective beyond these binary choices. What traps might be hiding within the notion of “respecting diversity” that we so readily take for granted?&lt;/p&gt;
&lt;h2 id=&quot;the-trap-of-respecting-diversity&quot; style=&quot;position:relative;&quot;&gt;The trap of respecting diversity&lt;a href=&quot;#the-trap-of-respecting-diversity&quot; aria-label=&quot;the trap of respecting diversity permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I dug deeper into this issue, I realized that diversity is often approached in a binary way — people tend to simply divide it into either respecting diversity or not.&lt;/p&gt;
&lt;p&gt;But reality isn’t that simple. Respecting diversity isn’t an absolute principle; it should be approached as a question of how much an organization or society can accommodate given its specific characteristics.&lt;/p&gt;
&lt;p&gt;This connects to the truth revealed by the Buddhist concept of dependent origination (pratītyasamutpāda). Because all phenomena exist in mutual dependence, neither absolute freedom nor absolute control is possible. &lt;small&gt;(I know bringing up Buddhism out of nowhere might seem surprising, but the stories from Buddhist teachings actually offer a great deal of life wisdom.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Take the South Korean constitution as an example. South Korea is a democracy that guarantees its citizens’ freedom, yet Article 8 of the constitution allows for the dissolution of political parties under certain conditions. This means that when elements threaten the basic democratic order, freedom cannot be granted without limits. In other words, even the state doesn’t unconditionally respect all forms of diversity.&lt;/p&gt;
&lt;p&gt;The same principle applies to organizations. Should a company tolerate an employee who doesn’t keep regular working hours or insists on working from home despite an uncooperative attitude, simply because “we respect diversity”? Diversity deserves respect, but when it conflicts with the organization’s operations and objectives, limits are inevitable.&lt;/p&gt;
&lt;p&gt;Through these observations, I arrived at a conclusion: unconditional respect for diversity is an illusion that cannot exist.&lt;/p&gt;
&lt;p&gt;So is diversity always a bad thing? Of course not. Diversity clearly has both light and shadow.&lt;/p&gt;
&lt;h2 id=&quot;the-light-and-shadow-of-diversity&quot; style=&quot;position:relative;&quot;&gt;The light and shadow of diversity&lt;a href=&quot;#the-light-and-shadow-of-diversity&quot; aria-label=&quot;the light and shadow of diversity permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The positive effects of diversity are real. When team members with varied backgrounds come together, new ideas emerge and more approaches to problem-solving open up. Working in a frontend organization of about 100 people, I’ve met an incredible variety of developers and collaborated closely with non-developer colleagues. Through this, I’ve felt the synergy created when talented, diverse people come together.&lt;/p&gt;
&lt;p&gt;But diversity doesn’t always produce positive outcomes. As differences in opinion grow, the time and energy required for coordination increase exponentially, and team cohesion can weaken in the process. As Buddhist dependent origination teaches, because all phenomena are interdependent, a change in one element can have unexpected effects on the entire system.&lt;/p&gt;
&lt;p&gt;Understanding this dual nature of diversity allowed me to look at the team member I mentioned earlier from a new angle.&lt;/p&gt;
&lt;h2 id=&quot;anattā-non-self-and-the-possibility-of-change&quot; style=&quot;position:relative;&quot;&gt;Anattā (non-self) and the possibility of change&lt;a href=&quot;#anatt%C4%81-non-self-and-the-possibility-of-change&quot; aria-label=&quot;anattā non self and the possibility of change permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Reflecting more deeply on this team member, I was reminded of the Buddhist concept of anattā — non-self. Individual diversity is not a fixed, unchanging attribute; it shifts constantly. Just because that team member doesn’t want to grow right now doesn’t mean they never will.&lt;/p&gt;
&lt;p&gt;As a leader, I’ve always tried to present higher-level goals to my team members. This wasn’t merely about driving performance — it came from a genuine desire to draw out each person’s potential and help them grow as professionals. But through this process, I reached a conclusion: growth cannot be forced. You can propose growth, but the final decision and responsibility belong to the individual.&lt;/p&gt;
&lt;p&gt;Ultimately, I realized that what’s needed is the wisdom to respect someone’s choice in the present moment while keeping the door open for change and waiting patiently.&lt;/p&gt;
&lt;p&gt;But simply waiting isn’t the answer either. As a leader, I also needed concrete principles for how to communicate and act.&lt;/p&gt;
&lt;h2 id=&quot;wisdom-from-the-noble-eightfold-path-right-communication&quot; style=&quot;position:relative;&quot;&gt;Wisdom from the Noble Eightfold Path: right communication&lt;a href=&quot;#wisdom-from-the-noble-eightfold-path-right-communication&quot; aria-label=&quot;wisdom from the noble eightfold path right communication permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What helped me here was the Buddhist Noble Eightfold Path — the eight practices the Buddha prescribed as the path to enlightenment.&lt;/p&gt;
&lt;p&gt;Among these, Right Speech and Right Action clearly illustrate the principles a leader should follow when communicating with team members.&lt;/p&gt;
&lt;p&gt;Right Speech means avoiding lies, divisive talk, harsh words, and idle chatter, and instead speaking truthfully and helpfully. Right Action means behaving in ways that don’t harm yourself or others.&lt;/p&gt;
&lt;p&gt;When proposing growth, it’s crucial to use truthful, constructive language rather than criticism or coercion, and to act in ways that benefit both the individual and the organization. The key isn’t pushing some abstract goal of “getting better” — it’s concretely showing what that growth means and what positive impact it can have.&lt;/p&gt;
&lt;p&gt;But when you try to put these principles into practice, you inevitably face another complex problem: how to balance your own values as a leader with your team members’ diverse perspectives.&lt;/p&gt;
&lt;h2 id=&quot;leadership-through-compassion-and-skillful-means&quot; style=&quot;position:relative;&quot;&gt;Leadership through compassion and skillful means&lt;a href=&quot;#leadership-through-compassion-and-skillful-means&quot; aria-label=&quot;leadership through compassion and skillful means permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This dilemma resembles the clash of political ideologies. Progressive and conservative — each has its own strengths and weaknesses. It’s not a matter of right versus wrong, but a difference in which direction to pursue. The same goes for organizational culture. Even if I hold certain beliefs and values as a leader, is it justified to impose them on my team? Yet if I allow total freedom in everything, the organization may descend into chaos.&lt;/p&gt;
&lt;p&gt;In Buddhism, compassion (karuṇā) isn’t mere sympathy. It’s genuinely helping others find true well-being. I believe my desire for my team members’ growth is an expression of this same compassion. And through the wisdom of skillful means (upāya), different approaches should be used for each person based on their situation and disposition.&lt;/p&gt;
&lt;p&gt;Rather than applying the same yardstick to everyone, it’s about understanding individual contexts and finding the appropriate method for each.&lt;/p&gt;
&lt;p&gt;As I examined these various Buddhist principles, I realized they all converge on a single core idea: balance.&lt;/p&gt;
&lt;h2 id=&quot;the-middle-way&quot; style=&quot;position:relative;&quot;&gt;The Middle Way&lt;a href=&quot;#the-middle-way&quot; aria-label=&quot;the middle way permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the end, just as respecting diversity matters, so does maintaining certain standards and order to achieve organizational goals.&lt;/p&gt;
&lt;p&gt;So how do you strike this balance? One conclusion I’ve reached from running my team is that “not all diversity must be unconditionally respected.” This doesn’t mean diversity should be restricted — it means diversity should be channeled in a direction consistent with the organization’s fundamental purpose.&lt;/p&gt;
&lt;p&gt;As a leader, I strive to provide a safe environment where team members’ diversity is respected, while also setting clear standards and guidelines for effective collaboration. From a Buddhist perspective, a leader is both someone who supports team members in growing at their own pace and in their own way, and someone who sets direction and guides them toward it.&lt;/p&gt;
&lt;p&gt;Balancing these two roles isn’t easy, but I think it’s the Middle Way that yields the best results for both the organization and the individual.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Diversity is an essential ingredient for organizational growth. But it’s the leader’s job to ensure it doesn’t breed conflict and inefficiency. I’ll keep thinking about how to set the right standards while respecting my team’s diversity.&lt;/p&gt;
&lt;p&gt;As the Buddha taught: “Don’t follow the mind, teach the mind.” I want to keep that in mind as I navigate between individual diversity and organizational objectives.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[무조건적 다양성 존중은 허상이다: 연기법(緣起法)으로 본 조직 운영의 지혜]]></title><description><![CDATA[현대 조직에서 ‘다양성’은 거의 신성불가침의 가치로 여겨진다. 다양한 배경을 가진 사람들이 모여 시너지를 만들어내고, 서로 다른 관점이 혁신을 이끌어낸다는 믿음은 이제 상식이 되었다. 특히 IT 업계에서는 다양성과 포용성(Diversity…]]></description><link>https://evan-moon.github.io/2025/07/06/diversity-illusion-leadership/</link><guid isPermaLink="false">20250706-diversity-illusion-leadership</guid><pubDate>Sun, 06 Jul 2025 07:09:54 GMT</pubDate><content:encoded>&lt;p&gt;현대 조직에서 ‘다양성’은 거의 신성불가침의 가치로 여겨진다. 다양한 배경을 가진 사람들이 모여 시너지를 만들어내고, 서로 다른 관점이 혁신을 이끌어낸다는 믿음은 이제 상식이 되었다. 특히 IT 업계에서는 다양성과 포용성(Diversity &amp;#x26; Inclusion)이 조직 문화의 핵심 키워드로 자리잡았다.&lt;/p&gt;
&lt;p&gt;하지만 현실에서 리더로 일하다 보면, 이런 이상적인 원칙들이 생각보다 복잡한 딜레마를 만들어낸다는 것을 깨닫게 된다. 과연 모든 종류의 다양성을 무조건 존중해야 하는 것일까? 개인의 선택과 조직의 목표가 충돌할 때, 리더는 어떤 기준으로 판단해야 할까?&lt;/p&gt;
&lt;p&gt;이번 글에서는 필자가 100명 규모의 프론트엔드 조직에서 챕터 리드로 일을 하면서 마주한 구체적인 딜레마를 통해, 다양성 존중의 한계와 그 속에서 찾은 지혜에 대한 이야기를 해보려고 한다.&lt;/p&gt;
&lt;p&gt;그리고 이 과정에서 불교 철학, 특히 연기법과 중도 사상이 어떻게 현대 조직 운영에 실질적인 통찰을 제공할 수 있는지 살펴볼 것이다.&lt;/p&gt;
&lt;h2 id=&quot;딜레마의-시작&quot; style=&quot;position:relative;&quot;&gt;딜레마의 시작&lt;a href=&quot;#%EB%94%9C%EB%A0%88%EB%A7%88%EC%9D%98-%EC%8B%9C%EC%9E%91&quot; aria-label=&quot;딜레마의 시작 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;리더로서 탁월한 조직을 만들기 위해서는 구성원들의 성장을 지원하고 독려해야하지만 100명이나 되는 사람이 모여있다 보니 구성원들 중에서 생각이 다른 사람도 있을 수밖에 없다.&lt;/p&gt;
&lt;p&gt;최근 필자를 깊은 고민에 빠뜨린 팀원이 있었다. 그 분은 기술적으로 출중한 역량을 가지고 있었고, 현재 맡은 업무를 완벽하게 수행했으며, 동료들로부터도 신뢰를 받는 사람이었다. 그래서 필자가 볼 때는 리드를 하면 딱 좋을 것 같은데 이러한 추가적인 역할은 거부했다.&lt;/p&gt;
&lt;p&gt;필자가 성장을 위한 새로운 도전을 제안하면 그 분은 담담하게 이렇게 답했다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“지금은 딱히 생각이 없어요.”&lt;/p&gt;
&lt;p&gt;“다른 것에 집중하고 싶어서요.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;만약 그 분이 역량이 부족하면서 성장도 하지 않는다면 명확히 문제가 되겠지만, 이미 잘하고 있는 사람이라서 더욱 애매했다.&lt;/p&gt;
&lt;p&gt;이 경험은 필자에게 근본적인 질문들을 던졌다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“충분히 잘 하고 있는 사람에게 더 높은 목표를 제시하는 것이 과연 옳은가?”&lt;/p&gt;
&lt;p&gt;그리고 “개인의 다양성과 선택을 존중해야 한다는 원칙은 어디까지 적용되어야 하는가?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;독자 여러분도 비슷한 고민을 해본 적이 있을 것이다. 이런 딜레마 앞에서 우리는 흔히 두 가지 극단적인 선택지 사이에서 헤매게 된다. 하나는 “다양성을 무조건 존중해야 한다”는 입장이고, 다른 하나는 “조직의 목표를 위해서는 통일성이 필요하다”는 입장이다.&lt;/p&gt;
&lt;p&gt;이 경험을 통해 필자는 이런 극단적 선택지를 넘어서는 새로운 관점이 필요하다는 것을 깨달았다. 그 팀원의 상황을 더 깊이 들여다보면서, 다양성이라는 개념 자체를 보다 세밀하게 살펴볼 필요가 있다는 생각이 들었다. 과연 우리가 흔히 당연하게 여기는 다양성 존중이라는 개념에는 어떤 함정이 숨어있을까?&lt;/p&gt;
&lt;h2 id=&quot;다양성-존중의-함정&quot; style=&quot;position:relative;&quot;&gt;다양성 존중의 함정&lt;a href=&quot;#%EB%8B%A4%EC%96%91%EC%84%B1-%EC%A1%B4%EC%A4%91%EC%9D%98-%ED%95%A8%EC%A0%95&quot; aria-label=&quot;다양성 존중의 함정 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이 문제를 깊이 들여다보면서, 필자는 다양성이라는 개념이 흔히 이분법적으로 접근되는 경우가 많다는 것을 깨달았다. 즉, 다양성을 존중하는 것과 하지 않는 것으로 단순히 나누려는 시각이 존재한다는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 현실은 그렇게 단순하지 않으며, 다양성을 존중해야 한다는 것은 절대적인 원칙이 아니라 조직이나 사회의 특성에 따라 어느 정도까지 포용할 수 있는가의 문제로 접근해야 한다.&lt;/p&gt;
&lt;p&gt;이는 불교의 연기법(緣起法)이 보여주는 진리와 맞닿아 있다. 모든 현상은 서로 의존하며 존재하기 때문에, 절대적인 자유나 절대적인 통제 모두 불가능하다는 것이다. &lt;small&gt;(뜬금없이 불교 얘기를 해서 당황스럽겠지만, 의외로 불교에서 말하는 에피소드들이 삶의 지혜를 많이 알려준다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;대한민국의 헌법을 예로 들어보자. 대한민국은 국민의 자유를 보장하는 민주주의 국가이지만, 헌법 제8조에서는 특정 조건에 따라 위헌 정당을 해산할 수 있도록 하고 있다. 이는 민주적 기본 질서를 위협하는 요소가 있을 경우, 자유를 무제한으로 허용할 수 없다는 것을 의미한다. 즉, 국가조차도 모든 다양성을 무조건적으로 존중하지는 않는다는 것이다.&lt;/p&gt;
&lt;p&gt;이와 같은 원리는 조직에도 동일하게 적용된다. 예를 들어, 회사가 다양성을 존중해야 한다는 이유만으로 정해진 근무 시간을 지키지 않거나, 업무 태도가 성실하지 않음에도 불구하고 재택근무만을 주장하는 직원까지 포용해야 할까? 다양성은 존중받아야 하지만, 그것이 조직의 운영과 목표에 부합하지 않을 때는 결국 제한될 수밖에 없다.&lt;/p&gt;
&lt;p&gt;이러한 관찰을 통해 필자는 무조건적인 다양성 존중이라는 것은 존재할 수 없는 허상이라는 결론에 도달했다.&lt;/p&gt;
&lt;p&gt;그렇다면 다양성은 정말 무조건 나쁜 것일까? 물론 그런 것은 아니다. 다양성에는 분명히 빛과 그림자가 공존한다.&lt;/p&gt;
&lt;h2 id=&quot;다양성의-빛과-그림자&quot; style=&quot;position:relative;&quot;&gt;다양성의 빛과 그림자&lt;a href=&quot;#%EB%8B%A4%EC%96%91%EC%84%B1%EC%9D%98-%EB%B9%9B%EA%B3%BC-%EA%B7%B8%EB%A6%BC%EC%9E%90&quot; aria-label=&quot;다양성의 빛과 그림자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;물론 다양성이 우리에게 선물해주는 긍정적인 효과는 분명하다. 다양한 배경과 사고 방식을 가진 팀원들이 모였을 때, 새로운 아이디어가 탄생하고, 문제를 해결하는 데 있어 더 많은 접근법을 시도할 수 있다는 것이다. 필자가 100명 규모의 프론트엔드 조직에서 일하면서 평소 굉장히 다양한 개발자들을 만나고, 개발자가 아닌 동료들과도 밀접한 협업을 수행하는 과정에서 탁월한 역량을 가진 다양한 사람들이 모여 만들어내는 시너지를 느낄 수 있었다.&lt;/p&gt;
&lt;p&gt;하지만 이러한 다양성이 항상 긍정적인 결과만을 가져오는 것은 아니다. 의견 차이가 커질수록 조율에 드는 시간과 에너지가 기하급수적으로 증가하며, 이 과정에서 팀의 결속력이 약해지기도 한다. 이는 불교의 연기법이 보여주는 바와 같이, 모든 현상이 상호의존적이기 때문에 한 요소의 변화가 전체 시스템에 예상치 못한 영향을 미칠 수 있음을 의미한다.&lt;/p&gt;
&lt;p&gt;다양성의 이런 양면성을 이해하고 나니, 앞서 언급한 팀원에 대한 고민도 새로운 시각에서 바라볼 수 있게 되었다.&lt;/p&gt;
&lt;h2 id=&quot;무아無我와-성장의-변화-가능성&quot; style=&quot;position:relative;&quot;&gt;무아(無我)와 성장의 변화 가능성&lt;a href=&quot;#%EB%AC%B4%EC%95%84%E7%84%A1%E6%88%91%EC%99%80-%EC%84%B1%EC%9E%A5%EC%9D%98-%EB%B3%80%ED%99%94-%EA%B0%80%EB%8A%A5%EC%84%B1&quot; aria-label=&quot;무아無我와 성장의 변화 가능성 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 언급한 팀원에 대한 고민을 더 깊이 생각해보면서, 필자는 불교의 무아(無我) 사상을 떠올리게 되었다. 개인의 다양성이라는 것도 고정불변한 속성이 아니라 끊임없이 변화하는 것이다. 그 팀원이 현재 성장을 원하지 않는다고 해서 미래에도 그럴 것이라고 단정할 수는 없다.&lt;/p&gt;
&lt;p&gt;필자는 리더로서 항상 팀원들에게 더 높은 수준의 목표를 제시하려고 노력해왔다. 이는 단순히 성과를 내기 위한 것이 아니라, 각자가 가진 잠재력을 최대한 끌어내어 프로페셔널로서 더 성장하길 바라는 마음에서였다. 그러나 이 과정에서 “성장은 강요될 수 없는 것”이라는 결론에 도달했다. 성장을 제안할 수는 있지만, 그 선택의 최종 결정과 책임은 개인의 몫이라는 점을 깨달았다.&lt;/p&gt;
&lt;p&gt;결국 필자는 이 순간의 선택을 존중하면서도, 변화의 가능성을 열어두고 인내심을 갖고 기다리는 지혜가 필요하다는 것을 깨달았다.&lt;/p&gt;
&lt;p&gt;하지만 단순히 기다리기만 하는 것이 능사는 아니다. 리더로서 어떻게 소통하고 행동해야 하는지에 대한 구체적인 원칙도 필요했다.&lt;/p&gt;
&lt;h2 id=&quot;팔정도八正道의-지혜-올바른-소통&quot; style=&quot;position:relative;&quot;&gt;팔정도(八正道)의 지혜: 올바른 소통&lt;a href=&quot;#%ED%8C%94%EC%A0%95%EB%8F%84%E5%85%AB%E6%AD%A3%E9%81%93%EC%9D%98-%EC%A7%80%ED%98%9C-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%86%8C%ED%86%B5&quot; aria-label=&quot;팔정도八正道의 지혜 올바른 소통 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이때 필자에게 도움이 된 것은 불교의 팔정도(八正道) 사상이었다. 팔정도는 부처가 제시한 여덟 가지 올바른 수행 방법으로, 깨달음에 이르는 길을 구체적으로 제시한 것이다.&lt;/p&gt;
&lt;p&gt;이 중에서도 정어(正語)와 정업(正業)은 리더가 팀원과 소통할 때 지켜야 할 원칙을 명확하게 보여준다.&lt;/p&gt;
&lt;p&gt;정어(正語)는 “올바른 말”을 의미한다. 거짓말, 이간질, 욕설, 쓸데없는 말을 하지 않고, 진실하고 도움이 되는 말을 해야 한다는 것이다. 정업(正業)은 “올바른 행동”으로, 자신과 타인에게 해가 되지 않는 행동을 하라는 가르침이다.&lt;/p&gt;
&lt;p&gt;성장을 제안할 때는 비난이나 강요가 아닌 진실하고 건설적인 언어를 사용해야 하며, 개인과 조직 모두에게 도움이 되는 방향으로 행동해야 한다는 점이 중요하다. 단순히 더 나아져야 한다는 추상적인 목표가 아니라, 그 성장이 어떤 의미를 가지며 어떤 긍정적 영향을 줄 수 있는지 구체적으로 보여주는 것이 핵심이다.&lt;/p&gt;
&lt;p&gt;그런데 이런 원칙들을 실천하려고 하다 보면, 또 다른 복잡한 문제에 직면하게 된다. 바로 리더 자신의 가치관과 팀원들의 다양한 생각 사이에서 어떤 균형을 잡아야 하는가의 문제다.&lt;/p&gt;
&lt;h2 id=&quot;자비慈悲와-방편方便의-리더십&quot; style=&quot;position:relative;&quot;&gt;자비(慈悲)와 방편(方便)의 리더십&lt;a href=&quot;#%EC%9E%90%EB%B9%84%E6%85%88%E6%82%B2%EC%99%80-%EB%B0%A9%ED%8E%B8%E6%96%B9%E4%BE%BF%EC%9D%98-%EB%A6%AC%EB%8D%94%EC%8B%AD&quot; aria-label=&quot;자비慈悲와 방편方便의 리더십 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이러한 고민은 정치적 이데올로기의 충돌과도 비슷하다. 진보와 보수, 각각의 이념적 차이는 고유한 강점과 약점을 가지고 있으며, 옳고 그름의 문제라기보다는 어떤 방향성을 추구하느냐의 차이일 뿐이다. 조직 문화도 마찬가지다. 리더로서 필자가 가진 신념과 가치가 있다고 해도 그것을 구성원들에게 강요하는 것이 과연 정당한가? 하지만 모든 것에 대한 자유를 허용하면 조직은 혼란스러워질 수 있다.&lt;/p&gt;
&lt;p&gt;불교에서 말하는 자비(慈悲)는 단순한 동정이 아니라 상대방이 진정으로 행복해지도록 돕는 것이다. 필자가 팀원들의 성장을 바라는 마음도 이와 같은 자비심의 발현이라고 생각한다. 그리고 방편(方便)의 지혜를 통해, 각 개인의 상황과 성향에 맞는 다른 접근법을 사용하는 것이 필요하다.&lt;/p&gt;
&lt;p&gt;모든 사람에게 동일한 잣대를 적용하는 것이 아니라, 개별적인 맥락을 이해하고 그에 맞는 방법을 찾아가는 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 여러 불교적 원칙들을 살펴보면서, 필자는 결국 이 모든 것이 하나의 핵심으로 수렴된다는 것을 깨달았다. 바로 “균형”이다.&lt;/p&gt;
&lt;h2 id=&quot;중도中道의-균형&quot; style=&quot;position:relative;&quot;&gt;중도(中道)의 균형&lt;a href=&quot;#%EC%A4%91%EB%8F%84%E4%B8%AD%E9%81%93%EC%9D%98-%EA%B7%A0%ED%98%95&quot; aria-label=&quot;중도中道의 균형 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;결국 다양성을 존중하는 것이 중요한 만큼, 조직의 목표와 성과를 달성하기 위해 일정 수준의 기준과 질서도 필요하다.&lt;/p&gt;
&lt;p&gt;그렇다면 이 균형은 어떻게 잡아야 할까? 필자가 팀을 운영하며 내린 한 가지 결론은 “모든 다양성이 무조건 존중받아야 하는 것은 아니다”라는 것이다. 이 말은 다양성을 제한해야 한다는 뜻이 아니라, 조직의 본질적인 목적과 일치하는 방향에서 다양성이 활용되어야 한다는 의미다.&lt;/p&gt;
&lt;p&gt;리더로서, 필자는 팀원들에게 다양성을 존중받을 수 있는 안전한 환경을 제공하는 동시에, 협업의 효율성을 위해 명확한 기준과 가이드를 제시하려고 노력한다. 불교의 관점에서 보면, 리더는 팀원들이 각자의 속도와 방식대로 성장하도록 지원하는 존재이기도 하며, 방향성을 제시하고 그것을 따라가도록 이끄는 존재이기도 하다.&lt;/p&gt;
&lt;p&gt;이 두 가지 역할 간의 균형을 맞추는 것은 쉽지 않지만, 조직과 개인 모두에게 최선의 결과를 낼 수 있는 중도의 길이라고 생각한다. 마치 부처가 극단적 쾌락주의와 극단적 고행주의 사이에서 중도를 찾았듯이, 리더는 무조건적 다양성 존중과 일방적 통제 사이에서 균형점을 찾아야 한다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;다양성은 조직의 성장과 혁신을 위한 필수 요소다. 그러나 그것이 갈등과 비효율을 초래하지 않도록 균형을 잡는 것은 리더의 몫이다. 필자는 앞으로도 팀의 다양성을 존중하면서, 조직의 목표를 달성하기 위해 어떤 기준을 세워야 할지에 대해 꾸준히 고민할 것이다. 그리고 이 여정에서 얻은 통찰을 계속 나누고자 한다.&lt;/p&gt;
&lt;p&gt;마치 부처가 가르친 것처럼, “마음을 따르지 말고 마음을 가르치라”는 지혜를 기억하며, 개인의 다양성과 조직의 목표 사이에서 지혜로운 선택을 계속해 나가고 싶다. 이것이 바로 현대 조직에서 필요한 불교적 리더십의 핵심이 아닐까 생각한다.&lt;/p&gt;
&lt;p&gt;이상으로 연기법으로 본 조직 운영의 지혜 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 11. 선언적 프로그래밍]]></title><description><![CDATA[필자는 이 책의 첫 번째 파트에서 카테고리 이론과 프로그래밍이 모두 합성 가능성(Composability)에 대한 것이라는 주장을 하였다. 프로그래밍에서는 문제를 조금씩 세분화해나가며 다룰 수 있는 세부 수준으로 분해한 다음, 각 하위 문제를 해결하고, 하위 문제의 해결책들을 다시 합성하여 전체 문제를 해결하는 방식을 사용한다.]]></description><link>https://evan-moon.github.io/2024/12/25/category-theory-for-programmers-11-declarative-programming/</link><guid isPermaLink="false">20241225-category-theory-for-programmers-11-declarative-programming</guid><pubDate>Wed, 25 Dec 2024 07:45:20 GMT</pubDate><content:encoded>&lt;p&gt;필자는 이 책의 첫 번째 파트에서 카테고리 이론과 프로그래밍이 모두 합성 가능성(Composability)에 대한 것이라는 주장을 하였다.&lt;/p&gt;
&lt;p&gt;프로그래밍에서는 문제를 조금씩 세분화해나가며 다룰 수 있는 세부 수준으로 분해한 다음, 각 하위 문제를 해결하고, 하위 문제의 해결책들을 다시 합성하여 전체 문제를 해결하는 방식을 사용한다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;이를 수행하는 방법에는 크게두 가지 정도가 있다. 하나는 컴퓨터에게 무엇을 해야 하는지 알려주는 방법, 그리고 다른 하나는 어떻게 해야 하는 지를 알려주는 방법이다. 이때 전자는 선언형(Declarative), 후자는 명령형(Imperative)이라고 한다.&lt;/p&gt;
&lt;p&gt;이 두 가지 방법의 차이는 가장 기본적인 수준에서도 확인이 가능하다. 먼저 선언적으로 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;를 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 실행된 이후 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;를 적용한 합성이라고 정의해보면 이렇게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;혹은 명령적으로 정의해볼 수도 있다. 즉, 먼저 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 호출하고 그 호출의 결과를 기억한 뒤, 그 결과를 사용해서 다시 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;를 호출하는 것이다.&lt;/p&gt;
&lt;p&gt;명령형 방식의 프로그램은 일반적으로 시간 순서대로 정렬된 일련의 작업들로 표현된다. 특히 이 방식에서는 명시적으로 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;의 호출이 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;의 실행이 완료되기 전에는 절대 발생할 수 없음이 표현된다. 그러나 지연 평가(lazy evaluation)와 call-by-need 방식의 인수 전달을 사용하는 언어에서는 실제 실행 순서가 다를 수 있다.&lt;/p&gt;
&lt;p&gt;사실, 컴파일러의 최적화 수준에 따라 선언적 코드와 명령적 코드의 실행 방식에는 거의 차이가 없을 수도 있다. 하지만 이 두 가지 방법론은 때로 문제 해결 접근 방식과 결과 코드의 유지보수성 및 테스트 가능성에서 극명하게 다르다.&lt;/p&gt;
&lt;p&gt;여기서 중요한 질문은 “우리가 문제를 풀 때 항상 선언적인 접근 방식과 명령적인 접근 방식 중 하나를 선택할 수 있는가? 그리고 만약 선언적인 해결책이 있다면 항상 컴퓨터 코드로 변환할 수 있는 것인가?”이다. 사실 이 질문에 대한 답은 아직 명확하게 나오지 않았으며, 만약 그 답을 찾을 수 있다면 아마 우리 우주에 대한 이해를 혁신적으로 바꿀 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;설명을 덧붙이자면, 물리학에서도 이와 유사한 이중성이 존재한다. 이는 심오한 근본 원칙을 가리키거나, 우리의 사고방식에 대해 무언가를 말해주는 것일 수 있다. 리처드 파인만은 자신의 양자 전기역학 연구에서 이 이중성이 영감의 원천이 되었다고 언급한 바 있다.&lt;/p&gt;
&lt;p&gt;물리 법칙을 표현하는 데에는 두 가지 방식이 있다. 하나는 국소적(local) 또는 미소적(infinitesimal) 접근 방식을 사용하는 것이다. 이 접근 방식은 먼저 시스템의 작은 근방에서의 상태를 관찰하고, 다음 순간에 그것이 어떻게 변화할 지를 예측한다. 이러한 변화는 보통 미분 방정식을 사용하여 표현되며, 이를 일정 시간 동안 적분하거나 합산하여 최종 결과를 표현한다.&lt;/p&gt;
&lt;p&gt;이는 이전 단계의 결과에 의존하는 각각의 작은 단계들을 거쳐 최종 해결책에 도달하는 명령형 사고방식과 유사하다.&lt;/p&gt;
&lt;p&gt;실제로 물리적 시스템의 컴퓨터 시뮬레이션은 미분 방정식을 차분 방정식으로 변환하고 이를 반복 실행하는 방식으로 구현하는 경우가 많다. &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%95%84%EC%8A%A4%ED%85%8C%EB%A1%9C%EC%9D%B4%EC%A6%88_(%EB%B9%84%EB%94%94%EC%98%A4_%EA%B2%8C%EC%9E%84)&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Asteroids 게임&lt;/a&gt;에서 우주선이 애니메이션화 되는 방식도 이와 동일하다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/07e05bace0a500d1b2cd29c78efa839e/72799/1.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA/UlEQVR42oVTXQuDMAxMFT8q0spQdCD4KgiOuUf////abcEauzrzIKm95JJLSstr6e4dESml+MsGv6qqKIqMMUmS0GZ8NQzDuq40TVOe5wAVRYG/WZbBYQQca21d13Ec09HGcZwfMyEMB4C67sNvrHkuzzRNGQRO50tmRLFDfODa4OhCg3+/OzEf4Lo9JBaG+pumkRL4wRzpgqWvtW7b9lcCCvKgYVkCC/S3+s0g4e1rILwE+3eQDeQYmNekbCScMsighF3ggqVx25eDJKiFbiUOu4jF9NZmZ3N6wsfalWWJ3Xbx6L/ve6Q4nbMrDw8DaATLjIFpnc2Z38yZ1G+umgueGdC4iAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/07e05bace0a500d1b2cd29c78efa839e/72799/1.png&quot; srcset=&quot;/static/07e05bace0a500d1b2cd29c78efa839e/69538/1.png 160w,
/static/07e05bace0a500d1b2cd29c78efa839e/72799/1.png 320w&quot; sizes=&quot;(max-width: 320px) 100vw, 320px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;각 시간 단계마다 우주선의 위치는 속도와 시간 델타를 곱하여 계산된 작은 증분을 더해가면서 변경된다. 속도는 다시 가속도에 비례하는 작은 증분을 더해 변경되며, 가속도는 힘을 질량으로 나눈 값이다.&lt;/p&gt;
&lt;p&gt;이것은 사실 뉴턴의 운동 법칙에 해당하는 미분 방정식을 직접적으로 구현한 것이다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mspace linebreak=&quot;newline&quot;&gt;&lt;/mspace&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F=m\frac{dv}{dt}\\
v=\frac{dx}{dt}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:2.0574em;vertical-align:-0.686em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.3714em;&quot;&gt;&lt;span style=&quot;top:-2.314em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.677em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.686em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace newline&quot;&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:2.0574em;vertical-align:-0.686em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.3714em;&quot;&gt;&lt;span style=&quot;top:-2.314em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.677em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.686em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;이외에도 맥스웰 방정식을 사용하여 전자기장의 전파를 분석하거나, 격자 양자색역학(lattice QCD)을 사용하여 양성자 내부에서 쿼크와 글루온의 행동을 설명하는 등 더 복잡한 문제에도 국소적 사고방식이 적용될 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 국소적 사고방식은 디지털 컴퓨터를 사용하여 공간과 시간을 이산화(discretization)하는 시도와 결합되어, 우주의 모든 복잡성을 간단한 셀룰러 오토마타 시스템으로 축소하려는 스티븐 울프람(Stephen Wolfram)과 같은 영웅이 등장하기도 했다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;셀룰러 오토마타는 격자 내부에 위치한 여러 개의 셀들이 간단한 규칙에 따라 유한 개의 상태로 변화할 수 있는 시스템이다. 대표적인 셀룰러 오토마타 중 하나로는 &lt;a href=&quot;https://namu.wiki/w/%EC%BD%98%EC%9B%A8%EC%9D%B4%EC%9D%98%20%EC%83%9D%EB%AA%85%20%EA%B2%8C%EC%9E%84&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;콘웨이의 생명 게임&lt;/a&gt;이 있으며, 이러한 시스템은 간단한 규칙이 생명과 같은 복잡한 패턴을 표현할 수 있음을 보여준다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;다른 접근법은 전역적(global) 접근 방법이다. 시스템의 초기 상태와 최종 상태를 확인한 뒤, 에너지, 시간, 거리와 같은 물리량을 최소한으로 사용하여 이 상태들을 연결할 수 있는 최적의 경로를 계산한다. 가장 간단한 예는 &lt;strong&gt;페르마의 최소 시간 원리&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;이 원리는 빛이 비행 시간을 최소화하는 경로를 따라 전파된다는 것을 나타낸다. 그래서 반사나 굴절이 없는 경우, A 지점에서 B 지점으로 가는 빛은 가장 짧은 경로인 A와 B 사이의 직선 경로를 선택한다.&lt;/p&gt;
&lt;p&gt;그러나 빛은 물이나 유리와 같은 밀도가 높은 투명 물질에서는 속도가 느려진다. 따라서 빛의 시작 지점이 공기 중에 있고 도착 지점이 물속에 있을 경우, 빛이 공기 중에서 이동하는 거리보다 물 속에서 이동하는 거리가 더 짧아져야 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 477px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6eea0ab0c036ddfe049479e302fa185d/b18ba/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 134.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAe1DUprFFnNqWEHK/8QAGxABAAIDAQEAAAAAAAAAAAAAAQIRABAhAzH/2gAIAQEAAQUCZVkVk5PpGxvUuehbpBw+f//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABoQAAICAwAAAAAAAAAAAAAAABEgACEQMVH/2gAIAQEABj8C1aCsmcT/xAAdEAEAAgICAwAAAAAAAAAAAAABABEhcRBRMUFh/9oACAEBAAE/IXsaI5XB6ODhKvceG0OpTslS+RgJWtX448gXBQCf/9oADAMBAAIAAwAAABCcwIz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAWEQEBAQAAAAAAAAAAAAAAAAAQASH/2gAIAQIBAT8QLp//xAAgEAEBAAEEAQUAAAAAAAAAAAABEQAhMUFREHGRscHx/9oACAEBAAE/EB7UajhO8sUJu/Pv4B7ONid4ZQXdIHY74z9bEWwvpiFr7BHTv6w39VgDQ8KUkCFwCEAgZ//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/6eea0ab0c036ddfe049479e302fa185d/b18ba/2.jpg&quot; srcset=&quot;/static/6eea0ab0c036ddfe049479e302fa185d/0913d/2.jpg 160w,
/static/6eea0ab0c036ddfe049479e302fa185d/cb69c/2.jpg 320w,
/static/6eea0ab0c036ddfe049479e302fa185d/b18ba/2.jpg 477w&quot; sizes=&quot;(max-width: 477px) 100vw, 477px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;최소 시간을 따르는 경로는 빛이 공기와 물의 경계에서 굴절되도록 하며, 이는 스넬의 굴절 법칙(Snell’s Law of Refraction)으로 이어진다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;sin&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;θ&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;sin&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;θ&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{\sin(\theta_1)}{\sin(\theta_2)} = \frac{v_1}{v_2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:2.363em;vertical-align:-0.936em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.427em;&quot;&gt;&lt;span style=&quot;top:-2.314em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mop&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;θ&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.677em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mop&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;θ&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.936em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.9436em;vertical-align:-0.836em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.1076em;&quot;&gt;&lt;span style=&quot;top:-2.314em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.677em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.836em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;v_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 공기 중에서의 빛의 속도이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;v_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 물속에서의 빛의 속도이다.&lt;/p&gt;
&lt;p&gt;고전 역학의 모든 법칙은 최소 작용 원리로부터 도출될 수 있다. 작용은 라그랑지안(Lagrangian)을 경로에 따라 적분하여 계산할 수 있으며, 라그랑지안은 운동 에너지와 위치 에너지의 차이를 나타낸다 (참고로 합(sum)이 아니라 차이(difference)다. 합은 총 에너지를 나타낸다).&lt;/p&gt;
&lt;p&gt;우리가 특정 목표를 맞추기 위해 박격포를 발사하면, 포탄은 먼저 중력으로 인해 위치 에너지가 더 높은 곳으로 올라가고, 그 과정 속에서 점점 작용에 음의 기여를 축적한다. 그 후 포탄은 포물선의 꼭대기에서 속도를 줄여 운동 에너지를 최소화하고, 최종적으로는 위치 에너지가 낮은 구간을 빠르게 통과하기 위해 속도를 높인다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3bcd91aec0bd17805bb6b69ae376b97c/c08c5/3.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 53.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe7OkFA//8QAGRABAAMBAQAAAAAAAAAAAAAAAQACERIx/9oACAEBAAEFAvZZ4B0lqloGT//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAABEBEhYf/aAAgBAQAGPwLhZajUYf/EABkQAQEBAAMAAAAAAAAAAAAAAAERABAxQf/aAAgBAQABPyE93BoqYC6Hg8LTAYIb/9oADAMBAAIAAwAAABBgz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABoQAQEBAAMBAAAAAAAAAAAAAAERABAxUWH/2gAIAQEAAT8QcwvEZfuumkJ21z0UKPAQiqDp2eBv/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3&quot; title=&quot;&quot; src=&quot;/static/3bcd91aec0bd17805bb6b69ae376b97c/c08c5/3.jpg&quot; srcset=&quot;/static/3bcd91aec0bd17805bb6b69ae376b97c/0913d/3.jpg 160w,
/static/3bcd91aec0bd17805bb6b69ae376b97c/cb69c/3.jpg 320w,
/static/3bcd91aec0bd17805bb6b69ae376b97c/c08c5/3.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;리처드 파인만의 주요 기여 중 한 가지는 최소 작용 원리가 양자역학으로 일반화될 수 있음을 보여준 것이다. 이 경우에도 문제는 초기 상태와 최종 상태로 구성되며, 두 상태 사이의 전이 확률을 계산하기 위해 파인만 경로 적분(Feynman path integral)이 사용된다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/58afbf9a618154e80664783c0512faf6/c08c5/4.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3JoWD//EABoQAAICAwAAAAAAAAAAAAAAAAABAhEQEiH/2gAIAQEAAQUCk6Nnhorh/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAQUAAAAAAAAAAAAAAAAAEAABIUGh/9oACAEBAAY/AlTmcH//xAAcEAEAAgIDAQAAAAAAAAAAAAABACERYTFBUXH/2gAIAQEAAT8hT4e3qbNRCi3MRc5NEvwHkHFz/9oADAMBAAIAAwAAABCwD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB4QAQACAgIDAQAAAAAAAAAAAAEAESFBMWFRcdHw/9oACAEBAAE/EExE4NC8vUqeQtC5f32FEsbZX1ByGPb3BsBtsElqWF3U/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;4&quot; title=&quot;&quot; src=&quot;/static/58afbf9a618154e80664783c0512faf6/c08c5/4.jpg&quot; srcset=&quot;/static/58afbf9a618154e80664783c0512faf6/0913d/4.jpg 160w,
/static/58afbf9a618154e80664783c0512faf6/cb69c/4.jpg 320w,
/static/58afbf9a618154e80664783c0512faf6/c08c5/4.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;중요한 점은 물리 법칙을 설명하는 방식에 우열을 가리기 어려운 이중성이 존재한다는 것이다. 우리는 하나의 물리적 결과를 설명할 때 작은 일들이 순차적인 여러 단계로 나누어져 발생하는 국소적인 관점을 사용할 수도 있고, 초기 조건과 최종 조건을 선언한 뒤 그 사이에 무슨 일이 있었는지를 설명하는 전역적인 관점을 사용할 수도 있다.&lt;/p&gt;
&lt;p&gt;전역적 접근법은 프로그래밍에서도 사용될 수 있다. 예를 들어 레이 트레이싱(ray tracing)을 구현할 때, 우리는 눈의 위치와 광원의 위치를 선언하고, 이들을 연결하는 광선의 경로를 계산한다. 이때 우리가 각 광선의 비행 시간을 명시적으로 최소화하지 않더라도, 스넬의 법칙(Snell’s law)과 반사의 기하학을 이용하여 동일한 효과를 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;국소적 접근법과 전역적 접근법의 가장 큰 차이점은 공간, 그리고 더 중요한 시간에 대한 처리 방식이다. 국소적 접근법은 “지금 이 순간”의 즉각적인 결과를 중시하지만, 전역적 접근법은 마치 미래가 이미 정해져 있는 것처럼 장기적이고 정적인 관점을 취하며, 우리가 영원한 우주의 속성을 분석하는 것과 같다.&lt;/p&gt;
&lt;p&gt;이 점이 가장 잘 드러나는 곳은 사용자 상호작용에 대한 함수형 반응형 프로그래밍(Functional Reactive Programming, FRP) 접근법이다. FRP는 모든 이벤트에 대해 개별 핸들러를 작성하고 이들이 공유되는 가변 상태에 접근하도록 만드는 대신, 이벤트를 무한 리스트로 간주하고 이 이벤트에 대해 반응하는 특정한 변환을 적용한다.&lt;/p&gt;
&lt;p&gt;이론적으로 미래에 발생할 모든 동작을 담은 무한 리스트는 프로그램의 입력 데이터로 사용할 수 있다. 사실 프로그램 관점에서는 𝜋의 숫자 리스트, 의사 난수(pseudo-random number) 리스트, 또는 컴퓨터 하드웨어를 통해 전달되는 마우스 위치 리스트나 큰 차이가 없다. 데이터의 출처가 뭐든 간에 결국 리스트의 n번째 항목을 가져오려면 먼저 𝑛 − 1개의 항목을 통과해야 한다는 사실은 동일하기 때문이다. 이러한 속성이 시간적 이벤트에 적용될 때 이를 인과성(causality)이라고 부른다.&lt;/p&gt;
&lt;p&gt;그렇다면 이것이 카테고리 이론과 어떤 관련이 있다는 것일까? 필자는 카테고리 이론이 전역적 접근법을 장려하고, 따라서 선언적 프로그래밍을 지원한다는 이야기를 하려고 한다.&lt;/p&gt;
&lt;p&gt;첫 번째로, 미적분학과 달리 카테고리 이론에는 거리(distance), 이웃(neighborhood), 시간(time)과 같은 개념이 없다. 우리가 다루는 것은 그저 추상적인 대상과 대상들 간의 추상적인 연결뿐이다. 만약 A에서 B로 여러 단계를 통해 이동할 수 있다면, 한 번에 도달할 수도 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 541px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7bf87462d30c7320a6e32b55dd90f97e/8af7b/5.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 81.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB71LIaCA//8QAGhABAAIDAQAAAAAAAAAAAAAAAQASAhEiMf/aAAgBAQABBQJdQy6jZaIHn//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAMAAwAAAAAAAAAAAAAAAAABEBJRof/aAAgBAQAGPwI5NIeM/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARIVExEP/aAAgBAQABPyEPU1WPtD4c9B3bY3Tru9iWyU8n/9oADAMBAAIAAwAAABBTz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAQACAgMBAAAAAAAAAAAAAAERIQBBMVGBEP/aAAgBAQABPxA0ZWxRitcQLkYlk138hN1Rs0V175kT2jaRHE8UYSTuWs//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;5&quot; title=&quot;&quot; src=&quot;/static/7bf87462d30c7320a6e32b55dd90f97e/8af7b/5.jpg&quot; srcset=&quot;/static/7bf87462d30c7320a6e32b55dd90f97e/0913d/5.jpg 160w,
/static/7bf87462d30c7320a6e32b55dd90f97e/cb69c/5.jpg 320w,
/static/7bf87462d30c7320a6e32b55dd90f97e/8af7b/5.jpg 541w&quot; sizes=&quot;(max-width: 541px) 100vw, 541px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;게다가 카테고리 이론의 주요 도구인 보편적 구성(universal construction)은 전역적 접근법의 정수이다. 우리는 이를 카테고리적 곱(categorical product)의 정의에서 확인했다. 이는 그저 해당 대상의 속성을 명시함하는 것만으로도 충분히 정의할 수 있었으며, 이는 매우 선언적인 접근이다. 곱은 두 투영(projection)을 갖춘 대상이며, 다른 대상들의 투영을 인수분해하는 특성을 최적화하는 가장 적합한 대상이다.&lt;/p&gt;
&lt;p&gt;이런 특성을 페르마의 최소 시간 원리 또는 최소 작용 원리와 비교해보면 꽤 유사하다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;반대로 카테고리적 곱을 전통적인 데카르트 곱의 정의와 비교해보자. 데카르트 곱은 훨씬 더 명령적인 접근을 보여주고 있다. 이 방법은 하나의 집합에서 원소를 선태갛고 다른 집합에서 또 다른 원소를 선택하여 최종적으로 곱의 원소를 생성하는 방법을 보여주고 있다.&lt;/p&gt;
&lt;p&gt;Haskell과 같은 프로그래밍 언어에서 곱 타입, 합 타입, 그리고 함수 타입은 보편적 구성을 통해 정의되는 것이 아니라 이미 내장되어있는 경우가 대부분이다. (물론 카테고리적 프로그래밍 언어를 만드려는 시도는 있었으며, &lt;a href=&quot;http://web.sfc.keio.ac.jp/~hagino/thesis.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;타츠야 하기노의 논문&lt;/a&gt;에 그 내용이 잘 나와있다.)&lt;/p&gt;
&lt;p&gt;하지만 프로그래밍 언어에 카테고리적인 정의가 직접적으로 사용되던 아니던, 결국 카테고리적 정의는 기존의 프로그래밍 구조를 정당화하고 새로운 구조를 만들어낼 수 있는 토대가 된다. 가장 중요한 점은 카테고리 이론이 컴퓨터 프로그램을 선언적인 수준에서 추론하기 위한 메타 언어를 제공한다는 것이다. 또한 문제를 코드로 구현하기 전에 명세에 대해 논리적으로 사고하는 것에도 많은 도움을 준다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[What Is Good Code? On the Illusion of Readability]]></title><description><![CDATA[Throughout life, we face countless problems. Just looking at the practical ones (education, careers, job changes, finances, growth), we encounter all kinds of missions. And when I talk to people about these things, I often hear them speak as if there’s a predetermined right answer, or at least wishing there were one.]]></description><link>https://evan-moon.github.io/2024/12/23/the-illusion-of-a-right-answer/en/</link><guid isPermaLink="false">20241223-the-illusion-of-a-right-answer-en</guid><pubDate>Mon, 23 Dec 2024 09:34:56 GMT</pubDate><content:encoded>&lt;p&gt;Throughout life, we face countless problems. Just looking at the practical ones (education, careers, job changes, finances, growth), we encounter all kinds of missions. And when I talk to people about these things, I often hear them speak as if there’s a predetermined right answer, or at least wishing there were one.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Sometimes it feels like society is the one enforcing these answers. “Get into a good university and life will work out.” “You need to own a home to be happy.” “You need to earn at least this much to be middle class.” Hearing all these conditions and benchmarks, I sometimes wonder: are the decisions I make truly my own, or am I just following standards that society has laid out for me?&lt;/p&gt;
&lt;p&gt;Students don’t study to explore and acquire knowledge. They study to match the answers that the majority proclaims as correct. This problem isn’t limited to schools. It shows up in private education and in all sorts of organizations that teach developers. At the end of the day, customers want right answers, so providing right answers is the business.&lt;/p&gt;
&lt;p&gt;These formulas for success that society offers have conditioned us. Most problems we encounter in reality are unstructured and have no single correct answer. Yet when we face a problem, we often fall into the illusion that a right answer must exist somewhere.&lt;/p&gt;
&lt;p&gt;This social conditioning runs deep in how we think, and developers like me are no exception. So in this post, I want to unpack a concern I’ve been carrying for a while.&lt;/p&gt;
&lt;h2 id=&quot;the-drive-to-find-the-right-answer&quot; style=&quot;position:relative;&quot;&gt;The drive to find the right answer&lt;a href=&quot;#the-drive-to-find-the-right-answer&quot; aria-label=&quot;the drive to find the right answer permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Developers are, by nature, a group accustomed to seeking correct answers. Given the nature of working with logic, we’re trained to make decisions that are logically sound and grounded in clear evidence.&lt;/p&gt;
&lt;p&gt;The “right answers” developers tend to champion usually revolve around code structure and relationships. It’s not uncommon to see someone adopt a monorepo without a clear reason, or introduce a global state management library or memoization without any particular context demanding it.&lt;/p&gt;
&lt;p&gt;But as I mentioned earlier, reality isn’t that simple. In most cases, what counts as “best” varies depending on context, circumstances, and who’s interpreting it.&lt;/p&gt;
&lt;h3 id=&quot;what-is-good-code-code-with-good-readability&quot; style=&quot;position:relative;&quot;&gt;“What is good code?” “Code with good readability.”&lt;a href=&quot;#what-is-good-code-code-with-good-readability&quot; aria-label=&quot;what is good code code with good readability permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve been conducting interviews since 2016, early in my career, and I’ve kept at it ever since. Having done this for so long, I’ve developed a few go-to questions.&lt;/p&gt;
&lt;p&gt;One of them is: “What is good code?” It’s a topic I’ve personally pondered for a long time, so I genuinely enjoy hearing different developers’ perspectives. But when I ask this question, most people answer: “Code with good readability.” With slight exaggeration, I’d say 99 out of 100 give this answer.&lt;/p&gt;
&lt;p&gt;Every time I hear it, I feel a subtle awkwardness, because readability is subjective and abstract. The same code can be called readable by one person and unreadable by another.&lt;/p&gt;
&lt;p&gt;Sure, there are elements that many people would agree make code more readable — writing in a familiar programming language rather than Egyptian hieroglyphs, for instance. But we all know that’s not the level of readability we’re actually talking about.&lt;/p&gt;
&lt;p&gt;Can there really be a technical quality that all ~26 million software developers worldwide would universally agree on? If it’s a value that not everyone can agree on, shouldn’t we question whether “readable code” even exists as a meaningful concept?&lt;/p&gt;
&lt;p&gt;With this in mind, when I follow up with “What makes code readable?”, the answers start to diverge. Some emphasize cohesion and coupling. Others point to clear, intuitive naming. Some talk about separation of concerns. In other words, rather than a definition that captures the full essence of readability, most people cite specific real-world examples: “When you do this, readability improves.”&lt;/p&gt;
&lt;p&gt;This means every developer has a different idea of what’s most important for achieving good readability . These varied answers reveal how subjective and context-dependent readability is. It’s like looking at the same painting where one person sees beauty and another can’t figure out what it’s trying to express.&lt;/p&gt;
&lt;p&gt;Yet many people answer “code with good readability” to the question of what good code is. As if the answer were predetermined.&lt;/p&gt;
&lt;h3 id=&quot;how-should-i-grow-as-a-developer&quot; style=&quot;position:relative;&quot;&gt;“How should I grow as a developer?”&lt;a href=&quot;#how-should-i-grow-as-a-developer&quot; aria-label=&quot;how should i grow as a developer permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This instinct isn’t limited to developers. It shows up in the big and small decisions we make in everyday life. I occasionally have 1-on-1s and mentoring sessions where I get to hear other developers’ concerns and offer guidance. And in these settings too, I’ve seen the same drive to find the right answer.&lt;/p&gt;
&lt;p&gt;The questions and concerns I typically hear go something like this:&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;How do I become a good developer?&lt;/li&gt;
&lt;li&gt;What skills should I build to get into company X?&lt;/li&gt;
&lt;li&gt;I want to have this kind of experience in the future. What should I do?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;I completely empathize with the motivation behind these questions. When you desperately want to achieve something but don’t know what steps to take, that frustration is something everyone has felt at some point.&lt;/p&gt;
&lt;p&gt;The people asking these questions are genuinely passionate about growth and sincerely want to get better. But the problem is that they approach goals like success or growth through overly standardized methods.&lt;/p&gt;
&lt;p&gt;As a result, I’ve often seen people follow generic “right answers” that don’t fit their own circumstances, goals, or capabilities, and end up pouring effort in the wrong direction. It’s like trying to force yourself into clothes that don’t fit.&lt;/p&gt;
&lt;p&gt;Between the lines, there’s also the idea that if you just put in enough effort, like the 10,000-hour rule, you’ll eventually achieve what you want. I disagree. Time and effort are extremely limited resources, so where you invest them matters enormously. &lt;small&gt;(If you invest 10,000 hours only to discover it contributed nothing to your growth, those 10,000 hours are gone forever.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;What matters is where you invest your time and energy. The problem is that while we believe we’ve chosen this direction ourselves, that choice is often the product of standards set by others or by society.&lt;/p&gt;
&lt;h2 id=&quot;truth-that-shifts-with-context-not-fixed-truth&quot; style=&quot;position:relative;&quot;&gt;Truth that shifts with context, not fixed truth&lt;a href=&quot;#truth-that-shifts-with-context-not-fixed-truth&quot; aria-label=&quot;truth that shifts with context not fixed truth permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s natural for humans to seek stability and certainty — we’re wired to be uncomfortable with uncertainty. So this kind of thinking isn’t unnatural at all. If anything, believing that there’s no right answer might be the act that goes against human instinct.&lt;/p&gt;
&lt;p&gt;That’s why in the examples of readability and growth I mentioned earlier, many people who were eager to become great developers likely absorbed information from blogs, books, or fellow developers without critical examination. But we shouldn’t overlook the fact that problems like readability and growth simply don’t have predetermined right answers.&lt;/p&gt;
&lt;p&gt;In philosophy, concepts like relativism and contextualism are used to explore these kinds of problems.&lt;/p&gt;
&lt;p&gt;Relativism holds that truth and value aren’t universal. They vary depending on culture, perspective, and circumstances. This means that standards for readability can also differ based on an individual’s criteria or the situation they’re in.&lt;/p&gt;
&lt;p&gt;Contextualism means that whether a proposition is true depends on the context in which it’s used.&lt;/p&gt;
&lt;p&gt;For example, the same code might be evaluated differently depending on team culture, the nature of the project, or the business situation.&lt;/p&gt;
&lt;p&gt;Many people proclaim “code with good readability” as if it’s the definitive answer to what good code is. But this isn’t a fixed truth. It’s a relative concept that shifts across different contexts.&lt;/p&gt;
&lt;p&gt;Of course, since many people treat interviews as a game of guessing the interviewer’s expected answer, some bias may have crept in. But I’ve seen similar responses not just in interviews but also in mentoring sessions and 1-on-1s, so I don’t think the bias is significant. &lt;small&gt;(If you grab any 10 developers around you right now and ask “What do you think good code is?”, readability will almost certainly come up.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;We use programming languages, abstractions built from symbols familiar to humans, rather than machine code precisely because we want humans to easily understand how computers work. So if we could truly achieve “readable code,” there’s no question it would be great code.&lt;/p&gt;
&lt;p&gt;But readability is something that inevitably gets judged differently depending on circumstances and context. To glibly declare it as your answer without questioning what readability actually means. That’s something a programming professional shouldn’t do.&lt;/p&gt;
&lt;p&gt;So what criteria should we use to find essential value?&lt;/p&gt;
&lt;h3 id=&quot;my-choice-or-others-expectations&quot; style=&quot;position:relative;&quot;&gt;My choice, or others’ expectations?&lt;a href=&quot;#my-choice-or-others-expectations&quot; aria-label=&quot;my choice or others expectations permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first step is to reflect on whether your decisions, the things you believe are right, are truly your own.&lt;/p&gt;
&lt;p&gt;As I’ve mentioned several times, we live in a culture with strong collectivist tendencies. What we believe we decided for ourselves has often actually been determined by others’ or society’s standards.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Everyone says a developer’s starting salary should be at least X, so I should get at least that much.&lt;/li&gt;
&lt;li&gt;AI is supposedly the next big thing, so I should study AI.&lt;/li&gt;
&lt;li&gt;Big companies test algorithms, I hear. Time to start solving one algorithm problem a day.&lt;/li&gt;
&lt;li&gt;I absolutely must buy a home in Seoul.&lt;/li&gt;
&lt;li&gt;To be at the frontier of technology, I need to move to the US.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;I catch myself thinking like this too. Most recently it was: “If I drove a nice imported car, wouldn’t my life satisfaction go up a bit?” It felt great at first, but after about three months it just became normal. I spent the money but never got the satisfaction I was looking for.&lt;/p&gt;
&lt;p&gt;In the end, that was a decision influenced by society’s symbols of success, not one that truly came from within. I acquired what’s commonly recognized as a status symbol expecting it to improve my quality of life — a decision shaped by society’s perspective, not my own.&lt;/p&gt;
&lt;p&gt;So when the logic “to do A, you must do B” pops into your head, it’s often not the right answer. More precisely, it might be the right answer for someone else but not for you. That’s why it’s worth pausing to reflect.&lt;/p&gt;
&lt;h3 id=&quot;understanding-yourself-is-the-first-step&quot; style=&quot;position:relative;&quot;&gt;Understanding yourself is the first step&lt;a href=&quot;#understanding-yourself-is-the-first-step&quot; aria-label=&quot;understanding yourself is the first step permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The right answer isn’t far away. To find it, you first need a deep understanding of yourself.&lt;/p&gt;
&lt;p&gt;You need to know what you enjoy, what brings you joy, what makes you sad. You need to look back and identify what makes your heart race, what activities you lose yourself in. Without this kind of self-reflection, we’re easily swept along by standards that others or society have set for us.&lt;/p&gt;
&lt;p&gt;I think this matters a lot. Unfortunately, when we’re busy navigating day-to-day life, we spend all our mental energy on external problems and rarely take the time to look inward and reflect on ourselves.&lt;/p&gt;
&lt;p&gt;“Self-reflection” might sound old-fashioned and heavy, but it really starts with small questions you ask yourself:&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;When have I felt truly happy?&lt;/li&gt;
&lt;li&gt;Why do I go to work?&lt;/li&gt;
&lt;li&gt;Why am I working as a developer?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;What matters is checking whether every decision you make truly originates from your own will, and confirming that what you’ve thought and decided actually fits you, like clothes that are actually your size.&lt;/p&gt;
&lt;p&gt;I paid a premium for an imported car, but the novelty wore off in three months and I never got the satisfaction I wanted. Yet someone else might do the exact same thing and be perfectly content. It simply wasn’t the right fit for me. &lt;small&gt;(Though I still drive it because it feels wasteful to sell.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The right answer isn’t far away. It’s inside you. We may live in a society with strong collectivist tendencies, but building your own standards is the path to real satisfaction.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Existentialist philosopher Jean-Paul Sartre said, “We define ourselves, and the meaning of our existence is something we create.” He emphasized that humans are free to choose, but must also take responsibility for those choices.&lt;/p&gt;
&lt;p&gt;This suggests that when our choices come from our own values and standards rather than others’ expectations, we can live a satisfying life.&lt;/p&gt;
&lt;p&gt;Of course, navigating the real world sometimes requires meeting conditions that society or others demand. But what matters is whether you’re aware of why you’re meeting those conditions and have consciously chosen to do so.&lt;/p&gt;
&lt;p&gt;The statement that good code is readable code, or that you need to do this and that to become a good developer — these are just data points among many. Our role is to filter them through our own standards, taking what fits and discarding what doesn’t.&lt;/p&gt;
&lt;p&gt;So rather than believing the data itself is the answer, use it as raw material to build your own values and philosophy.&lt;/p&gt;
&lt;p&gt;That concludes this post on the illusion that right answers exist.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[좋은 코드란 무엇일까? - 가독성이란 허상에 대하여]]></title><description><![CDATA[우리는 인생을 살아가며 수없이 많은 문제들과 마주친다. 당장 현실적인 부분들만 보아도 입시, 취업, 이직, 재테크, 커리어, 성장 등 다양한 미션을 만나게 되는데, 종종 사람들과 이에 대해 이야기를 나누다보면 마치 정답이 정해져있다는 것과 같은 이야기 혹은 정답이 있기를 바라는 것과 같은 이야기를 듣고는 한다.]]></description><link>https://evan-moon.github.io/2024/12/23/the-illusion-of-a-right-answer/</link><guid isPermaLink="false">20241223-the-illusion-of-a-right-answer</guid><pubDate>Mon, 23 Dec 2024 09:34:56 GMT</pubDate><content:encoded>&lt;p&gt;우리는 인생을 살아가며 수없이 많은 문제들과 마주친다. 당장 현실적인 부분들만 보아도 입시, 취업, 이직, 재테크, 커리어, 성장 등 다양한 미션을 만나게 되는데, 종종 사람들과 이에 대해 이야기를 나누다보면 마치 정답이 정해져있다는 것과 같은 이야기 혹은 정답이 있기를 바라는 것과 같은 이야기를 듣고는 한다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;때로는 사회가 정답을 강요한다는 생각이 들기도 한다. “좋은 대학에 입학하면 인생이 필거야”, “행복하게 살려면 서울에 집 한 채는 있어야지”, “월 수입이 얼마는 되어야 중산층이지”와 같은 여러가지 조건과 기준들을 듣고 있자면, 내가 결정하는 것들이 정말 내가 결정하는 것이 맞는지 아니면 단순히 사회가 정해놓은 기준에 따라가고 있는 것인지 의문이 들 때가 있다.&lt;/p&gt;
&lt;p&gt;학생들은 지식을 얻고 탐구하고자 학습하는 것이 아닌, 다수가 외치는 정답을 맞추기 위해 학습한다. 그리고 이런 폐단은 학교 뿐 아니라 사교육에서도 동일하게 나타나며, 개발자들을 가르치는 여러 조직들 또한 크게 다르지 않다. 결국 고객들이 정답을 원하고 있으니 정답을 가르치는 것이 비즈니스 임팩트이기 때문이다.&lt;/p&gt;
&lt;p&gt;이렇게 사회가 제공하는 성공의 공식은 우리를 길들여왔다. 그래서 우리가 접하는 대부분의 문제들은 비정형적이고 정답이 없는 것들인 경우가 대부분이지만, 종종 우리는 문제를 만났을 때 마치 정답이 있을 것이라고 착각하고는 한다.&lt;/p&gt;
&lt;p&gt;이런 사회적 강요는 우리의 사고방식에도 깊은 영향을 미치며, 필자와 같은 개발자들 역시 예외는 아니다. 그래서 이번 포스팅에서는 이에 대해 필자가 평소 느꼈던 문제 의식에 대해 한번 풀어보고자 한다.&lt;/p&gt;
&lt;h2 id=&quot;정답을-찾으려는-노력&quot; style=&quot;position:relative;&quot;&gt;정답을 찾으려는 노력&lt;a href=&quot;#%EC%A0%95%EB%8B%B5%EC%9D%84-%EC%B0%BE%EC%9C%BC%EB%A0%A4%EB%8A%94-%EB%85%B8%EB%A0%A5&quot; aria-label=&quot;정답을 찾으려는 노력 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사실 필자와 같은 개발자들은 정답을 찾기 위해 노력하는 것이 익숙한 부류이다. 아무래도 논리를 다루는 직업의 특성 상, 명확한 근거를 기반으로 논리적으로 오류가 없는 의사 결정을 내리는 것에 익숙하기 때문이다.&lt;/p&gt;
&lt;p&gt;보통 개발자들이 외치는 정답은 대부분 코드의 형상과 관계에 초점이 맞춰져 있는데, 간혹 명확한 이유 없이 모노레포를 도입한다거나 전역 상태 관리 라이브러리 또는 메모이제이션과 같은 특정 메소드를 맥락 없이 도입하는 경우도 흔하다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 이야기 했듯 현실은 그렇게 단순하지 않으며 많은 경우 “최선”이라는 것은 맥락과 상황에 따라, 혹은 해석하는 사람에 따라 다르게 정의된다.&lt;/p&gt;
&lt;h3 id=&quot;좋은-코드란-무엇일까요-가독성이-좋은-코드요&quot; style=&quot;position:relative;&quot;&gt;좋은 코드란 무엇일까요? 가독성이 좋은 코드요.&lt;a href=&quot;#%EC%A2%8B%EC%9D%80-%EC%BD%94%EB%93%9C%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%9A%94-%EA%B0%80%EB%8F%85%EC%84%B1%EC%9D%B4-%EC%A2%8B%EC%9D%80-%EC%BD%94%EB%93%9C%EC%9A%94&quot; aria-label=&quot;좋은 코드란 무엇일까요 가독성이 좋은 코드요 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자는 어쩌다 보니 경력 초반인 지난 2016년부터 현재까지 꾸준히 인터뷰어로서의 경험을 쌓고 있는데, 아무래도 오랫동안 이 일을 하다보니 개인적으로 사용하는 질문 템플릿이 몇 가지 있다.&lt;/p&gt;
&lt;p&gt;그 중 하나는 “좋은 코드란 무엇일까요?”라는 질문이다. 이는 개인적으로도 오랫동안 고민해온 주제라 인터뷰를 통해 다양한 개발자들의 의견을 듣고 싶은 마음도 있다. 하지만 이런 질문을 던지면 신기하게도 굉장히 많은 분들이 “가독성이 좋은 코드”라는 답변을 해주시는데, 과장을 조금 보태자면 100명 중 99명은 이 답변을 주시는 것 같다.&lt;/p&gt;
&lt;p&gt;필자는 이 답변을 들을 때마다 묘한 어색함을 느끼는데, 가독성은 본질적으로 주관적이고 추상적인 개념이기 때문이다. 같은 코드를 보아도 누군가는 가독성이 좋다고 말할 수 있고, 누군가는 나쁘다고 말할 수 있는 것이니 말이다.&lt;/p&gt;
&lt;p&gt;물론 코드를 이집트 상형 문자로 표현하는 것보다 나에게 익숙한 언어로 표현하는 것이 이해하기 쉬운 것처럼 많은 사람들이 가독성이 높다고 공감할 수 있는 요소들은 존재할 수 있겠지만, 사실 우리가 이야기하는 가독성이라는 것이 이런 수준의 이야기를 하는 것이 아니라는 건 다들 알고 있을 것이다.&lt;/p&gt;
&lt;p&gt;애초에 전 세계에 존재하는 약 2,600만 명의 소프트웨어 개발자들이 모두 공감할 수 있는 기술적 요소라는 것이 존재할 수나 있는 것일까? 모두가 공감할 수 없는 가치라면 애초에 가독성이 좋은 코드라는 것이 세상에 존재하기는 하는 것인지에 대한 의심을 해봐야 하지 않을까?&lt;/p&gt;
&lt;p&gt;이런 마음을 담아 지원자에게 “가독성이 좋은 코드는 무엇인가요?”라는 질문을 던지면 이제부터 답변이 다양해진다. 누군가는 응집이나 결합을 강조하고, 누군가는 명확하고 직관적인 네이밍, 누군가는 관심사에 대한 이야기를 한다. 즉, 가독성이라는 것의 본질 전체를 꿰뚫는 정의가 아닌, 현실의 특정 사례를 예시로 들며 “이렇게 했을 때 가독성이 좋아집니다”와 같은 답변을 하는 경우가 많았다.&lt;/p&gt;
&lt;p&gt;결국 개발자마다 좋은 가독성을 달성하기 위해 가장 필요하다고 생각하는 부분이 모두 다르다는 것이며, 이 답변들이 오히려 가독성이라는 것이 얼마나 주관적이고 추상적이며 맥락 의존적인 것인지 드러내는 사례이다. 마치 같은 그림을 보면서도 누군가는 아름답다고 여기고 누군가는 도대체 뭘 표현하려는 것인지 모르겠다고 하는 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;하지만 분명 많은 사람들은 “좋은 코드가 무엇인가?”에 대한 질문에 “가독성이 좋은 코드”라는 답변을 하고 있다. 마치 정답이 정해져 있기라도 한 것처럼 말이다.&lt;/p&gt;
&lt;h3 id=&quot;성장하려면-어떻게-해야할까요&quot; style=&quot;position:relative;&quot;&gt;성장하려면 어떻게 해야할까요?&lt;a href=&quot;#%EC%84%B1%EC%9E%A5%ED%95%98%EB%A0%A4%EB%A9%B4-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C%EC%9A%94&quot; aria-label=&quot;성장하려면 어떻게 해야할까요 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이 본능은 비단 개발자 뿐 아니라, 우리가 일상에서 내리는 크고 작은 결정에서도 자주 드러난다. 필자는 종종 1-on-1, 멘토링과 같이 다른 개발자들의 고민을 듣고 도움을 드릴 수 있는 자리를 가지고는 하는데, 사실 이런 자리에서도 정답을 찾으려는 노력을 많이 보아왔다.&lt;/p&gt;
&lt;p&gt;이런 자리에서 주로 듣는 질문과 고민은 대략 이런 느낌이다.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;좋은 개발자가 되려면 어떻게 해야 하나요?&lt;/li&gt;
&lt;li&gt;ㅇㅇ 회사에 들어가려면 어떤 점을 채워야 할까요?&lt;/li&gt;
&lt;li&gt;나중에 이런 경험을 하고 싶은데, 그러면 어떻게 해야 하나요?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;물론 이런 질문을 하는 마음은 충분히 공감이 간다. 무언가를 달성하고 싶은 마음은 크지만 무엇을 해야 하는지는 모르겠을 때, 그 답답한 마음은 누구나 한번 쯤은 느껴보았을 것이다.&lt;/p&gt;
&lt;p&gt;사실 이런 질문을 던지는 분들은 분명 성장을 갈망하며 진심으로 더 나아지고 싶어한다. 하지만 문제는 성공이나 성장이라는 목표를 지나치게 정형화된 방법으로 접근한다는 점이다.&lt;/p&gt;
&lt;p&gt;그 결과 자신의 환경, 목표, 역량과 맞지 않는 보편적인 정답을 따라가다가 오히려 잘못된 방향으로 노력을 쏟는 경우를 자주 목격했다. 마치 내 몸에 맞지 않는 옷을 억지로 입으려고 하는 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;행간에는 1만 시간의 법칙과 같이 무조건 노력하면 언젠가 원하는 바를 달성할 수 있다는 이야기도 있지만, 필자는 절대 여기에 동의하지 않는다. 노력과 시간이라는 것은 매우 한정된 자원이기 때문에 어디에 투자할 것인지가 매우 중요하기 때문이다. &lt;small&gt;(기껏 1만 시간을 투자했더니 알고보니 내 성장에 전혀 도움이 되지 않았던 곳이었다고 해도 날려버린 1만 시간은 두번 다시 돌아오지 않는다.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;결국 중요한 것은 시간과 에너지를 어디에 투자할 것인가에 대한 방향성인데, 문제는 우리는  이 방향성을 스스로 결정했다고 믿지만, 사실 그 선택은 타인이나 사회가 제시한 기준에 의존한 결과일 때가 많다는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;고정된-진리가-아닌-다양한-맥락-속에서-변화하는-진리&quot; style=&quot;position:relative;&quot;&gt;고정된 진리가 아닌 다양한 맥락 속에서 변화하는 진리&lt;a href=&quot;#%EA%B3%A0%EC%A0%95%EB%90%9C-%EC%A7%84%EB%A6%AC%EA%B0%80-%EC%95%84%EB%8B%8C-%EB%8B%A4%EC%96%91%ED%95%9C-%EB%A7%A5%EB%9D%BD-%EC%86%8D%EC%97%90%EC%84%9C-%EB%B3%80%ED%99%94%ED%95%98%EB%8A%94-%EC%A7%84%EB%A6%AC&quot; aria-label=&quot;고정된 진리가 아닌 다양한 맥락 속에서 변화하는 진리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사실 사람은 누구나 안정성과 확실성을 추구하고 불확실한 상황을 불편해하는 심리적 기제를 지니고 있기 때문에 이러한 사고가 부자연스러운 것은 아니다. 오히려 정답이 없다고 믿는 것이 인간의 본능을 거스르는 행위일 수도 있다.&lt;/p&gt;
&lt;p&gt;그래서 앞서 언급한 가독성과 성장의 사례 또한 훌륭한 개발자가 되기 위해 갈망하고 공부하던 많은 사람들이 어떤 블로그, 책, 혹은 주변에 있는 개발자 등을 통해 퍼진 정보들을 비판 없이 흡수했을 가능성이 높다. 하지만 가독성이나 성장과 같은 문제는 정해진 정답이라는 것이 없다는 점을 간과해서는 안된다.&lt;/p&gt;
&lt;p&gt;철학에서는 이러한 문제를 탐구하기 위해 상대주의(Relativism)와 맥락주의(Contextualism) 같은 개념을 사용한다.&lt;/p&gt;
&lt;p&gt;상대주의는 진리나 가치는 보편적이지 않고, 특정 문화, 관점, 상황에 따라 달라진다는 것이며, 이는 가독성의 기준도 개인의 기준 혹은 개인이 처한 상황에 따라 달라질 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;맥락주의는 어떤 명제가 참인지 여부는 그것이 사용되는 맥락에 달려 있다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;예를 들어 동일한 코드라 하더라도, 팀의 문화나 프로젝트의 성격, 그리고 비즈니스 상황에 따라 그에 대한 평가가 달라질 수 있는 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;많은 이들이 좋은 코드란 무엇인가에 대해 가독성 좋은 코드라는 답을 정답처럼 외치고 있지만, 이것은 고정된 진리가 아니라 다양한 맥락 속에서 변화하는 상대적인 개념인 것이다.&lt;/p&gt;
&lt;p&gt;물론 인터뷰라는 자리를 마치 인터뷰어가 생각하는 정답을 맞춰야하는 게임이라고 착각하시는 경우가 많기 때문에 다소 편향이 발생했을 수도 있지만, 비단 인터뷰 뿐만 아니라 멘토링이나 1-on-1과 같은 자리에서도 많은 분들이 비슷한 반응을 보였기 때문에 편향이 크지는 않다고 생각한다. &lt;small&gt;(독자 여러분도 당장 주변에 있는 개발자 아무나 10명만 붙잡고 “좋은 코드란 뭐라고 생각하심?”이라는 질문을 한번 던져보면 아마 높은 확률로 가독성 이야기가 나올 것이다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;물론 우리가 굳이 기계어가 아니라 인간에게 익숙한 기호들로 추상화된 프로그래밍 언어를 사용하는 것은 결국 인간이 컴퓨터의 동작을 쉽게 이해하기 위함이니, 가독성이 좋은 코드라는 가치를 달성할 수만 있다면 더할 나위 없이 좋은 코드라고 부를 수 있음에는 이견이 없다.&lt;/p&gt;
&lt;p&gt;하지만 상황이나 맥락에 따라 다르게 판단될 수 밖에 없는 이 가독성이 좋다는 것이 도대체 무엇인지, 근본적인 진리에 대한 의문과 고찰없이 이런 답을 섣불리 내는 것은 프로그래밍 전문가로써 해서는 안될 행동이다.&lt;/p&gt;
&lt;p&gt;그렇다면 우리는 과연 무엇을 기준으로 본질적인 가치를 찾아야 하는 것일까?&lt;/p&gt;
&lt;h3 id=&quot;나의-선택인가-타인의-기대인가&quot; style=&quot;position:relative;&quot;&gt;나의 선택인가, 타인의 기대인가?&lt;a href=&quot;#%EB%82%98%EC%9D%98-%EC%84%A0%ED%83%9D%EC%9D%B8%EA%B0%80-%ED%83%80%EC%9D%B8%EC%9D%98-%EA%B8%B0%EB%8C%80%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;나의 선택인가 타인의 기대인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;가장 먼저 나의 의사결정 또는 내가 옳다고 생각하는 무언가가 정말 내가 결정한 것이 맞는지에 대해 성찰하는 과정이 필요하다.&lt;/p&gt;
&lt;p&gt;앞서 여러 번 언급했듯이 우리는 집단주의 성향이 강한 문화권에서 살아가고 있기 때문에, 내가 스스로 결정했다고 믿는 것이 사실은 타인이나 사회의 기준에 의해 결정된 경우가 많다.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;다들 개발자 초봉은 n천만원이라고 하니, 나도 그 정도는 받아야지.&lt;/li&gt;
&lt;li&gt;요즘 AI가 대세라고 하니까 나도 AI를 공부해야겠다.&lt;/li&gt;
&lt;li&gt;대기업은 알고리즘을 본다고 하네. 그럼 오늘부터 성실하게 1일 1알고리즘 풀이를 해야겠다.&lt;/li&gt;
&lt;li&gt;집은 무조건 서울에 사야지.&lt;/li&gt;
&lt;li&gt;기술의 선두 주자가 되려면 미국으로 건너가야겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;물론 필자도 알게 모르게 이런 생각을 많이 한다. 가장 최근에 했던 생각은 “비싼 수입차를 타면 내 인생에 대한 만족도가 조금은 올라가지 않을까”였는데, 처음에는 좋았지만 결국 3개월 정도 지나니까 익숙해져서 돈은 돈대로 쓰고 원했던 만족도는 얻지 못 했다.&lt;/p&gt;
&lt;p&gt;결국 이것 또한 사회에서 일반적으로 통용되는 성공의 상징을 취득하면 삶의 질이 올라갈 것이라 판단한 것이니, 필자 스스로의 의사결정이라기보다는 사회나 타인의 시선에 영향을 받은 상황이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;그래서 이렇게 “A를 하려면 B를 해야한다”와 같은 논리가 머릿속에 떠올랐다면 대부분 정답이 아닌 경우가 많다. 더 정확히 말하자면 누군가에게는 정답일 수 있어도 나에게는 아닐 수 있기 때문에 한번 멈추고 성찰하는 과정이 필요한 것이다.&lt;/p&gt;
&lt;h3 id=&quot;나를-이해하는-것이-첫걸음이다&quot; style=&quot;position:relative;&quot;&gt;나를 이해하는 것이 첫걸음이다&lt;a href=&quot;#%EB%82%98%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%B4-%EC%B2%AB%EA%B1%B8%EC%9D%8C%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;나를 이해하는 것이 첫걸음이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;정답은 사실 멀리 있는 것이 아니다. 정답을 찾기 위해서는 일단 나 스스로에 대한 깊은 이해가 필요하다.&lt;/p&gt;
&lt;p&gt;내가 무엇을 좋아하고, 어떨 때 기쁨을 느끼며, 어떤 순간에 슬픔을 느끼는 지 알아야 한다. 무엇을 할 때 가슴이 뛰는지, 어떤 일을 할 때 가장 몰입하는지를 돌아보아야 한다. 이런 자기 성찰이 뒷받침되지 않는다면, 우리는 쉽게 타인이나 사회가 정해준 기준에 휘둘릴 수밖에 없다.&lt;/p&gt;
&lt;p&gt;필자는 이것이 굉장히 중요한 요소라고 생각하는데, 안타깝게도 바쁘게 현생을 살다보면 외부의 문제에는 있는 힘껏 머리를 쓰면서도 정작 나에 대해서 돌아보고 생각해볼 기회는 많이 없는 것 같다.&lt;/p&gt;
&lt;p&gt;성찰이라고 하면 고루하고 어려운 이야기처럼 느껴질 수는 있지만, 사실 스스로에게 던지는 작은 질문부터 시작해보면 그리 어려운 것은 아니다.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;나는 어떤 상황에서 행복함을 느꼈을까?&lt;/li&gt;
&lt;li&gt;나는 회사를 왜 다니고 있지?&lt;/li&gt;
&lt;li&gt;나는 왜 개발자로 일하고 있지?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;결국 중요한 것은 내가 내리는 모든 결정이 진정 나의 의지에서 비롯된 것인지 점검하고, 내가 생각하고 결정한 것이 정말 내 몸에 맞는 옷이 맞는지를 확인하는 것이다.&lt;/p&gt;
&lt;p&gt;필자는 비싼 값을 치루고 수입차를 샀지만 결국 3개월 만에 익숙해져버려 원했던 만족감을 얻지 못 했다. 하지만 누군가는 동일한 행위를 해도 충분히 만족하면서 살아갈 수도 있다. 애초에 이 행위는 필자에 맞는 옷이 아니었던 것이다. &lt;small&gt;(하지만 또 팔기는 아까워서 아직 잘 타고 있다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;정답은 멀리 있는 것이 아니라, 내 안에 있다. 비록 우리는 집단주의적 성향이 강한 사회 속에서 살아가지만, 오히려 이런 곳에서 나만의 기준을 세워가는 것이야말로 진정한 만족과 성취를 얻는 길이라고 할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;실존주의 철학자 장폴 사르트르는 “우리는 스스로를 정의하며, 우리 존재의 의미는 우리가 만드는 것”이라고 말하며 인간이 자유롭게 선택할 수 있는 존재임과 동시에, 그 선택에 대한 책임을 져야 한다는 점을 강조했다.&lt;/p&gt;
&lt;p&gt;이는 우리의 선택이 타인의 기대가 아니라 스스로의 가치와 기준에서 나올 때, 진정으로 만족스러운 삶을 살 수 있음을 시사한다.&lt;/p&gt;
&lt;p&gt;물론 현생을 살기 위해서는 사회나 타인이 요구하는 여러 조건들을 맞춰야 하는 경우도 있다. 하지만 중요한 것은 스스로가 그 조건을 왜 맞춰야 하는지 인지하고 결정한 것이 맞냐는 것이다.&lt;/p&gt;
&lt;p&gt;좋은 코드는 가독성이 높은 코드라는 말, 좋은 개발자가 되기 위해서는 이런 저런 일을 해야한다는 타인의 말은 그저 수많은 데이터 중 하나일 뿐이다. 우리의 역할은 저 데이터를 그대로 받아들이는 것이 아니라 내 기준에 맞춰 정제하여 취할 것은 취하고 버릴 것은 버리는 것이다.&lt;/p&gt;
&lt;p&gt;그러니 데이터 자체가 정답이라고 믿는 것이 아닌 데이터를 재료로 하여 나만의 가치관과 철학을 만드는 과정에 대해 더 깊은 고민을 해보는 것을 추천한다.&lt;/p&gt;
&lt;p&gt;이상으로 정답이 존재한다는 착각 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Who Are You, the One Writing Code Right Now?]]></title><description><![CDATA[AI is transforming our lives. When you use the ChatGPT mobile app and have voice conversations back and forth, it’s hard not to feel like Jarvis from Iron Man has become reality. Generative AI like ChatGPT is used for everything from casual conversation to complex problem-solving, making our lives richer and more convenient.]]></description><link>https://evan-moon.github.io/2024/06/23/perspective-on-ai/en/</link><guid isPermaLink="false">20240623-perspective-on-ai-en</guid><pubDate>Sun, 23 Jun 2024 10:10:21 GMT</pubDate><content:encoded>&lt;p&gt;AI is transforming our lives. When you use the ChatGPT mobile app and have voice conversations back and forth, it’s hard not to feel like Jarvis from Iron Man has become reality.&lt;/p&gt;
&lt;p&gt;Generative AI like ChatGPT is used for everything from casual conversation to complex problem-solving, making our lives richer and more convenient.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;But I think we need to step back and ask whether the comfort these technologies afford us has made us forget an important question — one about the fundamental significance of human existence.&lt;/p&gt;
&lt;p&gt;For thousands of years, philosophers have argued that what makes us human is our capacity for self-reflection, critical and rational thinking, self-awareness, and moral judgment.&lt;/p&gt;
&lt;p&gt;Yet lately, I see more and more people delegating the very faculties we’ve long considered essential to being human to tools like ChatGPT.&lt;/p&gt;
&lt;p&gt;Of course, generative AI still isn’t perfectly accurate, so we haven’t delegated everything just yet. But the fact that the delegation has already begun is what matters. Given the pace of AI’s advancement, it’s not hard to imagine a future where this delegation accelerates rapidly.&lt;/p&gt;
&lt;p&gt;And yet, compared to the speed at which AI is advancing, the ethical and philosophical discourse around it has been largely sidelined. I think this absence of discourse will come back as a serious side effect once AI develops further, and those building this technology should be paying the most attention.&lt;/p&gt;
&lt;h2 id=&quot;i-could-have-done-better-if-id-used-chatgpt&quot; style=&quot;position:relative;&quot;&gt;“I could have done better if I’d used ChatGPT”&lt;a href=&quot;#i-could-have-done-better-if-id-used-chatgpt&quot; aria-label=&quot;i could have done better if id used chatgpt permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since 2016, I’ve interviewed countless developers. If I averaged four to six interviews per month, that comes to roughly 400–600 people over the years.&lt;/p&gt;
&lt;p&gt;I’ve heard all kinds of answers and perspectives through these interviews, but one response I heard recently was something I’d never encountered before:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I think I could have done better on the assignment if I’d been allowed to use ChatGPT.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This struck me as a peculiar and unfamiliar answer. It was essentially an admission that without a specific tool, the person couldn’t fully solve the problem in front of them — whether that tool is ChatGPT or Google.&lt;/p&gt;
&lt;p&gt;Typically in interviews, candidates avoid underselling themselves. They try to emphasize what they can do on their own merits, without external tools. Everyone understands that interviews are meant to find people who can solve problems without tools but can use tools to amplify their capabilities, not people who can’t solve problems without them.&lt;/p&gt;
&lt;p&gt;Some of you reading this might argue: “We’ll use ChatGPT on the job anyway, so what’s wrong with using tools during the evaluation?” Why not just assess the ability to use these tools effectively?&lt;/p&gt;
&lt;p&gt;I use ChatGPT at work too. And I won’t deny that using it well can dramatically boost productivity. But the topic I want to explore in this post isn’t something as narrow as “should we test ChatGPT proficiency in interviews.”&lt;/p&gt;
&lt;p&gt;Think about it. Right now, since generative AI has only been around for two years, humans still need to craft good prompts to get good results. But soon enough, AI will reach the point where even a vague, poorly worded question produces a perfect answer.&lt;/p&gt;
&lt;p&gt;If AI reaches that level, what does it even mean to “assess someone’s ability to use the tool”? If anyone, regardless of knowledge, can ask AI a sloppy question and get a perfect response, the very concept of tool proficiency becomes meaningless.&lt;/p&gt;
&lt;p&gt;The real issue is this: despite generative AI being only two years old, the number of people depending on AI for their thinking is growing fast, yet hardly anyone is paying attention to ethical questions like “how should we approach AI?” or “what does it mean to outsource our thinking to AI?”&lt;/p&gt;
&lt;p&gt;As I mentioned earlier, people currently know that generative AI isn’t perfect, so full delegation of thinking hasn’t happened yet. But the moment people start believing that AI produces better answers than they can, the degree of delegation will escalate rapidly.&lt;/p&gt;
&lt;p&gt;This is fundamentally different from simply using a tool to increase productivity. Every tool up to now has either assisted human capabilities or enabled things humans couldn’t do on their own.&lt;/p&gt;
&lt;p&gt;But AI can think and make decisions at a level nearly equal to humans, and in certain domains, it has already surpassed us. Unlike every tool that came before, it’s now possible to delegate not just labor but human thought itself to AI. And there’s almost no sign that people are wary of this possibility.&lt;/p&gt;
&lt;p&gt;Given that we’re already delegating parts of our thinking to AI just two years after generative AI entered the mainstream, I believe this trend will only accelerate.&lt;/p&gt;
&lt;h2 id=&quot;what-is-the-fundamental-significance-of-human-existence&quot; style=&quot;position:relative;&quot;&gt;What is the fundamental significance of human existence?&lt;a href=&quot;#what-is-the-fundamental-significance-of-human-existence&quot; aria-label=&quot;what is the fundamental significance of human existence permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To explain the concern I’ve been carrying, we first need to examine what has historically been defined as the reason humans can exist as humans. “What is a human being?” is a question philosophers have explored for thousands of years.&lt;/p&gt;
&lt;p&gt;We know we possess something that distinguishes us from other animals, but because no one has given us a definitive answer, we’ve spent millennia searching for one ourselves.&lt;/p&gt;
&lt;p&gt;Plato, through his Theory of Forms, said humans are beings who pursue truth and ideals. Aristotle defined humans as rational animals. Descartes, with his proposition “I think, therefore I am,” linked human existence to thought and self-awareness. Kant defined humans as autonomous agents capable of moral judgment. Sartre said humans are beings who create their own essence.&lt;/p&gt;
&lt;p&gt;Countless philosophers have offered various definitions of human nature and the significance of existence, but if you look closely, there are a few common threads.&lt;/p&gt;
&lt;p&gt;The most prominent commonality is self-reflection and self-awareness: the ability to understand oneself, analyze one’s thoughts and actions, and pursue a deep understanding of one’s own existence. Plato and Aristotle’s rational thinking, Descartes’ thought and self-awareness, Kant’s moral autonomy, Sartre’s creation of essence. All revolve around this core of self-reflection and self-awareness.&lt;/p&gt;
&lt;p&gt;In other words, humans are not beings who merely experience and react. We are beings who analyze and evaluate our experiences, and from them discover new meaning and direction.&lt;/p&gt;
&lt;p&gt;The essential human trait that philosophers have long emphasized, self-reflection and self-awareness, is what elevates us beyond mere biological existence. As long as there’s a possibility that we delegate this to AI, we need to examine the issue through deep contemplation.&lt;/p&gt;
&lt;h2 id=&quot;does-ai-threaten-the-essence-of-human-existence&quot; style=&quot;position:relative;&quot;&gt;Does AI threaten the essence of human existence?&lt;a href=&quot;#does-ai-threaten-the-essence-of-human-existence&quot; aria-label=&quot;does ai threaten the essence of human existence permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Returning to the interviewee’s response, “I could have done better if I’d used ChatGPT”: I discussed the danger of humans increasingly delegating their thinking to AI. That answer literally means the person couldn’t adequately perform a task without AI assistance, illustrating how human cognitive ability is becoming dependent on AI.&lt;/p&gt;
&lt;p&gt;The capacity to understand oneself, analyze one’s thoughts and actions, and pursue deep self-understanding — thought, self-reflection, and self-awareness. These define what it means to be human. These are what give humans their value beyond mere biological existence.&lt;/p&gt;
&lt;p&gt;Based on this reasoning, I want to argue that we need to be vigilant about the possibility that AI threatens the essence of human existence.&lt;/p&gt;
&lt;p&gt;As AI advances, we’re delegating more and more of our thinking to it. If relying on AI to solve problems becomes the norm, we’ll likely skip the process of thinking deeply on our own — which means losing opportunities for self-reflection, constraining our capacity for thought.&lt;/p&gt;
&lt;p&gt;Going further, if AI increasingly makes our decisions for us, we risk losing responsibility and autonomy, key components of self-awareness. The more we depend on AI’s decisions, the less accountable we feel for the outcomes, which could weaken our capacity for moral judgment.&lt;/p&gt;
&lt;p&gt;These questions about responsibility and moral judgment have long surfaced in everyday debates like “who’s responsible when a self-driving car causes an accident?” None of these questions have been conclusively answered.&lt;/p&gt;
&lt;p&gt;We must stay alert to the fact that as AI advances and our dependence deepens, we risk losing the very capabilities that define us as human. And those who are leading this technology should be paying even more attention to this ethical discourse.&lt;/p&gt;
&lt;h2 id=&quot;who-are-you-the-one-writing-code-right-now&quot; style=&quot;position:relative;&quot;&gt;Who are you, the one writing code right now?&lt;a href=&quot;#who-are-you-the-one-writing-code-right-now&quot; aria-label=&quot;who are you the one writing code right now permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As you’ve probably guessed, the people leading this technology are developers and researchers — especially those contributing directly to the AI domain.&lt;/p&gt;
&lt;p&gt;Yet lately, even among developers, I see cases where people accept AI-suggested code from ChatGPT or Copilot without any critical review.&lt;/p&gt;
&lt;p&gt;ChatGPT and Copilot are advancing rapidly, and it’s true they produce higher-quality code than before. But can we honestly say their output is flawless at this point?&lt;/p&gt;
&lt;p&gt;No, we can’t. AI-generated code sometimes contains errors, and in certain situations, it fails to provide a complete solution. In particular, understanding context across multiple modules and designing architecture remain problems AI hasn’t conquered.&lt;/p&gt;
&lt;p&gt;If AI-generated code were already perfect, the profession of software developer would have ceased to exist. The fact that developers still exist is itself proof that AI’s code is not yet complete. As AI advances, the number of people in this profession may shrink, but for now, that’s not the case.&lt;/p&gt;
&lt;p&gt;So what role should we — the people with expertise in this technology — play?&lt;/p&gt;
&lt;p&gt;Developers shouldn’t simply accept AI’s output. We should critically review and revise what AI generates. We must view AI as a tool and use it to maximize our own thinking and creativity. Even with AI’s help, the final decisions and responsibility rest with us.&lt;/p&gt;
&lt;p&gt;Knowing that hallucinations exist, copying and pasting AI-generated code without review, or treating AI’s responses as truth, is premature. Even if the day comes when AI produces perfect answers, we must never forget that AI should be controlled by experts as a tool. &lt;small&gt;(AI is a library, not a framework.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;If you’re accepting AI’s output uncritically and mistaking it for your own ability, ask yourself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Am I a human who uses AI as a tool? Or am I merely a vessel that transfers AI’s output into an IDE?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AI cannot become “me.” We can receive AI’s help, but in that process, we must remain vigilant about preserving our ability to think and judge for ourselves.&lt;/p&gt;
&lt;p&gt;This question goes beyond programming. It demands reflection on the nature of being human. If what makes us fundamentally human is the ability to understand ourselves through self-reflection and self-awareness, to explore the meaning of our existence, then merely following the instructions of a non-human tool cannot constitute human existence.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some might say these thoughts are premature, or that I’m making too great a leap. But as you know, AI is advancing at a staggering pace, and in certain fields, AI has surpassed humans in less than a decade.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7800e68ab22994055e740f794b98ab78/4b190/graph.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3pRQf//EABYQAAMAAAAAAAAAAAAAAAAAABAgIf/aAAgBAQABBQJKP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABsQAAICAwEAAAAAAAAAAAAAAAABITERQWGB/9oACAEBAAE/IXfCnCwKSdHgR//aAAwDAQACAAMAAAAQAA//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAwADAQAAAAAAAAAAAAABABExIUFhgf/aAAgBAQABPxBLlcJUvQHYBzFS6YhXhXsBbT5M6NPRP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;graph&quot; title=&quot;&quot; src=&quot;/static/7800e68ab22994055e740f794b98ab78/c08c5/graph.jpg&quot; srcset=&quot;/static/7800e68ab22994055e740f794b98ab78/0913d/graph.jpg 160w,
/static/7800e68ab22994055e740f794b98ab78/cb69c/graph.jpg 320w,
/static/7800e68ab22994055e740f794b98ab78/c08c5/graph.jpg 640w,
/static/7800e68ab22994055e740f794b98ab78/4b190/graph.jpg 800w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Math aside, look at the terrifying slope in language comprehension.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The number of AI-related projects on GitHub was only around 800 in 2011, but by 2023 it had grown to roughly 1.8 million. Over the same period, the number of research papers roughly tripled.&lt;/p&gt;
&lt;p&gt;I believe that compared to how fast the technology is advancing, our perspective on it, our discussion of the potential side effects, has not kept pace.&lt;/p&gt;
&lt;p&gt;AI is fundamentally different from every tool that came before. Previous tools could never surpass humans no matter what, and because of that inherent limitation, even the best tools could only assist.&lt;/p&gt;
&lt;p&gt;But as the chart above shows, AI has already surpassed humans in certain areas. AGI may still be some time away, but in specific domains, it’s already happened. We need to pay attention to this.&lt;/p&gt;
&lt;p&gt;What I want to say is this: as we use this convenient, explosively productive tool called AI, we should pause and ask whether we’re unknowingly delegating our essential human value to it.&lt;/p&gt;
&lt;p&gt;A tool is called a tool because humans wield it with agency. If using AI causes us to lose our autonomy and the fundamental significance of being human, can we still call it a tool?&lt;/p&gt;
&lt;p&gt;Building a better future alongside AI requires that ethical and philosophical discourse keep pace with technological development. Those of us leading this technology shouldn’t be focused solely on advancing the technology itself. We need to actively participate in these discussions and care about building a world where we, as humans, can properly wield AI as the powerful tool it is.&lt;/p&gt;
&lt;p&gt;This concludes my post: Who Are You, the One Writing Code Right Now?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[지금 프로그래밍을 하고 있는 당신은 누구인가]]></title><description><![CDATA[AI는 우리의 생활을 크게 변화시키고 있다. ChatGPT 모바일 앱을 사용하면서 음성으로 대화를 주고 받다보면 이제는 영화 아이언맨에 나오는 인공지능 비서 자비스가 현실화된 것이 아닌가 하는 착각마저도 일으킬 정도이다.]]></description><link>https://evan-moon.github.io/2024/06/23/perspective-on-ai/</link><guid isPermaLink="false">20240623-perspective-on-ai</guid><pubDate>Sun, 23 Jun 2024 10:10:21 GMT</pubDate><content:encoded>&lt;p&gt;AI는 우리의 생활을 크게 변화시키고 있다. ChatGPT 모바일 앱을 사용하면서 음성으로 대화를 주고 받다보면 이제는 영화 아이언맨에 나오는 인공지능 비서 자비스가 현실화된 것이 아닌가 하는 착각마저도 일으킬 정도이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;ChatGPT와 같은 생성형 AI는 일상적인 대화부터 복잡한 문제 해결까지 다양한 용도로 사용되며, 우리의 삶을 더욱 윤택하게 만들고 있다.&lt;/p&gt;
&lt;p&gt;그러나 필자는 이러한 기술의 발전이 선물해준 편리함 속에서 우리가 중요한 질문을 잊고 있는 것은 아닌지 돌아볼 필요가 있다고 생각한다. 바로 &lt;strong&gt;인간 존재의 본질적 의의&lt;/strong&gt;에 대한 질문이다.&lt;/p&gt;
&lt;p&gt;지난 수천 년 동안 많은 철학자들은 인간이 자기 성찰, 비판적/이성적 사고, 자아 인식과 자기 성찰, 도덕적 판단과 같은 것들을 가지고 있기 때문에 인간일 수 있다고 이야기해왔다.&lt;/p&gt;
&lt;p&gt;하지만 최근 주변을 둘러보면 지금껏 우리가 인간으로 존재하기 위해 지녀야 한다고 이야기해왔던 많은 가치들을 ChatGPT와 같은 도구에게 위임하는 모습을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;물론 지금의 생성형 AI는 아직 정확도가 높지 않기 때문에 많은 부분을 위임하지는 않겠지만, 그 위임이 이미 시작되고 있다는 것이 중요한 부분이며, AI의 발전속도를 생각해보면 앞으로 점점 더 빠른 속도로 위임이 이루어질 미래를 그리 어렵지 않게 그려볼 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 AI가 발전하는 속도에 비해 이러한 윤리적/철학적 담론은 거의 배제되고 있다. 필자는 추후 AI가 더욱 발전했을 때 이러한 담론의 부재가 큰 사이드 이펙트로 돌아올 것이라고 생각하며, 특히 이 기술을 개발하고 있는 분들은 더더욱 이 아젠다에 관심을 가져야 한다고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;chatgpt를-썼다면-더-잘할-수-있었을-것-같아요&quot; style=&quot;position:relative;&quot;&gt;ChatGPT를 썼다면 더 잘할 수 있었을 것 같아요&lt;a href=&quot;#chatgpt%EB%A5%BC-%EC%8D%BC%EB%8B%A4%EB%A9%B4-%EB%8D%94-%EC%9E%98%ED%95%A0-%EC%88%98-%EC%9E%88%EC%97%88%EC%9D%84-%EA%B2%83-%EA%B0%99%EC%95%84%EC%9A%94&quot; aria-label=&quot;chatgpt를 썼다면 더 잘할 수 있었을 것 같아요 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자는 지난 2016년부터 지금까지 수많은 개발자들의 인터뷰를 진행했었다. 만약 한 달에 4-6명씩 인터뷰를 진행했었다고 하면 대략 400-600명 정도 되는 인원을 만나본 셈이다.&lt;/p&gt;
&lt;p&gt;이러한 인터뷰를 통해 다양한 답변과 견해를 들을 수 있었지만, 최근에 들은 답변은 그동안의 경험에서 한 번도 듣지 못했던 것이었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“ChatGPT를 썼다면 과제를 더 잘할 수 있었을 것 같아요”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이는 필자에게 꽤나 독특하고 낯선 답변으로 다가왔다. 이것은 도구를 사용할 수 없었기 때문에 자신에게 주어진 문제를 온전히 풀어낼 수 없었다고 시인한 것이나 마찬가지이기 때문이다. 이 도구가 ChatGPT든, 구글링이든 상관없이 말이다.&lt;/p&gt;
&lt;p&gt;보통 인터뷰를 진행할 때 지원자들은 자신의 능력을 과소평가하는 말을 피하고, 오히려 도구가 없이도 펼칠 수 있는 자신 본연의 역량을 최대한 강조하려고 노력하기 마련이다. 이는 인터뷰라는 것이 도구가 없다면 문제를 해결할 수 없는 사람보다는 도구가 없어도 문제를 해결할 수 있되, 도구를 통해 자신의 역량을 부스팅할 수 있는 사람을 찾고자 하는 과정이라는 사실을 모두가 알고 있기 때문이기도 하다.&lt;/p&gt;
&lt;p&gt;혹시 이 글을 읽고 있는 누군가는 어차피 입사하면 ChatGPT를 사용할 것인데 역량 검증 과정에서 도구를 사용하는 것이 뭐가 문제냐고 할 수도 있다. 이 도구를 활용하는 역량을 검증하면 되는 것 아니냐고 말이다.&lt;/p&gt;
&lt;p&gt;물론 필자도 실무에서 ChatGPT를 사용한다. 그리고 필자는 ChatGPT를 업무에 잘 활용하면 생산성이 압도적으로 높아질 수 있다는 것을 부정하지도 않는다. 하지만 필자가 이 포스팅에서 이야기하고 싶은 주제는 “인터뷰에서 ChatGPT 활용 역량을 검증해야하냐”와 같은 지엽적인 주제는 아니다.&lt;/p&gt;
&lt;p&gt;한번 생각해보자. 지금이야 생성형 AI가 등장한지 2년 밖에 되지 않았으니 인간이 프롬프트를 잘 작성하기 위해 고민하는 과정이 필요하겠지만, 앞으로는 개떡같이 질문해도 찰떡같은 대답을 해주는 수준까지 금방 발전할 것이다.&lt;/p&gt;
&lt;p&gt;만약 이런 수준의 AI가 등장한다면 이 도구를 활용하는 역량을 검증한다는 것이 무슨 의미가 있을까? 아무런 지식이 없는 사람이 AI에게 대충 질문해도 찰떡같은 대답을 해주는 수준이 된다면 도구의 숙련도라는 개념도 어차피 무의미해진다.&lt;/p&gt;
&lt;p&gt;중요한 것은 생성형 AI인 ChatGPT가 세상에 소개된지 이제 겨우 2년 밖에 지나지 않았음에도 불구하고 AI라는 도구에 자신의 사고를 의존하는 사람들이 빠르게 늘어나고 있지만, 정작 “우리가 AI를 어떤 식으로 다뤄야 하는지”, “AI에게 사고를 의존한다는 것이 무슨 의미인지”와 같은 윤리적 담론에는 별로 주목하고 있지 않다는 것이다.&lt;/p&gt;
&lt;p&gt;서론에서 언급했듯이 물론 지금은 생성형 AI가 완전하지 않다는 사실에 대해 인간들도 알고 있으니 자신의 사고를 AI에게 온전히 위임하는 상황은 발생하지 않는다. 그러나 만약 인간이 보기에 AI가 자신보다 더 나은 답변을 내놓는다고 판단하기 시작한다면 그 위임의 정도는 빠르게 높아질 것이다.&lt;/p&gt;
&lt;p&gt;이는 단순히 도구를 활용하여 생산성을 증가시키는 것과는 완전히 다른 개념이다. 지금까지의 도구는 인간의 능력을 보조하는 역할을 하거나, 혹은 인간 스스로의 힘으로는 불가능한 일을 할 수 있도록 도와주는 역할이었다.&lt;/p&gt;
&lt;p&gt;하지만 AI는 인간과 거의 동등한 레벨의 사고와 의사결정을 할 수도 있는 존재이며, 이미 특정 분야에 대해서는 인간의 능력을 넘어선 경우도 있다. 즉, 지금까지의 도구와는 다르게 인간의 능력을 보조하는 정도를 넘어서서 인간의 사고 자체를 AI에게 위임하는 것도 가능하다는 것이다. 그리고 인간들이 이러한 가능성에 대해서 경계하는 움직임은 거의 보이지 않는다.&lt;/p&gt;
&lt;p&gt;생성형 AI가 세상에 본격적으로 등장한지 꼴랑 2년 밖에 되지 않은 지금도 사고의 일부를 AI에게 위임하는 상황들이 발생하고 있으니, 앞으로는 이런 상황들이 더더욱 많아질 것이라고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;인간-존재의-본질적-의의는-무엇인가&quot; style=&quot;position:relative;&quot;&gt;인간 존재의 본질적 의의는 무엇인가&lt;a href=&quot;#%EC%9D%B8%EA%B0%84-%EC%A1%B4%EC%9E%AC%EC%9D%98-%EB%B3%B8%EC%A7%88%EC%A0%81-%EC%9D%98%EC%9D%98%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;인간 존재의 본질적 의의는 무엇인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자가 가졌던 문제의식에 대해서 이야기하려면, 지금껏 우리가 무엇 때문에 인간으로 존재할 수 있다고 정의해왔는지부터 살펴봐야한다. “인간이란 무엇인가?”라는 질문은 지난 수천 년 동안 수 많은 철학자들이 탐구해온 주제이다.&lt;/p&gt;
&lt;p&gt;우리는 분명 다른 동물과 구분된 무언가를 가지고 있다는 사실을 알고 있지만, 그게 무엇인지에 대해서는 명확히 알려주는 이가 없었기에 수천 년 동안 스스로 탐구해온 것이다.&lt;/p&gt;
&lt;p&gt;플라톤은 이데아론을 통해 인간은 진리와 이상을 추구하는 존재라고 하였으며, 아리스토텔레스는 인간을 이성적 동물로 정의했다. 데카르트는 “나는 생각한다, 고로 존재한다”라는 명제를 통해 인간의 존재를 사유, 그리고 자아인식과 연결지었다. 칸트는 인간을 자율적이고 도덕적인 판단을 내리는 주체로 정의했으며, 사르트르는 인간이 스스로 자신의 본질을 창조하는 존재라 했다.&lt;/p&gt;
&lt;p&gt;이처럼 수많은 철학자들이 인간의 본질과 존재의 의의에 대해 다양한 정의를 내렸지만, 잘 살펴보면 공통적인 요소들이 몇 가지 있다.&lt;/p&gt;
&lt;p&gt;그 중에서도 가장 두드러지는 공통점은 바로 &lt;strong&gt;자기 성찰과 자아 인식&lt;/strong&gt;이다. 이는 인간이 스스로를 이해하고, 자신의 생각과 행동을 분석하며, 자신의 존재에 대한 깊은 이해를 추구할 수 있는 능력을 뜻한다. 플라톤과 아리스토텔레스의 이성적 사고, 데카르트의 사유와 자아인식, 칸트의 도덕적 자율성, 사르트르의 본질 창조 모두 이러한 자기 성찰과 자아 인식을 중심으로 전개된다.&lt;/p&gt;
&lt;p&gt;즉 인간은 단순히 경험하고 반응하는 존재가 아니라, 자신의 경험을 분석하고 평가하며, 그로부터 새로운 의미와 방향을 찾아내는 존재라고 할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;지금까지의 철학자들이 강조한 인간의 본질적 특징, 자기 성찰과 자아 인식은 인간이 단순한 생물학적 존재를 넘어선 독특한 존재로서의 가치를 지니게 하는 핵심 요소이기 때문에 우리가 이 부분을 AI에게 위임할 가능성이 존재하는 한, 우리는 이 문제에 대해 깊은 고민과 성찰을 통해 들여다봐야 할 필요가 있다.&lt;/p&gt;
&lt;h2 id=&quot;ai는-인간-존재의-본질을-위협하는가&quot; style=&quot;position:relative;&quot;&gt;AI는 인간 존재의 본질을 위협하는가&lt;a href=&quot;#ai%EB%8A%94-%EC%9D%B8%EA%B0%84-%EC%A1%B4%EC%9E%AC%EC%9D%98-%EB%B3%B8%EC%A7%88%EC%9D%84-%EC%9C%84%ED%98%91%ED%95%98%EB%8A%94%EA%B0%80&quot; aria-label=&quot;ai는 인간 존재의 본질을 위협하는가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“ChatGPT를 썼다면 더 잘할 수 있었을 것 같아요”라는 지원자의 답변에서, 필자는 인간이 AI에게 사고를 점점 더 위임하게 됨으로써 발생할 수 있는 위험에 대해 이야기했다. 말 그대로 이 답변은 AI의 도움을 받지 못했기 때문에 과제를 제대로 수행할 수 없었다는 의미로, 인간의 사고 능력이 AI에 의존하게 되는 현상을 보여준다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;인간이 스스로를 이해하고 자신의 생각과 행동을 분석하며, 자신의 존재에 대한 깊은 이해를 추구할 수 있는 능력, 즉 사고와 자기 성찰, 자아 인식이라는 것은 인간의 본질을 규정하는 중요한 요소이다. 이러한 능력들은 인간이 단순한 생물학적 존재를 넘어선 독특한 존재로서의 가치를 지니게 하는 핵심 요소라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 근거를 토대로 필자는 AI가 인간 존재의 본질을 위협할 가능성에 대해 경계할 필요가 있다고 이야기하고 싶다.&lt;/p&gt;
&lt;p&gt;AI가 발전함에 따라 우리는 점점 더 많은 사고 과정을 AI에게 위임하고 있다. 우리가 어떠한 문제를 해결할 때 AI의 도움을 받는 것이 점점 일반화된다면, 스스로 깊이 생각하고 고민하는 과정을 생략하게 될 가능성이 높으며 이는 결국 자기 성찰의 기회를 잃게 만들고 우리의 사고 능력을 제한할 수 있다.&lt;/p&gt;
&lt;p&gt;더 나아가 AI가 인간의 의사결정까지도 점점 대신하게 된다면 인간은 자아 인식의 중요한 요소인 책임감과 자율성을 상실할 위험이 있다. 또한 AI가 내린 의사결정에 의존하게 될수록 우리는 그 결과에 대한 책임을 덜 느끼게 되고, 이는 우리의 도덕적 판단 능력을 약화시킬 수도 있다.&lt;/p&gt;
&lt;p&gt;이렇게 책임감과 도덕적 판단 능력에 대한 이야기는 이미 “자율주행차가 사고를 내면 누구의 책임인가?”와 같은 생활 속의 아젠다로 떠오른지 오래지만, 필자는 아직도 이런 아젠다에 대한 명쾌한 결론은 아무 것도 나오지 않았다는 점을 강조하고 싶다.&lt;/p&gt;
&lt;p&gt;우리는 AI의 발전과 그에 따른 의존도가 높아질수록 우리가 인간으로 정의될 수 있는 본질적인 능력을 잃어버릴 위험에 처하게 될 수도 있다는 사실을 경계해야하는 것이다. 그리고 이러한 경계심에서 비롯된 윤리적 담론은 이 기술을 선도하고 있는 사람들일수록 더더욱 신경써야 한다.&lt;/p&gt;
&lt;h2 id=&quot;지금-프로그래밍을-하고-있는-당신은-누구인가&quot; style=&quot;position:relative;&quot;&gt;지금 프로그래밍을 하고 있는 당신은 누구인가&lt;a href=&quot;#%EC%A7%80%EA%B8%88-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%84-%ED%95%98%EA%B3%A0-%EC%9E%88%EB%8A%94-%EB%8B%B9%EC%8B%A0%EC%9D%80-%EB%88%84%EA%B5%AC%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;지금 프로그래밍을 하고 있는 당신은 누구인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;다들 예상했겠지만 이 기술을 선도하고 있는 사람들은 바로 개발자와 학자들이다. 특히 그 중에서도 AI라는 도메인에 직접적인 기여를 하고 있는 분들일것이다.&lt;/p&gt;
&lt;p&gt;그러나 최근 들어 개발자들 사이에서도 ChatGPT나 Copilot 같은 AI 도구를 사용하며 AI가 제안한 코드를 비판 없이 수용하는 사례가 종종 보인다.&lt;/p&gt;
&lt;p&gt;물론 ChatGPT나 Copilot의 발전은 매우 빠르며, 예전보다 높은 퀄리티의 코드를 출력해내고 있다는 것은 사실이지만, 하지만 현재 시점에서 보았을 때 그것이 완벽하다고 말할 수 있을까?&lt;/p&gt;
&lt;p&gt;아니, 그렇지 않다. AI가 생성한 코드는 때때로 오류를 포함하고 있으며, 특정 상황에서는 완벽한 해결책을 제시하지 못할 때도 있다. 특히 여러 모듈의 맥락을 연결해가며 이해하고 아키텍쳐를 설계해야하는 부분은 아직 AI가 정복하지 못한 문제이다.&lt;/p&gt;
&lt;p&gt;만약 AI가 제안한 코드가 이미 완벽하다면 개발자라는 직업은 이미 사라져야 마땅하다. 그러나 개발자라는 직업이 여전히 존재한다는 사실이 아직 AI의 코드가 완전하지 않다는 사실을 역설하고있다. 앞으로 AI가 발전하면 점점 이 직업에 종사하는 인구가 줄어들지언정 현재로써는 아직 그렇지 않다는 이야기이다.&lt;/p&gt;
&lt;p&gt;그렇다면 이러한 기술에 전문성을 가지고 있는 우리는 어떤 역할을 해야 하는 것일까?&lt;/p&gt;
&lt;p&gt;개발자는 단순히 AI의 출력을 수용하는 것에서 그치지 않고, AI가 생성한 코드를 비판적으로 검토하고 수정해야 한다. 우리는 AI를 도구로써 바라보고 활용해야 하며, 그 도구를 통해 우리의 사고력과 창의성을 극대화해야 한다. AI의 도움을 받더라도, 최종적인 결정과 책임은 우리 자신에게 있다는 것이다.&lt;/p&gt;
&lt;p&gt;할루시네이션이 존재한다는 사실을 뻔히 알면서도 그 코드를 비판적인 검토없이 복붙하거나, AI의 답변이 진실된 것인 것처럼 믿는 것은 아직 시기상조이며, 혹여 AI가 완벽한 답변을 내놓는 순간이 온다고 해도 어디까지나 AI는 도구로써 전문가에게 컨트롤되어야 한다는 사실을 잊어서는 안된다. &lt;small&gt;(AI는 라이브러리이지, 프레임워크가 아니다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;만약 AI의 출력을 비판없이 수용하고 마치 그것이 내 능력인 것처럼 착각하고 있다면, 스스로에게 한번 반문해보자.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;나는 AI라는 도구를 활용하는 인간인가? 아니면 AI가 내놓은 출력물을 IDE에 옮겨담고 있는 존재일 뿐인가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AI는 “내”가 될 수 없다. 우리는 AI의 도움을 받을 수 있지만, 그 도움을 받는 과정에서 스스로 생각하고 판단하는 능력을 잃지 않도록 경계해야한다.&lt;/p&gt;
&lt;p&gt;이러한 질문은 단순히 프로그래밍이라는 문제를 넘어, 인간의 본질에 대한 깊은 성찰을 요구한다. 인간이 본질적으로 자기 성찰과 자아 인식을 통해 스스로를 이해하고 자신의 존재 이유와 삶의 의미를 탐구하는 존재라면, 인간이 아닌 도구의 지시대로 행동하는 것만으로는 인간으로 존재할 수 없기 때문이다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;혹자는 필자의 이런 생각이 시기적으로 너무 이른 생각이라고, 혹은 너무 비약적이라고 이야기할 수도 있다. 하지만 독자 여러분도 아시다시피 AI의 발전 속도는 생각보다 어마무시하며, 특정 분야에서는 10년도 되지 않은 시간 안에 AI가 인간을 넘어선 경우도 존재한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7800e68ab22994055e740f794b98ab78/4b190/graph.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3pRQf//EABYQAAMAAAAAAAAAAAAAAAAAABAgIf/aAAgBAQABBQJKP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABsQAAICAwEAAAAAAAAAAAAAAAABITERQWGB/9oACAEBAAE/IXfCnCwKSdHgR//aAAwDAQACAAMAAAAQAA//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAwADAQAAAAAAAAAAAAABABExIUFhgf/aAAgBAQABPxBLlcJUvQHYBzFS6YhXhXsBbT5M6NPRP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;graph&quot; title=&quot;&quot; src=&quot;/static/7800e68ab22994055e740f794b98ab78/c08c5/graph.jpg&quot; srcset=&quot;/static/7800e68ab22994055e740f794b98ab78/0913d/graph.jpg 160w,
/static/7800e68ab22994055e740f794b98ab78/cb69c/graph.jpg 320w,
/static/7800e68ab22994055e740f794b98ab78/c08c5/graph.jpg 640w,
/static/7800e68ab22994055e740f794b98ab78/4b190/graph.jpg 800w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;수학은 그렇다치고 언어 이해력 부문의 무시무시한 기울기를 보자.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;깃허브에 올라와 있는 AI 관련 프로젝트의 수는 2011년 기준 약 800개에 불과했었으나, 2023년에는 약 180만개로 증가했으며, 같은 기간동안 논문의 수도 약 3배 정도 증가했다.&lt;/p&gt;
&lt;p&gt;필자는 이처럼 기술이 빠르게 발전하는 속도에 비해 우리가 이 기술을 바라보는 시각, 이 기술로 인해 발생할 여러가지 사이드 이펙트에 대한 논의는 아직까지 그 속도에 맞게 발전하지는 않았다고 생각한다.&lt;/p&gt;
&lt;p&gt;AI는 근본적으로 지금까지의 도구와는 궤를 달리한다. 지금까지의 도구는 무슨 짓을 해도 결코 인간을 넘어설 수 없었으며, 그러한 태생적 한계로 인해 아무리 좋은 도구라고 해도 그저 인간을 보조하는 정도에 그쳤다.&lt;/p&gt;
&lt;p&gt;하지만 이미 위 차트에서 볼 수 있듯이 이미 AI는 인간을 넘어서고 있다. 물론 AGI가 등장하려면 시간이 조금 더 걸리겠지만, 적어도 특정 분야에서만큼은 이미 그러하다. 우리는 이 점에 주목해야한다.&lt;/p&gt;
&lt;p&gt;결국 필자가 이야기하고 싶은 것은 우리가 AI라는 편리하고 폭발적인 생산성을 가져다주는 도구를 사용하면서, 나도 모르게 인간으로서의 본질적 가치를 이 도구에게 위임하고 있는 것은 아닌지 돌아보자는 것이다.&lt;/p&gt;
&lt;p&gt;도구는 인간이 주도권을 가지고 활용되기 때문에 도구라고 할 수 있다. 만약 우리가 AI를 사용함으로써 인간으로서의 주체성과 본질적 의의를 잃는다면, 그것을 더 이상 도구라고 할 수 있을까?&lt;/p&gt;
&lt;p&gt;결국 우리가 AI와 함께 더 나은 미래를 만들어 가기 위해서는 이러한 윤리적/철학적 담론이 반드시 동반되어야 하며, 특히 이 기술을 선도하고 있는 사람들이라면 단지 기술의 발전에만 몰두하는 것이 아니라 이러한 논의에도 활발하게 참여하여 우리가 인간으로써 AI라는 좋은 도구를 제대로 활용할 수 있는 세상을 만드는 것에 관심을 가져한다는 사실을 강조하고 싶다.&lt;/p&gt;
&lt;p&gt;이상으로 지금 프로그래밍을 하고 있는 당신은 누구인가 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 10. 자연 변환]]></title><description><![CDATA[필자는 지금까지 카테고리 사이의 구조를 보존하는 사상으로써의 펑터에 대해 이야기하였다. 펑터는 한 카테고리를 다른 카테고리에 포함(Embeds)한다. 이는 결국 펑터가 여러 대상을 하나로 합칠 수는 있지만, 절대 구조를 변형하지는 않는다는 것을 의미한다. 펑터에 대해 이해하는 방법 중 하나는 함자를 사용하여 하나의 카테고리를 다른 카테고리 내부에서 모델링해보는 것이다.]]></description><link>https://evan-moon.github.io/2024/06/01/category-theory-for-programmers-10-natural-transformations/</link><guid isPermaLink="false">20240601-category-theory-for-programmers-10-natural-transformations</guid><pubDate>Sat, 01 Jun 2024 01:21:26 GMT</pubDate><content:encoded>&lt;p&gt;필자는 지금까지 카테고리 사이의 구조를 보존하는 사상으로써의 펑터에 대해 이야기하였다. 펑터는 한 카테고리를 다른 카테고리에 &lt;a href=&quot;/2024/02/27/category-theory-for-programmers-5-products-and-coproducts/#57-%EB%B9%84%EB%8C%80%EC%B9%AD%EC%84%B1asymmetry&quot;&gt;포함(Embeds)&lt;/a&gt;한다. 이는 결국 펑터가 여러 대상을 하나로 합칠 수는 있지만, 절대 구조를 변형하지는 않는다는 것을 의미한다. 펑터에 대해 이해하는 방법 중 하나는 함자를 사용하여 하나의 카테고리를 다른 카테고리 내부에서 모델링해보는 것이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;소스가 되는 카테고리는 대상이 될 카테고리의 일부인 구조적인 모델 또는 청사진 역할을 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c4214ca2fdd7dfbd1bc9f19c3c05ac86/c08c5/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 98.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHvZ1EbCkBYP//EABkQAAMAAwAAAAAAAAAAAAAAAAABEQIQIP/aAAgBAQABBQKmTcJw1r//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAVEQEBAAAAAAAAAAAAAAAAAAABIP/aAAgBAgEBPwFj/8QAFhAAAwAAAAAAAAAAAAAAAAAAACEw/9oACAEBAAY/AhQ//8QAGhABAQEAAwEAAAAAAAAAAAAAAQAREDFBUf/aAAgBAQABPyHEJJ2JfmT3719jgV2L/9oADAMBAAIAAwAAABAEDwD/xAAVEQEBAAAAAAAAAAAAAAAAAAABIP/aAAgBAwEBPxAj/8QAFREBAQAAAAAAAAAAAAAAAAAAESD/2gAIAQIBAT8QRH//xAAeEAACAQQDAQAAAAAAAAAAAAABEQAhMUFxEFFhof/aAAgBAQABPxAjbNiBAgFWfZZECzajikA2IHxKnvghJ0x3AQn/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/c4214ca2fdd7dfbd1bc9f19c3c05ac86/c08c5/1.jpg&quot; srcset=&quot;/static/c4214ca2fdd7dfbd1bc9f19c3c05ac86/0913d/1.jpg 160w,
/static/c4214ca2fdd7dfbd1bc9f19c3c05ac86/cb69c/1.jpg 320w,
/static/c4214ca2fdd7dfbd1bc9f19c3c05ac86/c08c5/1.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;어떤 하나의 카테고리를 다른 카테고리에 포함시키는 방법에는 여러가지가 있을 수 있다. 대표적인 두 방법 중 하나의 방법은 소스 카테고리를 대상 카테고리가 가진 하나의 대상으로 축소시키는 방법, 그리고 다른 방법은 소스 카테고리의 각 대상을 대상 카테고리의 각 대상으로, 소스 카테고리의 각 사상을 대상 카테고리의 각 사상으로 매핑하는 방법이다. 즉, 같은 청사진이라고 해도 여러가지 방법으로 표현될 수 있다는 의미이다. 자연 변환은 이런 방법들을 비교하는 데 큰 도움이 된다. 자연 변환은 펑터들의 펑터적 성질을 보존해주는 특별한 사상이기 때문이다.&lt;/p&gt;
&lt;p&gt;카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 를 매핑하는 두 개의 펑터 &lt;code class=&quot;language-text&quot;&gt;F&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G&lt;/code&gt;를 한번 상상해보자. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 하나의 대상인 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대해서 한번 생각해보자면, 이 펑터들은 두 개의 대상인 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G a&lt;/code&gt;로 매핑될 것이다. 여기서 펑터들의 매핑이라는 말의 의미는 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;G a&lt;/code&gt;로 매핑하는 행위를 의미하는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f698739fc8d3c8896112a676ed3e29b5/c08c5/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 85%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGQABAQEAAwAAAAAAAAAAAAAAAAIDAQQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB93OsjsuBUBYP/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAECEBFC/9oACAEBAAEFAtFLWOOiQq6P/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAFxABAAMAAAAAAAAAAAAAAAAAIQAQIP/aAAgBAQAGPwKDbn//xAAbEAACAgMBAAAAAAAAAAAAAAABEQAxECFBwf/aAAgBAQABPyEiCXyNZAsObTozYjKFSuPGP//aAAwDAQACAAMAAAAQ8AcA/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAGhABAAMBAQEAAAAAAAAAAAAAAREhMQAQ4f/aAAgBAQABPxAQkELivnJjCqaInjIZxxKdCyuvIlZQh1sueCX1Vvxx4//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/f698739fc8d3c8896112a676ed3e29b5/c08c5/2.jpg&quot; srcset=&quot;/static/f698739fc8d3c8896112a676ed3e29b5/0913d/2.jpg 160w,
/static/f698739fc8d3c8896112a676ed3e29b5/cb69c/2.jpg 320w,
/static/f698739fc8d3c8896112a676ed3e29b5/c08c5/2.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;여기서 한 가지 유의해야할 점은 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G a&lt;/code&gt; 모두 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상이라는 것이다. 동일한 카테고리 내의 대상들 사이의 매핑은 카테고리가 가진 특성을 위반해서는 안된다. 우리는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상들 사이에 인위적인 연결을 만들어내는 것이 아니라, 그저 사상이라는 개념을 &lt;em&gt;자연스럽게&lt;/em&gt; 이용하면 되는 것이다.&lt;/p&gt;
&lt;p&gt;즉, 자연 변환은 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;라는 대상으로 인해 발생할 수 있는 사상들 중 &lt;code class=&quot;language-text&quot;&gt;F a → G a&lt;/code&gt;와 같은 하나의 사상을 선택하는 것이라고 볼 수 있다. 이 자연 변환을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(알파: a가 아니다.)라고 부른다면 이 사상은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 성분 또는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α_a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(밑은 알파가 아닌 대상 a이다)라고 불린다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 우리가 신경써야 하는 점은 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상이고, 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α_a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 사상이라는 것이다.&lt;/p&gt;
&lt;p&gt;만약 어떠한 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 기반으로 한 매핑 결과 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G a&lt;/code&gt; 사이에 사상이 존재하지 않는다면, 펑터 &lt;code class=&quot;language-text&quot;&gt;F&lt;/code&gt;와 펑터 &lt;code class=&quot;language-text&quot;&gt;G&lt;/code&gt; 간의 자연 변환 또한 존재할 수 없다는 의미이다.&lt;/p&gt;
&lt;p&gt;물론 이 이야기는 대상에 대한 이야기이므로 펑터가 만들어낼 수 있는 모든 케이스를 커버할 수 있는 것은 아니다. 왜냐하면 펑터들은 대상 뿐 아니라 사상 또한 매핑하기 때문이다. 그렇다면 사상들에 대해서는 자연 변환이 어떻게 작용하는 것일까?&lt;/p&gt;
&lt;p&gt;한번 임의의 사상을 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;라고 해보자. 사상들이 표현하는 매핑 행위는 고정되어있으니, &lt;code class=&quot;language-text&quot;&gt;F&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G&lt;/code&gt; 사이의 어떤 자연 변환에서도 &lt;code class=&quot;language-text&quot;&gt;F f&lt;/code&gt;는 반드시 &lt;code class=&quot;language-text&quot;&gt;G f&lt;/code&gt;로 변환되어야 한다.&lt;/p&gt;
&lt;p&gt;이에 더해 펑터는 이 사상들의 매핑이 가진 특성을 보존해야한다는 제약을 가지고 있기 때문에 자연 변환의 정의 또한 이 제약에 얽매일 수 밖에 없다. 한번 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 두 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 사이에 적용되는 사상 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 생각해보자. 이 사상은 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 두 개의 사상인 &lt;code class=&quot;language-text&quot;&gt;F f&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G f&lt;/code&gt;로 매핑될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 내의 다이어그램을 완성할 수 있는 두 개의 사상을 추가적으로 제공한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
α&lt;span class=&quot;token hvariable&quot;&gt;_b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/baadfd22e8685308e55e728d5cb9234b/c08c5/3.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 82.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGAABAQADAAAAAAAAAAAAAAAAAAIBBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7cJTYC1gJB//xAAZEAADAQEBAAAAAAAAAAAAAAAAAQIRMRD/2gAIAQEAAQUCdCoT0dG4lzyef//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABwQAAEDBQAAAAAAAAAAAAAAAAABESESIDFRkf/aAAgBAQAGPwKBNEDTwpMvZ//EABsQAQACAwEBAAAAAAAAAAAAAAEAERAhMXHR/9oACAEBAAE/IR4xZXsjxAFqyJsBXd21PIeNVPsYeYf/2gAMAwEAAgADAAAAEI8AAP/EABURAQEAAAAAAAAAAAAAAAAAABEg/9oACAEDAQE/EGP/xAAWEQEBAQAAAAAAAAAAAAAAAAABIDH/2gAIAQIBAT8QTI//xAAdEAEAAgEFAQAAAAAAAAAAAAABABFhECExQXGR/9oACAEBAAE/EEFgHK7HyJValJajmBwJ2SimNLALwYirjs0DV9rcdhpg05PJxez/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3&quot; title=&quot;&quot; src=&quot;/static/baadfd22e8685308e55e728d5cb9234b/c08c5/3.jpg&quot; srcset=&quot;/static/baadfd22e8685308e55e728d5cb9234b/0913d/3.jpg 160w,
/static/baadfd22e8685308e55e728d5cb9234b/cb69c/3.jpg 320w,
/static/baadfd22e8685308e55e728d5cb9234b/c08c5/3.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;위 다이어그램을 보면 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;G b&lt;/code&gt;로 가는 방법은 총 두 가지이다. 이 두 가지 방법이 동일한지 확인하려면 모든 f에 대해서 성립할 수 있는 &lt;em&gt;자연성&lt;/em&gt; 조건을 부여해야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; ◦ α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; α&lt;span class=&quot;token hvariable&quot;&gt;_b&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 자연성 조건은 매우 엄격한 제약이라고 볼 수 있다. 예를 들어 사상 &lt;code class=&quot;language-text&quot;&gt;F f&lt;/code&gt;가 가역적이라면 자연성 조건을 통해 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α_a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;만 사용해서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α_b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 결정해버릴 수 있다. 아래와 같이 말이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ◦ α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;^-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5c990e34263308dff03e8d7e9a68fc21/c08c5/4.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 70.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHaVqLAr//EABoQAAICAwAAAAAAAAAAAAAAAAERABIhIjH/2gAIAQEAAQUCeS6ji2RMDn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAACAgMAAAAAAAAAAAAAAAAAERAhMWGh/9oACAEBAAY/AtDfJyWf/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARIUFhcTH/2gAIAQEAAT8ha4N7LqIMXjsvsU2upRRp5MHxfJ//2gAMAwEAAgADAAAAEEjP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAEEH/2gAIAQIBAT8Qp//EAB8QAQACAQMFAAAAAAAAAAAAAAEAEUEhUWFxkaHB0f/aAAgBAQABPxBWTt7h8lONZq4cRiUBuKYMqAdb29xZdCYU+JUbrOmk/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;4&quot; title=&quot;&quot; src=&quot;/static/5c990e34263308dff03e8d7e9a68fc21/c08c5/4.jpg&quot; srcset=&quot;/static/5c990e34263308dff03e8d7e9a68fc21/0913d/4.jpg 160w,
/static/5c990e34263308dff03e8d7e9a68fc21/cb69c/4.jpg 320w,
/static/5c990e34263308dff03e8d7e9a68fc21/c08c5/4.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;만약 두 대상 사이에 여러 개의 가역적인 사상들이 존재한다면, 이 변환들은 모두 이 조건을 만족시켜야한다. 즉, 자연성 조건이 보장되는 상황이라면 어떤 경로를 따라가더라도 결국 동일한 결과에 다다라야 한다는 것이다. 그러나 일반적으로 사상들이 가역적인 경우는 별로 없기 때문에, 두 펑터 간의 자연 변환이 존재한다는 것이 항상 보장되는 것은 아니라고 이야기한 것이다.&lt;/p&gt;
&lt;p&gt;결과적으로는 이런 자연 변환을 통해 여러 펑터들이 작용하는 카테고리의 구조에 대한 많은 정보들을 표현해낼 수 있다. 추후 리미트와 요네다 보조정리에 대해 이야기할 때 이에 대한 몇 가지 예시를 다시 살펴볼 것이다.&lt;/p&gt;
&lt;p&gt;자연 변환을 각 요소 별로 뜯어서 살펴보면 결국 대상을 사상으로 매핑하는 것이라고 말할 수 있다. 자연성 조건으로 인해 사상을 교차하는 사각형 다이어그램으로 매핑한다고 볼 수도 있다는 것이다. 즉, 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 각각의 사상에 대해서 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 이 사상들을 교차하는 자연성 사각형 다이어그램을 가지고 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7d47f98e7bebb1e14efececc63d81552/c08c5/5.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 53.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7mUnDDFf/8QAGBABAQADAAAAAAAAAAAAAAAAADEBAhH/2gAIAQEAAQUC6rEbI//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAAMAAAAAAAAAAAAAAAAAAAAgQf/aAAgBAQAGPwIq/wD/xAAaEAEBAQEAAwAAAAAAAAAAAAABEQAhMUFh/9oACAEBAAE/ITuRezdN4noc7gTHw/cAIE3/2gAMAwEAAgADAAAAEEsP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8QZ//EABwQAQEAAwADAQAAAAAAAAAAAAERACExUWFxkf/aAAgBAQABPxBq62oa+/ubDUeiDzmMNVRRrvuFUOtfbgkqKbFLkwh4M//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;5&quot; title=&quot;&quot; src=&quot;/static/7d47f98e7bebb1e14efececc63d81552/c08c5/5.jpg&quot; srcset=&quot;/static/7d47f98e7bebb1e14efececc63d81552/0913d/5.jpg 160w,
/static/7d47f98e7bebb1e14efececc63d81552/cb69c/5.jpg 320w,
/static/7d47f98e7bebb1e14efececc63d81552/c08c5/5.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;자연 변환이 가진 이러한 성질은 카테고리적인 구성을 할 때 매우 유용하다. 카테고리적인 구성을 할 때 종종 교차 다이어그램이 포함되는 경우가 많은데, 이때 적절한 펑터를 선택함으로써 이러한 교차성 조건을 자연성 조건으로 변환할 수 있다. 이는 추후 극한(limits), 쌍대극한(colimits), 수반(Adjunctions)에 대한 예시를 다룰 때 더 자세히 살펴보도록 하겠다.&lt;/p&gt;
&lt;p&gt;마지막으로 자연 변환은 펑터들의 동형사상을 정의하는 데에도 사용될 수 있다. 두 펑터가 자연적으로 동형이라고 말하는 것은 두 펑터가 거의 같다고 말하는 것과 동일한 말이다. &lt;em&gt;자연 동형성&lt;/em&gt;은 모든 요소가 동형사상인 자연 변환으로 정의된다.&lt;/p&gt;
&lt;h2 id=&quot;101-다형성-함수polymorphic-functions&quot; style=&quot;position:relative;&quot;&gt;10.1 다형성 함수(Polymorphic Functions)&lt;a href=&quot;#101-%EB%8B%A4%ED%98%95%EC%84%B1-%ED%95%A8%EC%88%98polymorphic-functions&quot; aria-label=&quot;101 다형성 함수polymorphic functions permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지 필자는 프로그래밍에서의 펑터(특히 엔도펑터)에 대해서 이야기해왔었다. 이 펑터는 타입을 다른 타입으로 매핑하는 타입 생성자에 해당한다. 또한 함수를 함수로 매핑하기도 하며, 이 매핑은 고계 함수 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;에 의해 구현된다.&lt;/p&gt;
&lt;p&gt;자연 변환을 구성하기 위해서는 대상, 여기서는 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;부터 시작한다. 펑터 &lt;code class=&quot;language-text&quot;&gt;F&lt;/code&gt;는 이 타입을 타입 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;로 매핑할 것이다. 그리고 또 다른 펑터 &lt;code class=&quot;language-text&quot;&gt;G&lt;/code&gt;는 이 타입을 &lt;code class=&quot;language-text&quot;&gt;G a&lt;/code&gt;로 매핑한다. 이때 &lt;code class=&quot;language-text&quot;&gt;alpha&lt;/code&gt;라는 자연 변환의 성분은 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;이며, 이것은 결국 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;G a&lt;/code&gt;로 매핑되는 함수를 의미한다. 이것을 Haskell 의사코드로 표현해보면 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;자연 변환은 모든 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대해 정의되는 다형성 함수라고 할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서 &lt;code class=&quot;language-text&quot;&gt;forall&lt;/code&gt; 키워드는 선택적으로 사용할 수 있으며, 이 키워드를 사용하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;ExplicitForAll&lt;/code&gt; 언어 확장을 활성화해야한다. 일반적으로는 아래와 같이 표현한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 표현은 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 의해 매개변수화된 함수라는 점에 주의하자. 이는 Haskell 구문의 간결함에 대한 또 다른 예시이기도 하다. 만약 C++에서 이와 유사한 구조를 표현하려면 약간 더 복잡해질 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; G&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;F&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서의 다형성 함수와 C++의 일반적인 함수 사이에는 더 깊은 차이가 있으며, 이 차이는 이러한 함수들이 구현되고 타입 검사되는 방식에도 그대로 적용된다. Haskell의 다형성 함수는 모든 타입에 적용될 수 있도록 일관되게 정의되어야한다. 즉, 하나의 공식이 모든 타입에 대해 작동해야한다는 것이다. 이를 *매개변수 다형성(Parametric polymorphism)*이라고 한다.&lt;/p&gt;
&lt;p&gt;C++은 기본적으로 특수 다형성(Ad hoc polymorphism)을 지원한다. 이는 어떤 하나의 템플릿이 반드시 모든 타입에 대해 적용될 수 있도록 정의될 필요는 없다는 것을 의미한다. 주어진 타입에 대해 템플릿이 적용될 수 있는지에 대한 여부는 인스턴스화 타임에 결정며, 이때 타입 매개변수가 구체적인 타입으로 대체된다. 이러한 과정 때문에 타입 검사가 느려지기도 하며, 가끔은 이해하기 어려운 에러 메시지를 만나기도 한다.&lt;/p&gt;
&lt;p&gt;C++에는 함수 오버로딩이나 템플릿 특수화 같은 매커니즘도 존재한다. 이를 통해 하나의 함수가 각기 다른 타입에 맞춰 다른 정의를 제공할 수도 있다. Haskell에서는 이런 기능이 타입 클래스와 타입 패밀리를 통해 제공된다.&lt;/p&gt;
&lt;p&gt;Haskell의 매개변수 다형성은 종종 예상치 못한 결과를 가져오기도 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;F&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;G&lt;/code&gt;는 펑터이며 자연성 조건을 자동으로 만족한다. 이를 카테고리적 표기법으로 나타내면 다음과 같다. (&lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;는 함수 &lt;code class=&quot;language-text&quot;&gt;f :: a -&gt; b&lt;/code&gt;이다)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; ◦ α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; α&lt;span class=&quot;token hvariable&quot;&gt;_b&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서 펑터 &lt;code class=&quot;language-text&quot;&gt;G&lt;/code&gt;의 사상 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;에 대한 작용은 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 사용하여 구현된다. 먼저 명시적인 타입 주석을 사용하여 Haskell 의사 코드로 작성해보겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;fmap_G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;alpha_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;alpha_b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fmap_F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 타입 추론 덕분에 이러한 주석들은 필요하지 않으며, 다음의 등식이 성립할 수 있게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이건 진짜 Haskell 문법이 아니라 의사 코드이다. 함수의 동등성은 코드로 표현할 수 없기 때문이다. 하지만 이런 항등식은 방정식 추론에 이용할 수 있으며, 컴파일러가 최적화를 구현하는 데에도 사용될 수 있다.&lt;/p&gt;
&lt;p&gt;Haskell에서 자연성 조건이 자동으로 성립하는 이유는 “공짜 정리(Theorems for free)와 관련이 있다. Haskell에서 자연 변환을 정의하는데 사용되는 매개변수 다형성은 모든 타입에 대해 작동할 수 있는 하나의 공식을 구현해야한다는 강력한 제한을 부과한다. 이러한 제한은 함수에 대해 방정식 정리를 사용할 수 있도록 만든다. 펑터를 변환하는 함수의 경우 공짜 정리는 자연성 조건을 의미한다.&lt;/p&gt;
&lt;p&gt;Haskell에서 펑터를 다루는 아이디어 중 하나는 바로 펑터를 일반화된 컨테이너로 간주하는 것이다. 비유를 해보자면 펑터는 자연 변환한 컨테이너의 내용을 다른 컨테이너로 다시 포장하는 일종의 레시피라고 볼 수 있다. 우리는 컨테이너 내부 요소 자체를 수정하거나 새로운 요소를 만드는 것과 같은 변화를 가하지 않는다. 단지 그 요소들을 복사하여 새로운 컨테이너에 담을 뿐이다.&lt;/p&gt;
&lt;p&gt;자연성 조건은 내부 요소를 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 통해 먼저 수정하고 나중에 재포장하든, 재포장을 먼저 하고 새로운 컨테이너에서 내부 요소를 수정하든 상관없다는 것을 명시적으로 표현한다. 재포장과 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이라는 두 개의 동작은 마치 “계란을 옮긴다”, “계란을 끓인다”와 같이 직교적(서로 독립적)이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;한번 Haskell에서의 자연 변환을 보여주는 몇 가지 예시를 살펴보도록 하자. 첫 번째 예시는 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 펑터와 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 펑터와의 자연 변환이다. 이 함수는 리스트의 첫 번째 요소를 반환하지만, 만약 리스트가 비어있다면 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;을 반환한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대해 다형적이다. &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 어떤 타입이든 함수는 제한없이 작동하기 때문에 매개변수 다형성을 갖추고 있다고 하는 것이다. 따라서 이 함수는 두 개의 펑터 사이의 자연 변환의 예시가 될 수 있다. 하지만 확실히 짚고 넘어가기 위해 자연성 조건을 한번 검증해보도록 하겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 두 개의 경우를 고려해야한다. 먼저 빈 리스트에 대한 경우를 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 비어있지 않은 리스트에 대해서도 대응해야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;safeHead&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;List 펑터와 Maybe 펑터의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 구현에 대해서도 한번 되짚어보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- List&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- Maybe&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;더 흥미로운 예시는 펑터 중 하나가 단순한 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터인 경우이다. &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터로부터 출발하거나 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터로 향하는 자연 변환은 반환 타입이나 인수 타입 중 하나에 다형성을 가진 함수와 동일하다.&lt;/p&gt;
&lt;p&gt;예를 들어 길이(length)는 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 펑터에서 &lt;code class=&quot;language-text&quot;&gt;Const Int&lt;/code&gt; 펑터로의 자연 변환으로 볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;unConst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;unConst&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 생성자를 제거하는데 사용된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;unConst&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;unConst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 실제 &lt;code class=&quot;language-text&quot;&gt;length&lt;/code&gt;는 아래와 같이 단순하게 정의된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 타입 시그니처는 &lt;code class=&quot;language-text&quot;&gt;length&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 펑터에서 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터로의 자연 변환이라는 사실을 숨기고 있다.&lt;/p&gt;
&lt;p&gt;반면 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터에서 출발하는 매개변수 다형성 함수를 찾는 것은 조금 더 어려운 일이다. 왜냐하면 아무것도 없는 상태에서 값을 생성하기를 요구하기 때문이다. 따라서 우리가 할 수 있는 최선은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;scam&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;scam&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;또 다른 펑터는 예전에 보았던 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터이며, 이 펑터는 요네다 보조정리에서도 중요한 역할을 한다. &lt;code class=&quot;language-text&quot;&gt;newtype&lt;/code&gt; 키워드를 사용하여 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터의 정의를 다시 작성해보겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것은 두 가지 타입으로 매개변수화되지만, 두 번째 유형에 대해서만 공변적으로 펑터적이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;모든 타입 &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt;에 대해서, &lt;code class=&quot;language-text&quot;&gt;Reader e&lt;/code&gt;에서 다른 펑터 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;로의 자연 변환들을 정의할 수도 있다. 나중에 요네다 보조정리에 대한 이야기를 할 때 이 변환들의 구성원들이 항상 &lt;code class=&quot;language-text&quot;&gt;f e&lt;/code&gt;의 요소와 일대일 대응되는 것을 보게될 것이다.&lt;/p&gt;
&lt;p&gt;예를 들어 유닛 타입 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;를 생각해보자. 이 타입은 단 하나의 원소인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;를 가진다. &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터는 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 가져와서 함수 타입 &lt;code class=&quot;language-text&quot;&gt;() -&gt; a&lt;/code&gt;로 매핑한다. 그리고 이 함수는 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 하나의 원소를 선택하는 모든 함수들을 의미한다. 즉, 이 함수들은 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 있는 원소들의 수만큼 존재하는 것이다.&lt;/p&gt;
&lt;p&gt;그럼 이제 이 펑터에서 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 펑터로의 자연 변환을 생각해보겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 자연 변환은 &lt;code class=&quot;language-text&quot;&gt;dumb&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;obvious&lt;/code&gt; 두 가지 함수로 정의된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;dumb&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;obvious&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(어차피 함수 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 할 수 있는 유일한 행위는 값 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;에 적용되는 것 뿐이다.)&lt;/p&gt;
&lt;p&gt;실제로 요네다 보조정리에서 예측된대로 이 두 함수들은 &lt;code class=&quot;language-text&quot;&gt;Maybe ()&lt;/code&gt; 타입의 두 요소들인 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Just ()&lt;/code&gt;에 대응한다. 이에 대해서는 추후 요네다 보조정리를 이야기하며 더 자세히 살펴보도록 하겠다.&lt;/p&gt;
&lt;h2 id=&quot;102-자연성을-넘어beyond-naturality&quot; style=&quot;position:relative;&quot;&gt;10.2 자연성을 넘어(Beyond Naturality)&lt;a href=&quot;#102-%EC%9E%90%EC%97%B0%EC%84%B1%EC%9D%84-%EB%84%98%EC%96%B4beyond-naturality&quot; aria-label=&quot;102 자연성을 넘어beyond naturality permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;두 펑터 사이의 매개변수 다형성 함수는 항상 자연 변환이다. 즉, 모든 표준 대수적 데이터 타입은 펑터이니 이러한 타입들 사이의 모든 다형성 함수는 자연 변환이다.&lt;/p&gt;
&lt;p&gt;또한 우리는 함수 타입을 사용할 수 있으며, 함수 타입은 반환 타입에 대해 펑터적이다. 이를 사용하여 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터와 같은 펑터를 만들고, 고차 함수인 자연 변환을 정의할 수도 있다.&lt;/p&gt;
&lt;p&gt;그러나 함수 타입은 인자 타입에 대해 공변적이지 않으며 반공변적으로 작동한다. 물론 반공변 펑터는 반대 카테고리에서의 공변 펑터와 동등하다. 두 반공변 펑터 사이의 다형성 함수를 카테고리적 의미에서 보았을때는 여전히 자연 변환이다. 단, 이것들은 반대 카테고리에서 Haskell 타입으로 가는 펑터에서 작동한다.&lt;/p&gt;
&lt;p&gt;이전에 보았던 반공변 펑터의 예시를 다시 한번 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 펑터는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대해 반공변적이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 이 펑터를 가지고 &lt;code class=&quot;language-text&quot;&gt;Op Bool&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;Op String&lt;/code&gt;으로 향하는 다형성 함수를 작성해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;predToStr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;T&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;F&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 두 펑터가 모두 공변적이지 않기 때문에, 이것은 &lt;strong&gt;Hask&lt;/strong&gt;에서의 자연 변환이 아니다. 그러나 두 펑터가 모두 반공변적이니, “반대” 자연성 조건을 만족할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;predToStr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;predToStr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;contramap&lt;/code&gt;의 시그니처 때문에 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 사용할 때와는 반대 방향으로 가야한다는 점을 주목하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇다면 공변적이든 반공변적이든 펑터가 아닌 타입 생성자도 있을까? 여기 한 가지 예시가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것은 동일한 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 반공변 위치, 공변 위치 모두에서 사용되기 때문에 펑터가 아니며, 이 타입에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;contramap&lt;/code&gt;을 구현할 수도 없다. 따라서 아래와 같은 시그니처를 가진 함수는 자연 변환이 될 수 없다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;흥미롭게도 이러한 경우를 다루는 자연 변환의 일반화된 형태가 있으며, 이를 이자연 변환(Dinatural transformations)이라고 한다. 이에 대해서는 추후 끝(ends)에 대해 이야기할 때 다시 살펴볼 것이다.&lt;/p&gt;
&lt;h2 id=&quot;103-펑터-카테고리functor-category&quot; style=&quot;position:relative;&quot;&gt;10.3 펑터 카테고리(Functor Category)&lt;a href=&quot;#103-%ED%8E%91%ED%84%B0-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%ACfunctor-category&quot; aria-label=&quot;103 펑터 카테고리functor category permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제 우리는 펑터 간의 사상인 자연 변환에 대해 알게 되었으므로, 펑터만으로 이루어진 카테고리도 존재하는지 대해서 이야기해볼 수 있게 되었다. 그리고 실제로 펑터로만 이루어진 카테고리는 존재한다. 각 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 펑터로만 이루어진 카테고리를 생각해보자. 이 카테고리의 대상은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 펑터이며, 사상은 이 펑터들 사이의 자연 변환일 것이다.&lt;/p&gt;
&lt;p&gt;또한 이미 우리는 사상을 어떻게 합성하는지 알고 있으니, 두 자연 변환의 합성의 정의 또한 쉽게 할 수 있다.&lt;/p&gt;
&lt;p&gt;한번 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 생각해보자. 이때 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 성분은 다음과 같은 사상이 될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 이 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;H&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.08125em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 합성하려고 한다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 성분은 다음과 같은 사상이 될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;β&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;당연히 이 사상들은 합성이 가능하며, 그 합성 결과는 또 다른 사상이 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;β&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; ◦ α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 두 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 합성인 이 사상을 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β ⋅ α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⋅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 성분으로 사용하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;β ⋅ α&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; β&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; ◦ α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/77760305bd4e45023763ece302c8b710/c08c5/6.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 67.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHbVqKGV//EABgQAQEBAQEAAAAAAAAAAAAAAAEAAhAR/9oACAEBAAEFAnUah9tQc//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABUQAQEAAAAAAAAAAAAAAAAAABAR/9oACAEBAAY/Amv/xAAaEAEAAwEBAQAAAAAAAAAAAAABACExERBB/9oACAEBAAE/ISwd+wgtyoAplDjSMa98/9oADAMBAAIAAwAAABAbz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EGf/xAAcEAEBAQACAwEAAAAAAAAAAAABEQAhQVFxgbH/2gAIAQEAAT8QUhII8mXOAUXas6fuTJIMfeH6Rw4yvyoaHjf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;6&quot; title=&quot;&quot; src=&quot;/static/77760305bd4e45023763ece302c8b710/c08c5/6.jpg&quot; srcset=&quot;/static/77760305bd4e45023763ece302c8b710/0913d/6.jpg 160w,
/static/77760305bd4e45023763ece302c8b710/cb69c/6.jpg 320w,
/static/77760305bd4e45023763ece302c8b710/c08c5/6.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;아래 다이어그램을 보면, 이 합성의 결과가 실제로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;H&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.08125em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 자연 변환임을 확인해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;β ⋅ α&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;β ⋅ α&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;_b&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3ab8658c2500dadea960bfb7de8ab5c3/c08c5/7.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 96.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7lWcbpVALg//xAAbEAACAwADAAAAAAAAAAAAAAAAAQIRMRIyQf/aAAgBAQABBQLkWyOeJCVEuscP/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGRAAAgMBAAAAAAAAAAAAAAAAARAAESEx/9oACAEBAAY/AuMzKRf/xAAfEAABAwMFAAAAAAAAAAAAAAABABExIUFxEFFhscH/2gAIAQEAAT8hLCznRhE4W52jARzVEsdchMG9VeJQ40//2gAMAwEAAgADAAAAEDsHAP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAECAQE/EGP/xAAhEAEBAAIBAgcAAAAAAAAAAAABEQAhQRAxYXGBkbHB0f/aAAgBAQABPxC9VwDnyxRvT3YNeuVuEVu6ySKqivvGSM02QXn9wxFPCnABS7fGAFAFF9un/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;7&quot; title=&quot;&quot; src=&quot;/static/3ab8658c2500dadea960bfb7de8ab5c3/c08c5/7.jpg&quot; srcset=&quot;/static/3ab8658c2500dadea960bfb7de8ab5c3/0913d/7.jpg 160w,
/static/3ab8658c2500dadea960bfb7de8ab5c3/cb69c/7.jpg 320w,
/static/3ab8658c2500dadea960bfb7de8ab5c3/c08c5/7.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;자연 변환의 합성은 일반적인 사상과 동일하기 때문에 합성에 대한 결합법칙 또한 만족한다.&lt;/p&gt;
&lt;p&gt;마지막으로 각 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 대해서는 성분이 항등 사상인 항등 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1_F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7944em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;도 존재할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;id_Fa&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;따라서 펑터로만 이루어진 카테고리도 존재한다고 말할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;참고로 이 책에서는 카테고리 이론의 공동 창시자인 사운더스 맥레인(Saunders Mac Lane)의 방식을 따라, 자연 변환의 합성을 점으로 표기하고 있다.&lt;/p&gt;
&lt;p&gt;문제는 자연 변환을 합성하는 방법이 하나가 아니라는 것이다. 이 방법들은 크게 수직 합성과 수평 합성으로 나누어진다. 그 중에서도 수직 합성은 일반적인 다이어그램에서 펑터와 자연 변환이 모두 수직으로 표기되기 때문에 불리는 명칭이며, 이는 펑터 카테고리를 이해할 때 중요한 개념이기도 하다. 또 다른 합성 방법인 수평 합성에 대해서는 다음 섹션에서 마저 설명하도록 하겠다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 623px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea88c3814b829b2a248e93f9300f8566/50112/8.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdlaoUGD/8QAGxAAAgEFAAAAAAAAAAAAAAAAAAIBEBESEyH/2gAIAQEAAQUCdubDKCVuQlP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAACAwEAAAAAAAAAAAAAAAAAEAERITH/2gAIAQEABj8CNXaNlf/EAB0QAQACAgIDAAAAAAAAAAAAAAEAMREhEGFBUXH/2gAIAQEAAT8h1MPmyCFsZx2/JZ1NTCR6lmwb4//aAAwDAQACAAMAAAAQo8//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPxCn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHBABAQADAQADAAAAAAAAAAAAAREAITFhQVHx/9oACAEBAAE/EAAYIrcjz39yzAkAh6C7+8EQLVHTm+ZKPD4nyYzLsYna2d5vJM//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;8&quot; title=&quot;&quot; src=&quot;/static/ea88c3814b829b2a248e93f9300f8566/50112/8.jpg&quot; srcset=&quot;/static/ea88c3814b829b2a248e93f9300f8566/0913d/8.jpg 160w,
/static/ea88c3814b829b2a248e93f9300f8566/cb69c/8.jpg 320w,
/static/ea88c3814b829b2a248e93f9300f8566/50112/8.jpg 623w&quot; sizes=&quot;(max-width: 623px) 100vw, 623px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 간의 펑터 카테고리는 &lt;code class=&quot;language-text&quot;&gt;Fun(C, D)&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;[C, D]&lt;/code&gt;로 표기되며, 때로는 지수 형태인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 표기되기도 한다. 특히 마지막 표기법이 흥미로운데, 이는 펑터 카테고리 자체가 다른 카테고리에서 함수 대상(지수 대상)으로 간주될 수 있음을 암시하고 있기 때문이다. 이에 대해서 한번 알아보자.&lt;/p&gt;
&lt;p&gt;지금까지 우리가 구축해온 추상화 계층들을 한번 살펴보자. 우리는 대상과 사상의 집합인 카테고리에서부터 시작해왔다. 카테고리 자체, 특히 집합의 카테고리인 작은 카테고리는 상위 레벨 카테고리인 &lt;strong&gt;Cat&lt;/strong&gt;(카테고리의 카테고리)에서의 대상이 된다. 그리고 &lt;strong&gt;Cat&lt;/strong&gt;의 사상은 결국 펑터이기 때문에 &lt;strong&gt;Cat&lt;/strong&gt;의 Hom 집합은 펑터들의 집합이 될 것이다. 예를 들어 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Cat(C, D)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 두 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 간의 펑터들의 집합이다.&lt;/p&gt;
&lt;p&gt;펑터 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[C, D]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 역시 사상으로 자연 변환을 가지고 있다는 점만 제외하면 두 카테고리 간의 펑터들의 집합이라고 볼 수 있다. 이 카테고리의 대상은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Cat(C, D)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 원소와 동일하기 때문이다. 게다가 펑터 카테고리 또한 카테고리이기 때문에 &lt;strong&gt;Cat&lt;/strong&gt;의 대상이 되어야 한다. 즉, 우리는 이 관계를 하나의 카테고리 내의 Hom 집합과 대상 간의 관계로 표현할 수 있다는 것이며, 이건 이전 섹션에서 보았던 지수 대상과 정확하게 같은 개념이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4259939dc4841e14f984da03becbf3f3/c08c5/9.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 98.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQADAAAAAAAAAAAAAAAAAAIBAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7aEb0qYIsV//xAAbEAACAgMBAAAAAAAAAAAAAAABAhARABIxIf/aAAgBAQABBQI9DRZoN6vCoOax/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAFxAAAwEAAAAAAAAAAAAAAAAAASAxIf/aAAgBAQAGPwKxMK//xAAaEAADAQADAAAAAAAAAAAAAAAAATEREFFh/9oACAEBAAE/IXcNlGvpTClmkCGiJQQk7fH/2gAMAwEAAgADAAAAECsPvP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABURAQEAAAAAAAAAAAAAAAAAABEQ/9oACAECAQE/EFhP/8QAHhABAAICAgMBAAAAAAAAAAAAAREhADFBsRBRccH/2gAIAQEAAT8QRMlh4q4cOcaAsCIfuCARkck5EQbstxmZhMMutxzrDFCDYO4y5s7++8HUhqKOvH//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;9&quot; title=&quot;&quot; src=&quot;/static/4259939dc4841e14f984da03becbf3f3/c08c5/9.jpg&quot; srcset=&quot;/static/4259939dc4841e14f984da03becbf3f3/0913d/9.jpg 160w,
/static/4259939dc4841e14f984da03becbf3f3/cb69c/9.jpg 320w,
/static/4259939dc4841e14f984da03becbf3f3/c08c5/9.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;한번 &lt;strong&gt;Cat&lt;/strong&gt;에서 이 개념을 어떻게 구성할 수 있는지 살펴보자.&lt;/p&gt;
&lt;p&gt;지수를 구성하기 위해서는 먼저 곱의 개념을 정의해야 한다는 것을 기억할 것이다. 다행히도 &lt;strong&gt;Cat&lt;/strong&gt;에서는 곱을 정의하기가 비교적 쉽다. 각각의 작은 카테고리들은 대상들의 집합이므로, 곱이라는 개념을 집합의 곱으로 생각해도 무방할 것이다. 따라서 곱 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C × D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상은 그냥 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상들 중 하나씩 뽑아내어 구성된 대상들의 쌍 &lt;code class=&quot;language-text&quot;&gt;(c, d)&lt;/code&gt;이다.&lt;/p&gt;
&lt;p&gt;마찬가지로 두 개의 쌍 &lt;code class=&quot;language-text&quot;&gt;(c, d)&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;(c&apos;, d&apos;)&lt;/code&gt; 간의 사상은 사상의 쌍 &lt;code class=&quot;language-text&quot;&gt;(f, g)&lt;/code&gt;으로, 이때 각 사상들은 &lt;code class=&quot;language-text&quot;&gt;f :: c -&gt; c&apos;&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;g :: d -&gt; d&apos;&lt;/code&gt;가 될 것이다. 이러한 사상의 쌍은 성분 별로 합성되고, 항상 항등 사상의 쌍인 항등 쌍 또한 존재할 수 있다. 간단하게 말하자면 &lt;strong&gt;Cat&lt;/strong&gt;은 완전한 데카르트 폐쇄 카테고리이기 때문에 모든 카테고리 쌍에 대한 지수 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 가진다는 의미이다. 이때 &lt;strong&gt;Cat&lt;/strong&gt;의 대상이라는 것은 결국 카테고리를 의미하므로, 결론적으로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 간의 펑터 카테고리라고 말할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;104-2-카테고리&quot; style=&quot;position:relative;&quot;&gt;10.4 2-카테고리&lt;a href=&quot;#104-2-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%AC&quot; aria-label=&quot;104 2 카테고리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Cat&lt;/strong&gt;을 조금 더 자세히 들여다보자. 앞서 언급한 정의에 따라 &lt;strong&gt;Cat&lt;/strong&gt;의 Hom 집합은 펑터들의 집합이다. 하지만 방금 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[C, D]&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 사례에서 보았듯이 두 대상 사이의 펑터는 단순한 집합 이상으로 더 풍부한 구조를 지니고 있다. 자연 변환을 사상으로 적용하여 카테고리를 형성할 수도 있기 때문이다. 펑터는 &lt;strong&gt;Cat&lt;/strong&gt;에서 사상으로 간주되므로, 자연 변환은 사상 간의 사상이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;이처럼 더 풍부한 구조가 바로 2-카테고리의 예로, 2-카테고리에는 대상과 사상(또는 1-사상) 외에도 사상과 사상 간의 사상인 2-사상 또한 존재할 수 있다.&lt;/p&gt;
&lt;p&gt;즉, &lt;strong&gt;Cat&lt;/strong&gt;를 2-카테고리라고 본다면&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;대상&lt;/strong&gt;: 작은 카테고리들&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1-사상&lt;/strong&gt;: 카테고리 간의 펑터&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2-사상&lt;/strong&gt;: 펑터 간의 자연 변환&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;으로 정의할 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 이제 우리는 두 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 간의 Hom 집합 대신에, Hom 카테고리인 펑터 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 가질 수 있게 된다. 그리고 이 펑터들은 합성될 수도 있다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E^D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 합성되어 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G ◦ F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 얻을 수 있는 것처럼 말이다. 또한 각 Hom 카테고리 내에서 자연 변환 또는 2-사상이라고 부르는 수직 합성 또한 가질 수 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c46acab2023857c85a7f9ce461dc859f/c08c5/10.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 80%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGQAAAQUAAAAAAAAAAAAAAAAAAAECAwQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdsSKLIwP//EABkQAAMAAwAAAAAAAAAAAAAAAAABAhESMf/aAAgBAQABBQJ92MlIUilH/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAACAx0f/aAAgBAQAGPwKphD//xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhMXFh/9oACAEBAAE/IU6wHYaxH0qBTs9PiQbL2m+pS2P/2gAMAwEAAgADAAAAEJjv/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFhEBAQEAAAAAAAAAAAAAAAAAABEh/9oACAECAQE/EK1//8QAHRABAAEEAwEAAAAAAAAAAAAAAREAIUFRMWFxsf/aAAgBAQABPxAiPAhbfO6lBOMAkt33U0QOlo7qSWQKmYgoiMmkF04uxn2uBujRgr//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;10&quot; title=&quot;&quot; src=&quot;/static/c46acab2023857c85a7f9ce461dc859f/c08c5/10.jpg&quot; srcset=&quot;/static/c46acab2023857c85a7f9ce461dc859f/0913d/10.jpg 160w,
/static/c46acab2023857c85a7f9ce461dc859f/cb69c/10.jpg 320w,
/static/c46acab2023857c85a7f9ce461dc859f/c08c5/10.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;이제 이렇게 두 종류의 합성이 있는 2-카테고리에서 이 합성 체계들이 어떻게 상호작용하는지를 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;우선 &lt;strong&gt;Cat&lt;/strong&gt;에서 임의로 두 개의 펑터(1-사상)을 선택해보겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;E&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 이들의 합성은 아래와 같을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;E&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 작용하는 두 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;도 있을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;
β &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/26542db3b831313d7518b50db28363fd/c08c5/11.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHbS2AHD//EABoQAQACAwEAAAAAAAAAAAAAAAEAEQIQEiH/2gAIAQEAAQUCWdXBsfZlr//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAAMAAAAAAAAAAAAAAAAAAAEQIP/aAAgBAQAGPwKAv//EABsQAQADAQADAAAAAAAAAAAAAAEAEVEhEEGB/9oACAEBAAE/IWx+RWuPqdyoSl7ALffH/9oADAMBAAIAAwAAABBjz//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/EKf/xAAWEQEBAQAAAAAAAAAAAAAAAAABEBH/2gAIAQIBAT8QTSf/xAAcEAEAAgMAAwAAAAAAAAAAAAABABEhMUEQYeH/2gAIAQEAAT8QxChEaFr8lRZYqO955iOfTpp9kpJsAwwA4+P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;11&quot; title=&quot;&quot; src=&quot;/static/26542db3b831313d7518b50db28363fd/c08c5/11.jpg&quot; srcset=&quot;/static/26542db3b831313d7518b50db28363fd/0913d/11.jpg 160w,
/static/26542db3b831313d7518b50db28363fd/cb69c/11.jpg 320w,
/static/26542db3b831313d7518b50db28363fd/c08c5/11.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;이 쌍에는 수직 합성을 적용할 수가 없다. 왜냐하면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 통해 도달한 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 소스가 아니기 때문이다. 사실 이들은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D^C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E^D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 서로 다른 펑터 카테고리의 멤버이다. 하지만 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 통해 도달한 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 소스이기 때문에 이 두 펑터는 합성할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G ◦ F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;’◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G’◦ F’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 무슨 관계일까? &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 가지고 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G ◦ F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;’◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G’◦ F’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 자연 변환을 정의할 수는 있는 것일까? 다이어그램을 통해 전체적인 구조를 한번 살펴보자.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dc97ff15d263e478db5b98e4123b69ec/c08c5/12.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 72.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMCBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHs4vKLCv/EABkQAQEBAAMAAAAAAAAAAAAAAAEAEQIhMf/aAAgBAQABBQJ9iTY494X/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAXEAADAQAAAAAAAAAAAAAAAAAQICFh/9oACAEBAAY/AtSj/8QAGxABAAICAwAAAAAAAAAAAAAAAQARIWEQMcH/2gAIAQEAAT8hu6uqhbQ0+wAYKhyjk3XF/9oADAMBAAIAAwAAABAbD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB0QAQADAQACAwAAAAAAAAAAAAEAESExQVGBkbH/2gAIAQEAAT8QWxoMKsTvusjDodBS1+bzYBBPaJSLiVT83GS6N6c/IFwftn//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;12&quot; title=&quot;&quot; src=&quot;/static/dc97ff15d263e478db5b98e4123b69ec/c08c5/12.jpg&quot; srcset=&quot;/static/dc97ff15d263e478db5b98e4123b69ec/0913d/12.jpg 160w,
/static/dc97ff15d263e478db5b98e4123b69ec/cb69c/12.jpg 320w,
/static/dc97ff15d263e478db5b98e4123b69ec/c08c5/12.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;가장 먼저 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상인 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 부터 출발해보자. 이 대상의 이미지는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;code class=&quot;language-text&quot;&gt;F a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;F&apos;a&lt;/code&gt;라는 두 대상으로 나누어진다. 그리고 이때 이 두 대상을 연결하는 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 성분인 사상도 함께 생긴다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 갈 때, 이 두 개의 대상은 네 개의 대상으로 나누어진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 이 네 개의 대상을 서로 연결하는 정사각형, 즉 네 개의 사상 또한 생긴다. 그리고 이 사상들 중 두 개는 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 성분이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;β&lt;span class=&quot;token hvariable&quot;&gt;_Fa&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
β&lt;span class=&quot;token hvariable&quot;&gt;_F&lt;/span&gt;’&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 다른 두 개의 사상은 두 펑터에 의한 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α_a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 이미지이다. (펑터는 사상 또한 매핑한다는 사실을 기억하자)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;갑자기 사상이 너무 많아져서 조금 복잡해지긴 했지만, 결국 우리의 목표는 이 중 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G ◦ F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;’◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G’◦ F’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 연결하는 자연 변환의 성분이 될 수 있는 &lt;code class=&quot;language-text&quot;&gt;G (F a)&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;G&apos;(F&apos;a)&lt;/code&gt;로 향하는 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;mtext&gt;◦&lt;/mtext&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(β◦α)_a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 찾는 것이다.&lt;/p&gt;
&lt;p&gt;사실 위 다이어그램을 보면 &lt;code class=&quot;language-text&quot;&gt;G (F a)&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;G&apos;(F&apos;a)&lt;/code&gt;로 가는 경로는 총 두 가지이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt;α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt; ◦ β&lt;span class=&quot;token hvariable&quot;&gt;_Fa&lt;/span&gt;
β&lt;span class=&quot;token hvariable&quot;&gt;_F&lt;/span&gt;’&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; α&lt;span class=&quot;token hvariable&quot;&gt;_a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다행히도 이 두 경로는 같기 때문에 위 다이어그램의 정사각형은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 자연성 정사각형이된다.(다이어그램이 가환한다는 의미이다)&lt;/p&gt;
&lt;p&gt;이렇게 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G ◦ F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mtext&gt;’◦&lt;/mtext&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mtext&gt;’&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G’◦ F’&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’◦&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 자연 변환의 성분을 정의해보았다. 그리고 이 변환의 자연성을 증명하는 것은 귀찮은 과정이기는 하지만 꽤나 간단하게 해결이 가능한 부분이다.&lt;/p&gt;
&lt;p&gt;그리고 이 자연 변환을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;β&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05278em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 수평 합성이라고 부르는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;β ◦ α &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;G&apos;&lt;/span&gt; ◦ &lt;span class=&quot;token constant&quot;&gt;F&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서 이야기했듯 이 책은 맥레인의 표기법을 따르고 있기 때문에, 수평 합성에는 작은 원(&lt;code class=&quot;language-text&quot;&gt;◦&lt;/code&gt;)을 사용한다. 참고로 다른 곳에서는 경우에 따라 별표(&lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt;)를 사용하는 경우도 있다.&lt;/p&gt;
&lt;p&gt;카테고리 이론을 공부할 때의 원칙 중 하나는 어떠한 합성이 있을 때마다 이 합성이 속한 카테고리도 찾아내야 한다는 것이다. 앞서 언급했던 자연 변환의 수직 합성은 펑터 카테고리의 일부였다. 그렇다면 수평 합성은 어떤 카테고리에 속하는 것일까?&lt;/p&gt;
&lt;p&gt;이것을 알아내는 방법은 &lt;strong&gt;Cat&lt;/strong&gt;을 옆으로 보는 것이다. 자연 변환을 펑터 사이의 화살표가 아닌 카테고리 사이의 화살표로 본다. 그럼 이제 자연 변환은 자신이 변환하는 펑터가 연결하는 두 개의 카테고리 사이에 위치한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d1a5bd4e72d167a0a3646612dd7daa24/c08c5/13.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 28.750000000000004%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAGABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdu4SD//xAAWEAADAAAAAAAAAAAAAAAAAAAQEiH/2gAIAQEAAQUCrD//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAEDH/2gAIAQEABj8CKv/EABkQAQACAwAAAAAAAAAAAAAAAAEAQRExcf/aAAgBAQABPyHGhqIpSHZ//9oADAMBAAIAAwAAABAAD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EEn/xAAbEAEAAgIDAAAAAAAAAAAAAAABABEhUWFxkf/aAAgBAQABPxBVUjRvi9eyuCWwIEMp7n//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;13&quot; title=&quot;&quot; src=&quot;/static/d1a5bd4e72d167a0a3646612dd7daa24/c08c5/13.jpg&quot; srcset=&quot;/static/d1a5bd4e72d167a0a3646612dd7daa24/0913d/13.jpg 160w,
/static/d1a5bd4e72d167a0a3646612dd7daa24/cb69c/13.jpg 320w,
/static/d1a5bd4e72d167a0a3646612dd7daa24/c08c5/13.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;p&gt;이제 &lt;strong&gt;Cat&lt;/strong&gt;의 두 대상인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 사이의 사상은 자신들을 연결해주던 펑터들을 연결하는 자연 변환이 되었다. 마찬가지로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 펑터들을 연결하는 자연 변환도 있을테니, 이를 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 새로운 사상으로 간주할 수 있다. 결국 수평 합성은 이러한 관점에서 바라볼 때 사상들의 합성인 것이다.&lt;/p&gt;
&lt;p&gt;또한 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 항등 사상도 있을 것이다. 이때의 항등 사상은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 항등 펑터를 자기 자신으로 매핑하는 항등 자연 변환이다. 수직 합성에서의 항등 자연 변환은 모든 자연 변환의 수직 합성에 대해서 항등 역할을 할 수 있지만, 수평 합성에서는 항상 그렇지만은 않다는 것을 기억해두자.&lt;/p&gt;
&lt;p&gt;마지막으로 두 합성은 교환 법칙을 만족한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;β&apos; ⋅ α&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;β ⋅ α&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;β&apos; ◦ β&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ⋅ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;α&apos; ◦ α&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사운더스 맥레인(Saunders Mac Lane)의 말을 인용하자면 독자들은 이 사실을 증명하기 위해 명확한 다이어그램을 작성하는 것을 즐기게 될지도 모른다고 한다.&lt;/p&gt;
&lt;p&gt;나중에 유용하게 사용할 수 있는 표기법이 하나 더 있다. &lt;strong&gt;Cat&lt;/strong&gt;을 옆에서 바라보겠다는 이 해석에서 어떤 대상에서 다른 대상으로 향하는 방법에는 펑터를 사용하는 방법과 자연 변환을 사용하는 두 가지 방법이 있었다. 이때 이 펑터 화살표를 펑터에 작용하는 특수한 종류의 자연 변환인 항등 자연 변환으로 재해석해볼 수도 있다. 그래서 종종 아래와 같은 표기법을 볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; ◦ α&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 펑터이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 두 펑터 사이의 자연 변환이다. 펑터는 자연 변환과 합성할 수 없기 때문에, 이것은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 작용한 이후 항등 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1_F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7944em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 작용하는 수평 합성으로 해석하게된다.&lt;/p&gt;
&lt;p&gt;이와 마찬가지로 아래 표기는 항등 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1_F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7944em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 작용 이후 자연 변환 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;α&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;α&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0037em;&quot;&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 작용하는 것으로 해석하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;α ◦ &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;105-결론&quot; style=&quot;position:relative;&quot;&gt;10.5 결론&lt;a href=&quot;#105-%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;105 결론 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이렇게 이 책의 첫 번째 파트를 마쳤다. 이제 우리는 카테고리 이론의 기본적인 용어들을 배웠으며, 대상과 카테고리를 명사로 생각하고 사상, 펑터 그리고 자연 변환을 동사로 생각할 수 있는 역량을 얻었다.&lt;/p&gt;
&lt;p&gt;사상은 대상을 연결하고 펑터는 카테고리를 연결하며 자연 변환은 펑터를 연결하는 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 살펴보았듯이 한 수준의 추상화 단계에서는 동사로 보이는 것이 다음 수준에서는 대상이 되기도 한다. 마치 사상의 집합이 함수 대상이 되었던 것처럼 말이다. 그러면 이제 이 대상은 다시 다른 사상의 출발점이나 목표지점이 될 수 있게 된다. 이것이 우리가 알고있는 고차 함수(Higher Order Function)의 아이디어였다.&lt;/p&gt;
&lt;p&gt;펑터는 대상을 대상으로 매핑하기 때문에 이를 타입 생성자 또는 매개변수적 타입으로 사용할 수 있다. 또한 펑터는 사상도 매핑하는데, 이것이 바로 고차 함수인 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이다. &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt;, 곱, 쌍대곱과 같은 간단한 펑터들은 다양한 대수적 데이터 타입을 생성하는데 사용할 수도 있다. 함수 타입 또한 공변 펑터적인 성질과 반공변 펑터적인 성질을 모두 가지고 있으므로 대수적 데이터 타입을 확장하는데 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;펑터는 펑터 카테고리에서 대상으로 간주될 수도 있다. 따라서 펑터는 자연 변환의 출발점과 목표가 되며, 자연 변환은 다형성 함수의 특별한 타입이라고 볼 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 9. 함수 타입]]></title><description><![CDATA[지금까지는 함수 타입의 의미를 간단하게만 설명해왔다. 하지만 조금 더 자세히 들여다보면 함수 타입은 다른 타입과는 약간 다른 특성을 가지고 있다. 예를 들어  타입은 그냥 정수들의 집합, 그리고  타입은 두 개의 원소로 이루어진 집합일 뿐이다. 그러나 함수 타입 은 대상 와  사이에 존재하는 모든 사상들의 집합이다. 어떤 카테고리에서 두 객체 사이의 존재하는 모든 사상들의 집합은 Hom 집합이라고 한다. 그리고 Hom 집합 또한 결국 집합이기 때문에 카테고리 Set(모든 집합의 카테고리)에서는 Hom 집합 또한 Set에 포함된 대상이다.]]></description><link>https://evan-moon.github.io/2024/04/18/category-theory-for-programmers-9-function-types/</link><guid isPermaLink="false">20240418-category-theory-for-programmers-9-function-types</guid><pubDate>Thu, 18 Apr 2024 10:06:52 GMT</pubDate><content:encoded>&lt;p&gt;지금까지는 함수 타입의 의미를 간단하게만 설명해왔다. 하지만 조금 더 자세히 들여다보면 함수 타입은 다른 타입과는 약간 다른 특성을 가지고 있다.&lt;/p&gt;
&lt;p&gt;예를 들어 &lt;code class=&quot;language-text&quot;&gt;Integer&lt;/code&gt; 타입은 그냥 정수들의 집합, 그리고 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt; 타입은 두 개의 원소로 이루어진 집합일 뿐이다. 그러나 함수 타입 &lt;code class=&quot;language-text&quot;&gt;a -&gt; b&lt;/code&gt;은 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 사이에 존재하는 모든 사상들의 집합이다. 어떤 카테고리에서 두 객체 사이의 존재하는 모든 사상들의 집합은 Hom 집합이라고 한다. 그리고 Hom 집합 또한 결국 집합이기 때문에 카테고리 &lt;strong&gt;Set&lt;/strong&gt;(모든 집합의 카테고리)에서는 Hom 집합 또한 &lt;strong&gt;Set&lt;/strong&gt;에 포함된 대상이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/cb189cb187003cfbbbefe5161aefba06/bba1f/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 111.87500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAWABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAIDAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB9rlzGiVVBGgr/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAERAhAS/9oACAEBAAEFAta8t6gmSijENCzOf//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABQQAQAAAAAAAAAAAAAAAAAAADD/2gAIAQEABj8CH//EABgQAQEBAQEAAAAAAAAAAAAAAAERAEEx/9oACAEBAAE/ISCujuBLoqg51nMLqeM3Bgm//9oADAMBAAIAAwAAABBkx7z/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAVEQEBAAAAAAAAAAAAAAAAAAAgIf/aAAgBAgEBPxCj/8QAHBABAAMBAAMBAAAAAAAAAAAAAQARITFBUWGB/9oACAEBAAE/EHBacrKPs2iv7AQSOpgvSC1FKvd/YJXxcQOh7DtgvtEAAcJ//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/cb189cb187003cfbbbefe5161aefba06/c08c5/1.jpg&quot; srcset=&quot;/static/cb189cb187003cfbbbefe5161aefba06/0913d/1.jpg 160w,
/static/cb189cb187003cfbbbefe5161aefba06/cb69c/1.jpg 320w,
/static/cb189cb187003cfbbbefe5161aefba06/c08c5/1.jpg 640w,
/static/cb189cb187003cfbbbefe5161aefba06/bba1f/1.jpg 840w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;Hom 집합도 결국 집합이기 때문에 Set에 포함된 대상이다.&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;&lt;strong&gt;Set&lt;/strong&gt;이 아닌 다른 카테고리에서는 Hom 집합이 카테고리 외부에 있는 경우도 있다. 이런 경우 외부(External) Hom 집합이라고 한다.&lt;/p&gt;
&lt;p&gt;이것이 바로 함수 타입을 다른 타입보다 특별하게 만드는 카테고리 &lt;strong&gt;Set&lt;/strong&gt;의 자기 참조적인 성격이다. 이런 카테고리에서는 Hom 집합을 나타내는 대상을 구성할 수 있는 방법이 존재하며, 이러한 대상을 내부(Internal) Hom 집합이라고 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/42654a7df0869c5e40df37dc0c04c694/232db/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 117.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAYABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHstILUJzI2Ff/EABoQAQACAwEAAAAAAAAAAAAAAAEAAhARIRL/2gAIAQEAAQUCtfyttQecgjhlaax//8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAFBABAAAAAAAAAAAAAAAAAAAAMP/aAAgBAQAGPwIf/8QAHRAAAgIBBQAAAAAAAAAAAAAAAAERITEQQVFhof/aAAgBAQABPyGIVueBez0cw7dmJMCyibp//9oADAMBAAIAAwAAABCUyPz/xAAWEQEBAQAAAAAAAAAAAAAAAAAQEUH/2gAIAQMBAT8Qwp//xAAWEQEBAQAAAAAAAAAAAAAAAAAREAH/2gAIAQIBAT8Qhiz/xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhMRBRcYH/2gAIAQEAAT8QBQJ/EEbTi8QTUbht34I0jSmnBuACjUWo6SXKG6zx/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/42654a7df0869c5e40df37dc0c04c694/c08c5/2.jpg&quot; srcset=&quot;/static/42654a7df0869c5e40df37dc0c04c694/0913d/2.jpg 160w,
/static/42654a7df0869c5e40df37dc0c04c694/cb69c/2.jpg 320w,
/static/42654a7df0869c5e40df37dc0c04c694/c08c5/2.jpg 640w,
/static/42654a7df0869c5e40df37dc0c04c694/232db/2.jpg 819w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;카테고리 C의 Hom 집합은 외부 Hom 집합이다.&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;h2 id=&quot;91-보편적-구성universal-construction&quot; style=&quot;position:relative;&quot;&gt;9.1 보편적 구성(Universal Construction)&lt;a href=&quot;#91-%EB%B3%B4%ED%8E%B8%EC%A0%81-%EA%B5%AC%EC%84%B1universal-construction&quot; aria-label=&quot;91 보편적 구성universal construction permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자, 이제 함수 타입이 집합이라는 사실은 잠시 잊고, 함수 타입을 일반화하여 내부 Hom 집합이라고 생각해서 처음부터 구성해보도록 하자. 일반적으로는 &lt;code class=&quot;language-text&quot;&gt;Set&lt;/code&gt; 카테고리가 이 구성에 대한 단서를 주겠지만, 여기서는 집합의 특성에 의존하지 않고 생각해볼 것이다. 이런 과정을 통해 하나의 구성이 다른 카테고리에 자동으로 적용될 수 있도록 일반화해볼 수 있다.&lt;/p&gt;
&lt;p&gt;함수 타입은 인수 타입과 결과 타입과의 관계로 인해 복합적인 타입으로 간주된다. 이미 우리는 &lt;a href=&quot;/2024/02/27/category-theory-for-programmers-5-products-and-coproducts/&quot;&gt;곱 타입과 합 타입&lt;/a&gt;이라는 대상 간의 관계를 포함하는 복합적인 타입들을 정의하기 위한 보편적 구성(Universal Construction)에 대해서 배웠던 적이 있다. 함수 타입을 정의하는 데도 동일한 방법을 사용해볼 수 있다.&lt;/p&gt;
&lt;p&gt;함수 타입을 정의하기 위해서는 구성하려는 함수 타입, 인수 타입, 결과 타입을 모두 포함하는 패턴이 필요하다.&lt;/p&gt;
&lt;p&gt;이 세 가지 타입을 연결하는 명확한 패턴은 함수 적용(Function application) 또는 평가(Evaluation)이라고 불린다. 만약 함수 타입의 후보인 대상을 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;라고 하고 인수 타입인 대상을 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;라고 할 때, 적용(Application)은 이 쌍을 결과 타입인 대상 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 매핑하는 행위이다. 즉, 우리에게는 총 세 가지 대상이 있으며, 이 중 인수 타입과 결과 타입 두 가지는 고정되어있는 것이다.&lt;/p&gt;
&lt;p&gt;우리는 매핑인 적용도 가지고 있다. 어떻게 하면 이 매핑을 이 패턴에 통합할 수 있을까? 만약 우리가 대상 내부를 들여다볼 수 있다면, 집합 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;의 원소인 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;와 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 원소인 인수 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;를 짝지어 집합 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 원소인 &lt;code class=&quot;language-text&quot;&gt;f x&lt;/code&gt;로 매핑할 수 있게 된다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8d0e9053a062a17fd43fa807d4d4d315/a847c/3.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 87.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAGAABAQADAAAAAAAAAAAAAAAAAAMBAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7NJoswoDYH//xAAYEAEAAwEAAAAAAAAAAAAAAAABAAIQIv/aAAgBAQABBQJt1lll1hHf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGBAAAgMAAAAAAAAAAAAAAAAAABAgISL/2gAIAQEABj8CdGY//8QAGRABAQEBAQEAAAAAAAAAAAAAAREAECEx/9oACAEBAAE/IWATzSYbgwGhI93xwHP/2gAMAwEAAgADAAAAEHQPAP/EABURAQEAAAAAAAAAAAAAAAAAABEg/9oACAEDAQE/ECP/xAAVEQEBAAAAAAAAAAAAAAAAAAARIP/aAAgBAgEBPxBGP//EABwQAQACAgMBAAAAAAAAAAAAAAEAESExEEFhUf/aAAgBAQABPxC2pRkPdMtosqe9xVJ+p50wLo7JYQuaUuagEyECtHH/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3&quot; title=&quot;&quot; src=&quot;/static/8d0e9053a062a17fd43fa807d4d4d315/c08c5/3.jpg&quot; srcset=&quot;/static/8d0e9053a062a17fd43fa807d4d4d315/0913d/3.jpg 160w,
/static/8d0e9053a062a17fd43fa807d4d4d315/cb69c/3.jpg 320w,
/static/8d0e9053a062a17fd43fa807d4d4d315/c08c5/3.jpg 640w,
/static/8d0e9053a062a17fd43fa807d4d4d315/a847c/3.jpg 846w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;함수 집합 z에서 함수 f를 선택하고, 인수 타입 a의 집합에서 하나의 인수 x를 선택한다.&lt;br&gt;그러면 이제 집합 b에서 원소 f x를 얻을 수 있게된다.&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;그러나 이렇게 하나의 쌍인 &lt;code class=&quot;language-text&quot;&gt;(f, x)&lt;/code&gt;를 다루는 것보다는 함수 타입 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;와 인수 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 전체적인 곱에 대해서 이야기하는 것이 더 일반화된 개념일 것이다. 곱 &lt;code class=&quot;language-text&quot;&gt;z×a&lt;/code&gt; 또한 하나의 대상이며, 이 대상에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로의 화살표인 우리의 적용 변형으로 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;를 선택할 수 있다. &lt;strong&gt;Set&lt;/strong&gt;에서는 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 모든 쌍 &lt;code class=&quot;language-text&quot;&gt;(f, x)&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;f x&lt;/code&gt;로 매핑하는 함수가 될 것이다.&lt;/p&gt;
&lt;p&gt;두 대상 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 곱이 사상 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;에 의해 다른 대상 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 연결되는, 이것이 바로 패턴이다.&lt;/p&gt;
&lt;p&gt;정말 이 패턴이 보편적 구성을 통해 함수 타입을 명확하게 정의할 수 있는 것일까? 사실 모든 카테고리에 대해서 생각해본다면 그렇지 않을 수도 있다. 하지만 우리가 지금 다루고자 하는 카테고리에 대해서는 충분하다.&lt;/p&gt;
&lt;p&gt;그렇다면 또 다른 질문을 해보자. 과연 우리는 곱을 먼저 정의하지 않고도 함수 대상을 정의할 수 있을까? 모든 쌍의 대상에 대해 곱이 없는 카테고리나 모든 쌍의 곱이 존재하지 않는 카테고리도 있지 않은가? 정답은 “아니다”이다. 곱 타입이 없다면 함수 타입도 존재할 수 없다. 이에 대한 내용은 추후 지수(Exponentials)에 대해 설명하며 다시 다루도록 하겠다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4848023ae6caa38a3db6fb74b2138af9/c222a/4.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 57.50000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAexqolQ//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAECERASIf/aAAgBAQABBQLZnSLtON5//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAHRAAAgIBBQAAAAAAAAAAAAAAAAERITEQQVFhkf/aAAgBAQABPyFsnpwco2wMsTQjOfRUtP/aAAwDAQACAAMAAAAQ08//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEBAAICAwAAAAAAAAAAAAABEQAhEDFRgbH/2gAIAQEAAT8QChg6Q7mWCE9lyiUGbJca3nwR8wAB0a4//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;4&quot; title=&quot;&quot; src=&quot;/static/4848023ae6caa38a3db6fb74b2138af9/c08c5/4.jpg&quot; srcset=&quot;/static/4848023ae6caa38a3db6fb74b2138af9/0913d/4.jpg 160w,
/static/4848023ae6caa38a3db6fb74b2138af9/cb69c/4.jpg 320w,
/static/4848023ae6caa38a3db6fb74b2138af9/c08c5/4.jpg 640w,
/static/4848023ae6caa38a3db6fb74b2138af9/c222a/4.jpg 794w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이 그림이 바로 보편적 구성의 시작점인 대상과 사상의 패턴이다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;한번 보편적 구성에 대해 검토해보자. 우선 대상과 사상의 패턴에서부터 시작할 것이다. 물론 그저 대상과 사상의 패턴이라고만 하면 굉장히 많은 결과가 매칭될 것이기 때문에 이대로는 상당히 부정확한 쿼리라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Set&lt;/strong&gt;에서는 거의 모든 것이 서로 연결되어있다. 어떤 대상 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;와 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 곱을 형성할 수도 있으며, 이 곱에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로의 함수도 존재할 수 있다. (단, &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;가 빈 집합일 경우는 제외한다.)&lt;/p&gt;
&lt;p&gt;이제 이 패턴의 결과들에 대한 순위를 매긴다는 비밀무기를 꺼내볼 차례이다. 일반적으로 후보 대상들 사이에는 이 구성을 어떤 방식이로든 분해할 수 있는 고유한 매핑이 있어야 한다.&lt;/p&gt;
&lt;p&gt;필자는 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;z×a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 향하는 사상 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;z&apos;&lt;/code&gt;와 이에 적용되는 사상 &lt;code class=&quot;language-text&quot;&gt;g’&lt;/code&gt;보다 우수하다고 결정할 것이다. 그리고 만약 이 결정이 참이라면 &lt;code class=&quot;language-text&quot;&gt;z&apos;&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;로 향하는 유일한 사상 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;이 존재해야 할 것이다. 그리고 이 사상은 &lt;code class=&quot;language-text&quot;&gt;g&apos;&lt;/code&gt;를 적용한 결과와 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;를 적용한 결과가 동일하다는 것 또한 보장해야한다. (잘 이해되지 않는다면 아래 그림을 보면서 이 문장을 읽어보자.)&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d7e642209529d3ac993be63af211510a/d4b53/5.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 80%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdqkqDCh/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERAhD/2gAIAQEAAQUCd7oQlD//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAIDH/2gAIAQEABj8CWn//xAAcEAEAAgEFAAAAAAAAAAAAAAABABFBECFRYYH/2gAIAQEAAT8hVniDsaF78gaLcRBlP//aAAwDAQACAAMAAAAQs8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAWEQADAAAAAAAAAAAAAAAAAAABEDH/2gAIAQIBAT8QEX//xAAaEAEBAAMBAQAAAAAAAAAAAAABEQAhMRCh/9oACAEBAAE/EGiUKRHuLsOnb45ey0LvzFWONTdxwK2prmf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;5&quot; title=&quot;&quot; src=&quot;/static/d7e642209529d3ac993be63af211510a/c08c5/5.jpg&quot; srcset=&quot;/static/d7e642209529d3ac993be63af211510a/0913d/5.jpg 160w,
/static/d7e642209529d3ac993be63af211510a/cb69c/5.jpg 320w,
/static/d7e642209529d3ac993be63af211510a/c08c5/5.jpg 640w,
/static/d7e642209529d3ac993be63af211510a/d4b53/5.jpg 853w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;함수 대상에 대한 후보들 간의 순위를 결정한다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;여기가 조금 어려운 부분인데, 이게 바로 필자가 이 보편적 구성에 대한 정의를 계속 질질 끌고 있던 이유이다. 사상 &lt;code class=&quot;language-text&quot;&gt;h :: z&apos;-&gt; z&lt;/code&gt;가 주어졌을 때 우리는 &lt;code class=&quot;language-text&quot;&gt;z’&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;가 모두 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 연결되어있는 다이어그램을 닫기를 원한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다이어그램을 닫는다는 이야기가 이해하기 어렵다면, 자료구조 그래프를 떠올려보면 된다. 여기서 &lt;code class=&quot;language-text&quot;&gt;z’&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;가 모두 연결되어있는 다이어그램을 닫고 싶다는 의미는, &lt;code class=&quot;language-text&quot;&gt;z→a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;z’→a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;z’→z&lt;/code&gt;처럼 연결되어있고 다른 대상들과는 이어지지 않은 그래프를 만들고 싶다는 의미이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이를 위해 필요한 것은 &lt;code class=&quot;language-text&quot;&gt;z’&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;로 향하는 매핑 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;가 주어졌을 때, 이를 이용해서 &lt;code class=&quot;language-text&quot;&gt;z&apos;×a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;z×a&lt;/code&gt;로의 매핑을 얻어내는 것이다. 앞서 &lt;a href=&quot;/2024/04/02/category-theory-for-programmers-8-functoriality/&quot;&gt;곱의 함수적인 특징&lt;/a&gt;에 대해 논의했었으니, 이제 이 과정에 대해 이해할 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;곱 자체는 펑터, 정확하게는 엔도 이항 펑터이기 때문에 쌍에 대한 사상을 리프팅할 수 있다. 다른 말로 하면 우리는 대상의 곱 뿐만 아니라 사상의 곱도 정의할 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;이를 리프팅하기 위해 곱 &lt;code class=&quot;language-text&quot;&gt;z&apos;×a&lt;/code&gt;의 두 번째 구성 요소인 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에는 아무런 영향을 끼치지 않아야 하므로, &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대한 항등사상인 &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;를 사용하여 사상의 쌍 &lt;code class=&quot;language-text&quot;&gt;(h, id)&lt;/code&gt;를 리프팅할 것이다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;g’&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 포함된 식으로 인수 분해하는 방법은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; × &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서의 핵심은 곱이 사상에 대해서 어떻게 작용하고 있는지를 보는 것이다.&lt;/p&gt;
&lt;p&gt;보편적 구성의 세 번째 파트는 보편적으로 가장 좋은 대상을 선택하는 것이었다. 필자는 이 대상을 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;라고 부를 것이다. (참고로 이건 어떤 대상에 대한 상징적인 이름이며, Haskell 타입 클래스 제약과는 관련없는 네이밍이다. 추후에 조금 더 다양한 방법으로 이름을 지을 수 있는 방법에 대해 논의해보겠다.)&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;라는 대상은 &lt;code class=&quot;language-text&quot;&gt;(a ⇒ b) × a&lt;/code&gt; 에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 향하는 사상인 &lt;code class=&quot;language-text&quot;&gt;eval&lt;/code&gt;이라는 적용을 가지고 있다. 만약 다른 함수 대상 후보로부터 출발하는 사상 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;eval&lt;/code&gt;을 포함한 식으로 분해되어 이 대상에 유일하게 매핑될 수 있다면, 대상 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;가 가장 적합한 후보라고 할 수 있을 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/36c0f5325a8dadf4bf7dcae580413720/edf8d/6.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 76.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHt1CNUq//EABkQAAIDAQAAAAAAAAAAAAAAAAABAhExIf/aAAgBAQABBQJ6sJIUeUf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAQICH/2gAIAQEABj8CSj//xAAcEAACAgIDAAAAAAAAAAAAAAABEQAhUZEQMUH/2gAIAQEAAT8hZrqMOBSznE6j7gEenc//2gAMAwEAAgADAAAAEBsP/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8Qh//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/ECf/xAAcEAEBAAMAAwEAAAAAAAAAAAABEQAhMUFRscH/2gAIAQEAAT8QDr4QDtxEsS++GDeZuhNAI/cdQVdcfMuza3H/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;6&quot; title=&quot;&quot; src=&quot;/static/36c0f5325a8dadf4bf7dcae580413720/c08c5/6.jpg&quot; srcset=&quot;/static/36c0f5325a8dadf4bf7dcae580413720/0913d/6.jpg 160w,
/static/36c0f5325a8dadf4bf7dcae580413720/cb69c/6.jpg 320w,
/static/36c0f5325a8dadf4bf7dcae580413720/c08c5/6.jpg 640w,
/static/36c0f5325a8dadf4bf7dcae580413720/edf8d/6.jpg 929w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이것이 보편적 구성을 통한 함수 대상의 정의이다. 위 그림과 동일한 다이어그램이지만 이제 대상 a ⇒ b가 가장 보편적이게 되었다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;한번 정리해보자.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 향하는 &lt;strong&gt;함수 대상&lt;/strong&gt;은 대상 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;와 사상 &lt;code class=&quot;language-text&quot;&gt;eval :: ((a ⇒ b) × a) -&gt; b&lt;/code&gt; 으로 정의된다. 만약 임의의 다른 대상 &lt;code class=&quot;language-text&quot;&gt;z × a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 향하는 사상 &lt;code class=&quot;language-text&quot;&gt;g :: z × a -&gt; b&lt;/code&gt;가 주어진다면, &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;로 향하는 유일한 사상 &lt;code class=&quot;language-text&quot;&gt;h :: z -&gt; (a ⇒ b)&lt;/code&gt;이 존재해야하고, 최종적으로 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;eval&lt;/code&gt;을 포함한 식으로 분해될 수 있어야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eval&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; × &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 모든 카테고리에서 반드시 임의의 대상의 쌍 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에 대해 대상 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;가 반드시 존재할 것이라는 보장은 없다. 하지만 최소한 &lt;strong&gt;Set&lt;/strong&gt;에서만큼은 항상 존재한다. 게다가 이 대상은 Set의 Hom 집합인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Set(a,b)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와도 동형이다.&lt;/p&gt;
&lt;h2 id=&quot;92-커링currying&quot; style=&quot;position:relative;&quot;&gt;9.2 커링(Currying)&lt;a href=&quot;#92-%EC%BB%A4%EB%A7%81currying&quot; aria-label=&quot;92 커링currying permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;함수 대상에 대한 후보를 다시 한번 살펴보자. 그러나 이번에는 사상 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;를 두 변수 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대한 함수로 생각해볼 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt; × &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;대상의 곱으로부터 출발한 사상은 두 개의 변수를 가진 함수와 유사한 형태를 가지고 있다. &lt;strong&gt;Set&lt;/strong&gt;에서 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;는 집합 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;과 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 값을 하나씩 가져와 구성한 쌍에서 출발하게 될 것이다.&lt;/p&gt;
&lt;p&gt;그리고 함수 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 가진 보편적인 속성에 따라 각각의 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;에 대해 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;를 함수 대상 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt;로 매핑하는 유일한 사상 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt; 또한 존재한다는 것을 떠올려볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Set&lt;/strong&gt;에서는 단순히 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;가 타입이 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;인 변수를 하나 받아 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 향하는 함수를 반환하는 함수임을 의미한다. 이러한 정의는 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;를 고차함수(Higher ordered function)로 만든다.&lt;/p&gt;
&lt;p&gt;따라서 보편적 구성은 이변수 함수와 함수를 반환하는 일변수 함수 간의 일대일 대응을 설정한다. 이 대응은 커링(Currying)이라고 불리며, &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;의 커링된(Curried) 버전이라고 한다.&lt;/p&gt;
&lt;p&gt;이처럼 어떤 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 주어졌을때 유일한 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;가 존재하고, 어떤 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;가 주어질 때도 아래의 공식을 이용하여 이변수 함수인 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;를 다시 생성할 수 있기 때문에 일대일 대응이라고 할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eval&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; × &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 함수 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;의 커링되지 않은(Uncurried) 버전이라고 할 수 있다. 사실 커링은 함수가 함수를 반환하는 Haskell의 구문만으로도 표현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 문법은 보통 아래와 같이 괄호가 제거된 시그너치를 통해 이변수 함수로 해석된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 해석은 다인수 함수를 정의할 때 명확하게 확인해볼 수 있다. 예를 들어 아래와 같은 함수처럼 말이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;catstr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;catstr&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 하나의 인수를 받아 다시 함수를 반환하는 형태로도 작성할 수 있다. 만약 람다로 표현하면 다음과 같을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;catstr&apos;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;s&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 두 정의는 동등하며, 두 정의 중 어떤 것을 사용하든 하나의 인수에 대해 부분 적용되어 아래와 같이 하나의 인수를 받은 함수를 생성할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;greet&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;greet&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;catstr&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello &quot;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;엄밀히 말하자면 이변수 함수는 곱 타입인 쌍을 받는 함수이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 두 개의 표현 간의 변환은 간단하다. 이미 예상했겠지만 이러한 변환을 수행하는 두 개의 고차함수는 &lt;code class=&quot;language-text&quot;&gt;curry&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;uncurry&lt;/code&gt;로 불린다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;uncurry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;uncurry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;curry&lt;/code&gt;가 함수 대상의 보편적 구성을 위한 인수분해(factorization)라는 점에 주목하자. 이 점은 아래와 같은 형태로 다시 작성해보면 더 명확하게 알 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다시 한번 짚고 넘어가자면 &lt;code class=&quot;language-text&quot;&gt;factorizer&lt;/code&gt;라는 인수분해 행위는 후보로부터 분해 함수를 생성한다.&lt;/p&gt;
&lt;p&gt;C++과 같이 함수형 언어가 아닌 언어에서도 커링이 가능하기는 하지만 일이 조금 복잡해진다. C++에서의 다인수 함수는 Haskell에서 튜플을 받는 함수에 해당한다고 볼 수 있다. (여기서 더 혼란스러운 점은 C++에서 명시적으로 &lt;code class=&quot;language-text&quot;&gt;std::tuple&lt;/code&gt;을 받는 함수, 가변 인수 함수, 초기화 리스트를 받는 함수를 정의할 수 있다는 점이다.)&lt;/p&gt;
&lt;p&gt;C++ 함수를 부분 적용하려면 템플릿 &lt;code class=&quot;language-text&quot;&gt;std::bind&lt;/code&gt;를 사용하면 된다. 예를 들어 아래와 같이 두 개의 문자열을 받는 함수가 있다고 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string &lt;span class=&quot;token function&quot;&gt;catstr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s1 &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; s2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그럼 이 함수와 &lt;code class=&quot;language-text&quot;&gt;std::bind&lt;/code&gt;를 사용하여 하나의 문자열을 받는 함수를 정의해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;placeholders&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; greet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;catstr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;greet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Haskell Curry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Scala는 C++이나 Java에 비하면 함수형 프로그래밍에 더 가깝긴 하지만, 사실은 애매한 어딘가에 위치하고 있다. 만약 함수가 부분 적용되도록 작성하려면 아래처럼 여러 인수의 목록으로 정의할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scala&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-scala line-numbers&quot;&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; catstr&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s1 &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; s2&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 이 코드는 이 함수가 확실히 부분 적용될 것이라는 것을 가정하기 때문에 프로그래머의 예지력에 의존하고 있지만 말이다.&lt;/p&gt;
&lt;h2 id=&quot;93-지수exponentials&quot; style=&quot;position:relative;&quot;&gt;9.3 지수(Exponentials)&lt;a href=&quot;#93-%EC%A7%80%EC%88%98exponentials&quot; aria-label=&quot;93 지수exponentials permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;수학 논문에서 함수 대상 또는 두 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 사이의 내부 Hom 대상은 종종 지수(Exponential)로 불리며 &lt;code class=&quot;language-text&quot;&gt;ba&lt;/code&gt;라고 표기된다. 처음에는 이 표기법이 조금 어색해보일 수 있지만, 함수와 곱의 관계를 생각해보면 그렇게 이상한 것도 아니다. 이미 내부 Hom 대상의 보편적 구성에서 곱이 필요하다는 것을 한 차례 확인했지만, 사실 이 둘 간의 연결은 더 심오하다.&lt;/p&gt;
&lt;p&gt;이 연결은 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Char&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Double&lt;/code&gt;과 같이 유한한 값을 가지는 집합 간의 함수를 고려해볼 때 제대로 확인해볼 수 있다. 이러한 함수들은 원론적으로 완전히 메모아이징(Memoizing)될 수 있거나 데이터 구조로 변환되어 조회될 수도 있다. 이것이 바로 사상으로써의 함수와 대상으로써의 함수 타입 간 동등성의 본질이다.&lt;/p&gt;
&lt;p&gt;예를 들어 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;에서의 순수 함수는 &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt;에 해당하는 값과 &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;에 해당하는 값의 쌍에 의해 완전히 특정화된다. &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;로 향하는 모든 함수의 집합은 모든 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt; 쌍들의 집합이다. 이것은 곱 &lt;code class=&quot;language-text&quot;&gt;Int × Int&lt;/code&gt;, 조금 더 창의적으로 표기해보자면 &lt;code class=&quot;language-text&quot;&gt;Int2&lt;/code&gt;와 동일하다.&lt;/p&gt;
&lt;p&gt;다른 예시로 C++의 타입인 &lt;code class=&quot;language-text&quot;&gt;char&lt;/code&gt;를 한번 살펴보자. 이 타입은 총 256개의 값을 포함하고 있다.&lt;/p&gt;
&lt;p&gt;C++ 표준 라이브러리의 &lt;code class=&quot;language-text&quot;&gt;isupper&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isspace&lt;/code&gt;와 같은 일부 함수들은 테이블 조회를 사용하여 구현되며, 이 테이블은 256개의 부울 값들의 튜플과 동등하다. 튜플은 곱 타입이므로 우리는 &lt;code class=&quot;language-text&quot;&gt;bool × bool × bool × ... × bool&lt;/code&gt;과 같은 256개의 부울의 곱을 떠올려볼 수 있다.&lt;/p&gt;
&lt;p&gt;그리고 우리는 이렇게 반복적인 곱이 곧 지수(Exponential)을 정의한다는 사실을 알고 있다. 만약 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;char&lt;/code&gt; 타입이 가진 값의 개수인 256번만큼 곱한다면, &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;char&lt;/code&gt;만큼 거듭제곱한 것, 즉, &lt;code class=&quot;language-text&quot;&gt;boolchar&lt;/code&gt;를 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;의 256 튜플로 정의된 타입에는 얼마나 많은 값이 존재하는 것일까? 정확하게 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^{256}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;256&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개이다. 이는 &lt;code class=&quot;language-text&quot;&gt;char&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;로 향하는 서로 다른 함수들의 개수와도 동일하며, 각 함수는 고유한 256 튜플에 해당된다.&lt;/p&gt;
&lt;p&gt;비슷한 방식으로 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;char&lt;/code&gt;로 향하는 함수의 개수도 계산해보면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;256^2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개라는 사실을 알 수 있다. 함수 타입에 대한 지수 표기법은 이런 의미를 가지고 있는 것이다.&lt;/p&gt;
&lt;p&gt;아마 우리는 &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;double&lt;/code&gt;에서 출발하는 함수를 모두 메모아이즈하고 싶어하지는 않을 것이다. 하지만 비록 실용적이지 않더라도 함수와 데이터 타입 사이의 동등성은 명확히 존재한다.&lt;/p&gt;
&lt;p&gt;그리고 리스트, 트리, 문자열과 같은 무한한 타입도 있다. 이러한 타입에서 출발하는 함수를 메모아이즈하기 위해서는 무한한 저장 공간을 필요로 한다.&lt;/p&gt;
&lt;p&gt;그러나 Haskell은 게으른 언어이므로, 게으르게 평가되는 무한한 데이터 구조와 함수 사이의 경계는 모호하게 다가온다. 이러한 함수와 데이터 간의 쌍대성은 함수 타입을 카테고리론적 지수 대상과 동일시 할 수 있다는 것을 설명한다. 이러한 특성은 우리가 가진 데이터에 대한 개념과도 일치하기 때문에 Haskell에서는 함수를 데이터처럼 취급할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;94-데카르트-닫힌-카테고리cartesian-closed-categories&quot; style=&quot;position:relative;&quot;&gt;9.4 데카르트 닫힌 카테고리(Cartesian Closed Categories)&lt;a href=&quot;#94-%EB%8D%B0%EC%B9%B4%EB%A5%B4%ED%8A%B8-%EB%8B%AB%ED%9E%8C-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%ACcartesian-closed-categories&quot; aria-label=&quot;94 데카르트 닫힌 카테고리cartesian closed categories permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;물론 필자는 계속 집합의 카테고리를 타입과 함수의 모델로 사용할 것이지만, 이런 목적으로 사용할 수 있는 더 큰 카테고리 패밀리가 있다는 것을 언급하는 것은 충분히 가치가 있을 것 같다. 이런 카테고리는 데카르트 닫힌 카테고리(Cartesian closed categories)라고 하며, &lt;strong&gt;Set&lt;/strong&gt;은 그저 이 카테고리 중 하나의 예일 뿐이다.&lt;/p&gt;
&lt;p&gt;데카르트 닫힌 카테고리는 아래 세 가지를 반드시 포함하고 있어야 한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;종결 대상&lt;/li&gt;
&lt;li&gt;어떤 두 대상의 곱&lt;/li&gt;
&lt;li&gt;어떤 두 대상의 지수&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;지수를 무한히 많은 횟수로 반복되는 곱이라고 간주한다면, 데카르트 닫힌 카테고리는 임의의 항수를 지원하는 것이라고 생각할 수 있다. 특히 종결 대상은 곱의 항등원(0)인 대상의 곱 또는 대상의 항등원(0) 승이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;컴퓨터 과학의 관점에서 데카르트 닫힌 카테고리들이 흥미로운 이유는 이 카테고리들이 간단하게 타이핑된 람다 미적분법의 모델을 제공하고 있기 때문이다. 이 모델은 타입을 사용하는 모든 프로그래밍 언어의 기초를 형성한다.&lt;/p&gt;
&lt;p&gt;종결 대상과 곱 연산에는 각각 초기 대상과 합 연산이라는 쌍대(Dual)가 존재한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;a × (b + c) = a × b + a × c
(b + c) × a = b × a + c × a&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 두 요소를 지원하고 곱이 합을 통해 분배될 수 있는 데카르트 닫힌 카테고리를 이중 데카르트 닫힌 카테고리(Bicartesian closed category)라고 한다. 다음 섹션에서 보겠지만 우리가 계속 다뤄온 &lt;strong&gt;Set&lt;/strong&gt;이 대표적인 이중 데카르트 닫힌 카테고리이며, 이 카테고리는 몇 가지 흥미로운 특성을 가지고 있다.&lt;/p&gt;
&lt;h2 id=&quot;95-지수와-대수적-자료형exponentials-and-algebraic-data-types&quot; style=&quot;position:relative;&quot;&gt;9.5 지수와 대수적 자료형(Exponentials and Algebraic Data Types)&lt;a href=&quot;#95-%EC%A7%80%EC%88%98%EC%99%80-%EB%8C%80%EC%88%98%EC%A0%81-%EC%9E%90%EB%A3%8C%ED%98%95exponentials-and-algebraic-data-types&quot; aria-label=&quot;95 지수와 대수적 자료형exponentials and algebraic data types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;함수 타입을 지수로 해석하는 것은 대수적 자료형의 체계에 아주 잘 들어맞는다. 실제로 고등학교에서 배우는 대수학에서 나오는 숫자 0과 1, 합, 곱, 그리고 지수와 관련된 기본적인 항등식은 각각 초기 대상, 종결 대상, 합집합, 곱집합 그리고 지수에 대해 거의 그대로 적용된다는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;우리는 아직 이 성질을 제대로 증명할만한 수반(Adjunction)이나 요네다 보조정리같은 도구를 가지고 있지는 않지만, 그럼에도 불구하고 독자 여러분께 직관을 제공하기 위해 일단 쭉 설명해보겠다.&lt;/p&gt;
&lt;h3 id=&quot;951-0승&quot; style=&quot;position:relative;&quot;&gt;9.5.1 0승&lt;a href=&quot;#951-0%EC%8A%B9&quot; aria-label=&quot;951 0승 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a^0 = 1 &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8641em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8641em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;카테고리적 해석에서 우리는 0을 초기 대상으로, 1을 종결 대상으로, 그리고 등식을 동형사상으로 대체한다. 여기서 지수는 내부 Hom 대상을 의미하기 때문에 결국 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a^0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이라는 식은 초기 대상에서 임의의 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 향하는 사상의 집합을 나타낸다. 초기 대상의 정의에 따라 이런 사상은 정확히 하나만 존재할 수 있으므로 Hom 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C(0,a)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 단일 원소 집합이다.&lt;/p&gt;
&lt;p&gt;단일 원소 집합은 &lt;strong&gt;Set&lt;/strong&gt;에서의 종결 대상이므로, 이 항등식은 &lt;strong&gt;Set&lt;/strong&gt;에서 쉽게 성립할 수 있다. 여기서 중요한 것은 이 항등식이 이중 데카르트 닫힌 카테고리의 모든 경우에 대해서 성립한다는 것이다.&lt;/p&gt;
&lt;p&gt;Haskell에서는 0을 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;로, 1을 유닛 타입인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;으로 대체한다. 결국 필자가 앞에서 했던 주장은 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;에서 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 향하는 함수의 집합이 유닛 타입과 동등하다는 것이다. 다시 말하자면 &lt;code class=&quot;language-text&quot;&gt;Void -&gt; a&lt;/code&gt; 함수는 하나뿐이라는 것이다. 그리고 우리는 이미 이 함수를 예전에 본 적이 있다. 바로 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt; 함수이다.&lt;/p&gt;
&lt;p&gt;그러나 이것을 현실에 구현하기는 약간 까다롭다. 이유는 크게 두 가지인데, 첫째로 Haskell에서는 실제로 어떤 값도 속하지 않는 타입이라는게 존재하지 않는다. 모든 타입은 “끝나지 않는 계산의 결과” 또는 Bottom(&lt;code class=&quot;language-text&quot;&gt;_|_&lt;/code&gt;)을 포함하기 때문이다.&lt;/p&gt;
&lt;p&gt;두번째 이유는 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt;에는 어떤 값도 전달할 수 없기 때문에 누가 무슨 짓을 하던 결국 아무도 실행시킬 수 없다는 점이다. 결국 이 함수의 구현은 근본적으로 모두 동등하다는 것이다. 그렇다고 해서 만약 영원히 끝나지 않는 계산을 전달한다면 이 함수는 결코 반환이라는 행위까지 도달하지 못할 것이다.&lt;/p&gt;
&lt;h3 id=&quot;952-1의-지수&quot; style=&quot;position:relative;&quot;&gt;9.5.2 1의 지수&lt;a href=&quot;#952-1%EC%9D%98-%EC%A7%80%EC%88%98&quot; aria-label=&quot;952 1의 지수 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1^a = 1	&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;위 식은 &lt;strong&gt;Set&lt;/strong&gt;에서 해석될 때 모든 대상에서 종결 대상으로 향하는 고유한 사상이 존재한다는 종결 대상에 대한 정의를 다시 한번 표현하고 있다. 일반적으로 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 종결 대상으로 향하는 내부 Hom 대상은 종결 대상과 동형이다.&lt;/p&gt;
&lt;p&gt;Haskell에서 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 유닛으로 향하는 함수는 &lt;code class=&quot;language-text&quot;&gt;a -&gt; ()&lt;/code&gt; 단 하나 뿐이다. 우리는 이 함수를 &lt;code class=&quot;language-text&quot;&gt;unit&lt;/code&gt;이라고 부른다는 것을 이미 알고 있다. 이 함수는 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;에 부분 적용된 &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt; 함수로 생각할 수도 있다.&lt;/p&gt;
&lt;h3 id=&quot;953-1승&quot; style=&quot;position:relative;&quot;&gt;9.5.3 1승&lt;a href=&quot;#953-1%EC%8A%B9&quot; aria-label=&quot;953 1승 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a^1 = a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8641em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8641em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;위 식은 종결 대상으로부터 출발하는 사상은 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 원소를 선택하는데 사용될 수 있다는 것을 다시 표현한 것이다. 이러한 사상들의 집합은 대상 자체와 동형이다. &lt;strong&gt;Set&lt;/strong&gt;, 그리고 Haskell에서는 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 원소들과 해당 원소들을 선택하는 함수들인 &lt;code class=&quot;language-text&quot;&gt;() -&gt; a&lt;/code&gt;가 동형이라는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;954-지수의-합&quot; style=&quot;position:relative;&quot;&gt;9.5.4 지수의 합&lt;a href=&quot;#954-%EC%A7%80%EC%88%98%EC%9D%98-%ED%95%A9&quot; aria-label=&quot;954 지수의 합 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a^{b+c} = a^b ×a^c	&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8991em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8991em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9824em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8991em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;카테고리론적으로 위 식은 대상의 두 지수의 합이 각 지수를 가진 대상들의 곱과 동형이라는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;이 대수적 동형성을 Haskell에서 다루게 되면 매우 실용적인 해석을 가져다준다. 이는 두 타입의 합으로부터 출발하는 함수가 각각의 타입으로부터 출발하는 함수의 쌍과 동등하다는 것을 의미하기 때문이다.&lt;/p&gt;
&lt;p&gt;이 개념이 바로 우리가 합에 대한 함수를 정의할 때 사용하는 문법의 근원이다. 우리는 합을 의미하는 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;를 정의할 때 &lt;code class=&quot;language-text&quot;&gt;case&lt;/code&gt; 문을 사용하여 함수를 정의하지 않고, 각각의 타입 생성자를 따로 처리하는 두 개, 혹은 그 이상의 함수로 나눈다.&lt;/p&gt;
&lt;p&gt;예를 들어 합 타입(&lt;code class=&quot;language-text&quot;&gt;Either Int Double&lt;/code&gt;)를 한번 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 경우 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;는 각각 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Double&lt;/code&gt;에 대한 함수의 쌍으로 정의될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Negative int&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Positive int&quot;&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Negative double&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Positive double&quot;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;955-지수의-지수&quot; style=&quot;position:relative;&quot;&gt;9.5.5 지수의 지수&lt;a href=&quot;#955-%EC%A7%80%EC%88%98%EC%9D%98-%EC%A7%80%EC%88%98&quot; aria-label=&quot;955 지수의 지수 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/msup&gt;&lt;msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(a^b)^c = a^{b×c}	&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.1491em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8991em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8991em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8991em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;위 식은 지수 대상들에 대한 커링(Currying)을 표현하고 있다. 함수가 함수를 반환하는 것은 곱에서 출발하는 함수, 즉 이변수 함수와 동등하다.&lt;/p&gt;
&lt;h3 id=&quot;956-곱의-지수&quot; style=&quot;position:relative;&quot;&gt;9.5.6 곱의 지수&lt;a href=&quot;#956-%EA%B3%B1%EC%9D%98-%EC%A7%80%EC%88%98&quot; aria-label=&quot;956 곱의 지수 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(a×b)^c =a^c × b^c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7977em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서 쌍을 반환하는 함수는 각 쌍의 요소 하나를 생성하는 두 함수의 쌍과 동등하다.&lt;/p&gt;
&lt;p&gt;이처럼 고등학교에서 배우는 대수학의 간단한 항등식들이 카테고리 이론으로 확장되어 함수형 프로그래밍에서 실용적으로 적용될 수 있다는 것은 굉장히 놀라운 일이다.&lt;/p&gt;
&lt;h2 id=&quot;96-커리-하워드-동형사상curry-howard-isomorphism&quot; style=&quot;position:relative;&quot;&gt;9.6 커리-하워드 동형사상(Curry-Howard Isomorphism)&lt;a href=&quot;#96-%EC%BB%A4%EB%A6%AC-%ED%95%98%EC%9B%8C%EB%93%9C-%EB%8F%99%ED%98%95%EC%82%AC%EC%83%81curry-howard-isomorphism&quot; aria-label=&quot;96 커리 하워드 동형사상curry howard isomorphism permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자는 이미 논리와 대수적 자료형 간의 대응 관계에 대해 언급한 적이 있다. &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입과 유닛 타입(&lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;)은 각각 거짓과 참에 해당하며, 곱 타입과 합 타입은 논리곱(AND)과 논리합(OR)에 해당한다. 이 체계에서 함수 타입은 논리적 함의(&lt;code class=&quot;language-text&quot;&gt;⇒&lt;/code&gt;)에 해당한다. 다시 말해 타입 &lt;code class=&quot;language-text&quot;&gt;a -&gt; b&lt;/code&gt;는 “만약 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;라면 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;이다”라고 읽을 수 있다.&lt;/p&gt;
&lt;p&gt;커리-하워드 동형사상에 따르면 모든 타입은 참 또는 거짓일 수 있는 명제, 즉 진술이나 판단으로 해석될 수 있다. 해당 타입이 존재하면 그 명제는 참으로 간주되고, 존재하지 않으면 거짓으로 간주된다. 특히 논리적 함의가 참이라는 것은 그에 해당하는 함수 타입이 존재한다는 것을 의미하며, 그 타입의 함수가 실제로 존재한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;따라서 함수의 구현 자체가 정리의 증명이 되는 것이며, 우리가 프로그램을 작성하는 것은 정리를 증명하는 것과 동등하다. 한번 몇 가지 예시를 살펴보자.&lt;/p&gt;
&lt;p&gt;함수 대상의 정의에서 소개했던 &lt;code class=&quot;language-text&quot;&gt;eval&lt;/code&gt; 함수를 살펴보도록 하겠다. &lt;code class=&quot;language-text&quot;&gt;eval&lt;/code&gt;의 시그니처는 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 함수와 그 인자로 구성된 쌍을 받아 적절한 타입의 결과를 반환한다. 즉 위 코드는 사상에 대한 Haskell에서의 구현이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; ⇒ &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; × &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 표현은 함수 타입 &lt;code class=&quot;language-text&quot;&gt;a ⇒ b&lt;/code&gt; (또는 지수 대상 &lt;code class=&quot;language-text&quot;&gt;ba&lt;/code&gt;)를 정의한다. 이 서명을 커리-하워드 동형사상을 사용하여 논리적 술어로 번역해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;((a ⇒ b) ∧ a) ⇒ b&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 명제는 만약 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로부터 도출되는 것이 참이고, &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 또한 참이라면, &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 또한 반드시 참이어야 한다고 읽을 수 있다. 이는 직관적으로 완벽한 의미를 가지고 있으며 고대부터 전건 긍정(*modus ponens)*라고 불려왔다. 이제 다음 함수를 구현함으로써 이 정리를 증명할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 받아서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;를 반환하는 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;와 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 구체적인 값 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;로 구성된 쌍을 제공한다면, 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;에 적용함으로써 타입 b의 구체적인 값을 생성할 수 있다.&lt;/p&gt;
&lt;p&gt;즉, 필자는 이 함수를 구현함으로써 타입 &lt;code class=&quot;language-text&quot;&gt;((a -&gt; b), a) -&gt; b&lt;/code&gt;가 실제로 존재한다는 것을 보였다. 따라서 우리의 논리에서 전건 긍정(modus ponens)는 참이다.&lt;/p&gt;
&lt;p&gt;그렇다면 명백하게 거짓인 술어는 어떨까? 예를 들어 “만약 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;가 참이면, &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;는 반드시 참이어야 한다”와 같은 명제가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;a ∨ b ⇒ a&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이는 명백하게 잘못된 명제이다. 왜냐하면 이 명제대로라면 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 거짓이고  &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;가 참인 상황도 존재할 수 있기 때문이다. 이 술어를 커리-하워드 동형사상을 사용하여 함수 시그니처로 매핑하면 다음과 같은 결과를 얻을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 아무리 시도를 하더라도 이 함수는 절대 구현할 수 없다. &lt;code class=&quot;language-text&quot;&gt;Right&lt;/code&gt; 값으로 호출되었을 때는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 타입의 값을 생성할 수 없기 때문이다. (우리가 순수 함수에 대해서만 이야기하고 있다는 점을 기억하자)&lt;/p&gt;
&lt;p&gt;이제 드디어 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt; 함수의 진짜 의미에 대해 이야기할 때가 되었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;absurd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;가 “거짓”이라고 번역된다고 생각해보면 우리는 아래와 같은 술어를 얻을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;false ⇒ a&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;거짓에서는 어떤 것이든 따라올 수 있다(&lt;em&gt;ex falso quodlibet&lt;/em&gt;). 여기 Haskell에서 이 명제(함수)를 증명(구현)할 수 있는 한 가지 예시가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;absurd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;absurd&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;는 다음과 같이 정의된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입은 까다로운 녀석이다. 이 정의는 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입의 값을 생성하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입의 값이 필요하다는 의미를 가지고 있기 때문에 절대 값을 구성할 수 없게 만든다. 결국 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입의 값이라는 것은 존재할 수가 없으므로 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt; 함수는 절대 호출될 수가 없는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“거짓에서는 어떤 것이든 따라올 수 있다”라는 뜻의 &lt;em&gt;ex falso quodlibet&lt;/em&gt;는 거짓 명제로부터는 어떤 명제라도 유도될 수 있다는 것을 의미하며, 이는 논리학에서 매우 중요한 원칙 중 하나이다.&lt;/p&gt;
&lt;p&gt;쉽게 말하자면 거짓인 전제가 주어진다면, 그 전제로부터 나오는 어떠한 결론도 모두 정당화될 수 있다는 것이다.이와 마찬가지로 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt; 함수는 절대 생성될 수 없는 값의 타입인 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;를 인자로 받아 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 반환할 수 있다고 선언된다.&lt;/p&gt;
&lt;p&gt;즉, 거짓으로부터 출발했으니 어떤 타입을 반환하더라도 논리가 깨지지는 않는 것이다.참고로 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt; 함수는 절대 호출될 수가 없기 때문에 실제로 사용될 수는 없고, 순수하게 프로그래밍 언어의 타입 시스템의 원리를 설명하기 위한 이론적인 목적으로만 사용된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 이 예시들이 모두 흥미롭기는 하지만, 도대체 커리-하워드 동형사상이 우리에게 어떤 실용적인 혜택을 가져다준다는 것일까? 아마도 일상적인 프로그래밍에서는 아니겠지만, Agda나 Coq와 같은 프로그래밍 언어들은 정리를 증명하기 위해 커리-하워드 동형사상을 활용한다.&lt;/p&gt;
&lt;p&gt;컴퓨터는 수학자들이 그들의 일을 하는데 도움을 주는 것뿐만 아니라, 수학의 근본을 혁신하고 있다. 이러한 분야에서 가장 최근에 뜨거운 감자로 떠오르는 연구는 호모토피 타입 이론이라고 하며, 타입 이론의 발전에 큰 기여를 하고있다. 이 이론은 Boolean, Integer, 곱과 쌍대곱, 함수 타입 등으로 가득 차 있다. 그리고 이러한 이론은 Coq와 Agda에서 공식적으로 도입되고 있다.&lt;/p&gt;
&lt;p&gt;이처럼 컴퓨터는 여러 방면에서 세상을 혁신하고 있다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 8. 펑터의 특성]]></title><description><![CDATA[이제 펑터가 무엇인지 알았으니, 작은 펑터로부터 큰 펑터를 구축해나가는 방법에 대해서 살펴보도록 하겠다. 여기서 특히 흥미로운 부분은 카테고리 내 대상 간의 매핑에 대당하는 타입의 생성자가 확장되어 사상 간의 매핑을 포함하는 펑터가 되는 과정을 볼 수 있다는 것이다.]]></description><link>https://evan-moon.github.io/2024/04/02/category-theory-for-programmers-8-functoriality/</link><guid isPermaLink="false">20240402-category-theory-for-programmers-8-functoriality</guid><pubDate>Tue, 02 Apr 2024 05:29:53 GMT</pubDate><content:encoded>&lt;p&gt;이제 펑터가 무엇인지 알았으니, 작은 펑터로부터 큰 펑터를 구축해나가는 방법에 대해서 살펴보도록 하겠다.&lt;/p&gt;
&lt;p&gt;여기서 특히 흥미로운 부분은 카테고리 내 대상 간의 매핑에 대당하는 타입의 생성자가 확장되어 사상 간의 매핑을 포함하는 펑터가 되는 과정을 볼 수 있다는 것이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;81-이항-펑터bifunctors&quot; style=&quot;position:relative;&quot;&gt;8.1 이항 펑터(Bifunctors)&lt;a href=&quot;#81-%EC%9D%B4%ED%95%AD-%ED%8E%91%ED%84%B0bifunctors&quot; aria-label=&quot;81 이항 펑터bifunctors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;펑터는 카테고리들의 카테고리인 &lt;em&gt;Cat&lt;/em&gt;에서의 사상이기 때문에 사상에 대한 많은 직관들 특히 함수에 대한 직관들은 펑터에도 그대로 작용한다고 할 수 있다.&lt;/p&gt;
&lt;p&gt;예를 들어 두 개의 인수를 가지는 함수가 있듯이, 두 개의 인수를 가지는 펑터인 이항 펑터(Bifunctors)도 존재할 수 있다. 먼저 대상에 대해서만 생각해보자면 이항 펑터는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, 그리고 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 각각의 대상으로 이루어진 모든 쌍을 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상으로 매핑하는 펑터이다. 즉, 이항 헝터는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C×D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 표현되는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 데카르트 곱에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로의 매핑이라고 볼 수 있는 것이다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 313px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6f3400dcb00c047b27d284f6c7f27034/aa65c/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 95%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB9qSmO25pJriHcH//xAAbEAACAgMBAAAAAAAAAAAAAAABAhESAAMiIf/aAAgBAQABBQK/R2myGwK+8h1EKROBFnP/xAAVEQEBAAAAAAAAAAAAAAAAAAABIP/aAAgBAwEBPwEj/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGhAAAgIDAAAAAAAAAAAAAAAAARARMQAgIf/aAAgBAQAGPwKMtSa0PF//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMWFBEP/aAAgBAQABPyGm2apHKjWu5l0eoCAxftQgBvsDByTij8//2gAMAwEAAgADAAAAEMPAfP/EABcRAQEBAQAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QK8gpk//EABYRAQEBAAAAAAAAAAAAAAAAAAEgMf/aAAgBAgEBPxAQ2P/EABwQAQEAAwEAAwAAAAAAAAAAAAERACExQWFxgf/aAAgBAQABPxArQUr9GVYl0LA8Odyl0qJ5+YboVU+zFxsGnZXcHJOkvyu8CjSiONoXhtw0Z//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/6f3400dcb00c047b27d284f6c7f27034/aa65c/1.jpg&quot; srcset=&quot;/static/6f3400dcb00c047b27d284f6c7f27034/0913d/1.jpg 160w,
/static/6f3400dcb00c047b27d284f6c7f27034/aa65c/1.jpg 313w&quot; sizes=&quot;(max-width: 313px) 100vw, 313px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;사실 여기까지는 매우 간단하게 이해할 수 있다. 그러나 펑터의 특성상 이항 펑터는 대상 뿐만 아니라 사상 또한 매핑할 수 있어야 한다. 즉, 하나는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 다른 하나는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 가져온 사상의 쌍을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;E&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 사상으로 매핑해야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;한번 더 이야기하자면, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 사상의 쌍은 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C×D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 단일한 사상이다. 우리는 데카르트 곱 카테고리에서의 사상을 어떤 대상의 쌍에서 다른 대상의 쌍으로 이동하는 사상의 쌍으로 정의할 수 있다. 이러한 사상의 쌍들은 아래와 같은 방식으로 합성도 가능하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ◦ &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; ◦ &lt;span class=&quot;token hvariable&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; ◦ &lt;span class=&quot;token hvariable&quot;&gt;g&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;합성은 결합법칙을 만족하며, &lt;code class=&quot;language-text&quot;&gt;(id, id)&lt;/code&gt;와 같은 항등원 또한 존재한다. 이처럼 데카르트 곱 카테고리는 카테고리의 기본적인 법칙을 모두 만족하기 때문에 실제로 하나의 카테고리가 될 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;이항 펑터에 대해서 더 쉽게 이해하려면 이 펑터가 두 인자 모두에 대한 펑터라는 점을 이해하는 것에서부터 출발해야한다. 즉, 펑터 법칙인 결합성과 항등 보존에 대한 개념을 곧바로 이항 펑터와 연결하고 확인해보려고 시도하는 것보다는, 이항 펑터가 가진 각 인자에 대해 하나씩 확인해보는 것이 더 이해하기 쉽다는 것이다.&lt;/p&gt;
&lt;p&gt;만약 한 쌍의 카테고리로부터 세 번째 카테고리로의 매핑이 있고, 그 매핑이 각 인자에 대해 펑터적(Functorial)이라는 사실을 만족한다는 사실을 증명한다면, 해당 매핑은 자동으로 이항 펑터가 된다. 여기서 펑터적이라는 의미는 이 펑터가 사상에 대해서 제대로 된 펑터처럼 작동한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;Haskell에서 이항 펑터를 한번 정의해보자. 이 경우에는 세 개의 카테고리가 모두 Haskell 타입의 카테고리이기 때문에 사실상 같은 카테고리라고 볼 수 있다. 이항 펑터는 두 개의 타입 인자를 가지는 타입 생성자로 표현된다. 아래는 라이브러리 &lt;code class=&quot;language-text&quot;&gt;Control.Bifunctor&lt;/code&gt;에서 직접 가져온 &lt;code class=&quot;language-text&quot;&gt;Bifunctor&lt;/code&gt; 타입 클래스의 정의이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;타입 변수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;는 이항 펑터를 나타내며, 아래 정의된 모든 타입 시그니처에서 이 타입 변수가 항상 두 개의 타입 인자에 적용되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;첫 번째 타입 시그니처는 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;을 정의하는데, 이것은 두 함수의 매핑을 한 번에 나타낸다. 결과는 이항 펑터의 타입 생성자에 의해 생성된 타입들에서 동작하는 함수 &lt;code class=&quot;language-text&quot;&gt;(f a b -&gt; f c d)&lt;/code&gt;이다. &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;first&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;second&lt;/code&gt;를 사용하여 구현되어 있는데, 이는 이항 펑터가 각각의 인자에 대해 펑터적으로 작동한다는 사실을 정의하는 것만으로도 이항 펑터를 정의할 수 있다는 사실을 보여준다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 313px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6f3400dcb00c047b27d284f6c7f27034/aa65c/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 95%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB9qSmO25pJriHcH//xAAbEAACAgMBAAAAAAAAAAAAAAABAhESAAMiIf/aAAgBAQABBQK/R2myGwK+8h1EKROBFnP/xAAVEQEBAAAAAAAAAAAAAAAAAAABIP/aAAgBAwEBPwEj/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGhAAAgIDAAAAAAAAAAAAAAAAARARMQAgIf/aAAgBAQAGPwKMtSa0PF//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMWFBEP/aAAgBAQABPyGm2apHKjWu5l0eoCAxftQgBvsDByTij8//2gAMAwEAAgADAAAAEMPAfP/EABcRAQEBAQAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QK8gpk//EABYRAQEBAAAAAAAAAAAAAAAAAAEgMf/aAAgBAgEBPxAQ2P/EABwQAQEAAwEAAwAAAAAAAAAAAAERACExQWFxgf/aAAgBAQABPxArQUr9GVYl0LA8Odyl0qJ5+YboVU+zFxsGnZXcHJOkvyu8CjSiONoXhtw0Z//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/6f3400dcb00c047b27d284f6c7f27034/aa65c/1.jpg&quot; srcset=&quot;/static/6f3400dcb00c047b27d284f6c7f27034/0913d/1.jpg 160w,
/static/6f3400dcb00c047b27d284f6c7f27034/aa65c/1.jpg 313w&quot; sizes=&quot;(max-width: 313px) 100vw, 313px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;bimap&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;first&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;second&lt;/code&gt;는 각각 첫 번째와 두 번째 인자에 대한 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;의 펑터적인 성질을 증명하는 두 개의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 388px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/351da696e6a37d5df6740dce2c23f8d6/c3c84/3.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 82.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAEEBQL/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB1613PXQdkkEg/8QAHRAAAgEEAwAAAAAAAAAAAAAAAQIAAxAREhMhMf/aAAgBAQABBQJqms5ThO1YYg2g8v8A/8QAFREBAQAAAAAAAAAAAAAAAAAAASD/2gAIAQMBAT8BCP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABoQAQEAAgMAAAAAAAAAAAAAAAEAESEgIkH/2gAIAQEABj8Cb3LblDcdeP8A/8QAHBAAAgEFAQAAAAAAAAAAAAAAAAERICExQVFh/9oACAEBAAE/IfY4JqX0B3JkISQbQzOEr8MFoo//2gAMAwEAAgADAAAAEB/PAP/EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAEDAQE/EGY//8QAFhEBAQEAAAAAAAAAAAAAAAAAAREg/9oACAECAQE/EKGP/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBgRBRkf/aAAgBAQABPxBUQwHAVPUdSwoLj7UGbi3mzqERNwu+oYWLGXTviBAQqyGiPENeP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3&quot; title=&quot;&quot; src=&quot;/static/351da696e6a37d5df6740dce2c23f8d6/c3c84/3.jpg&quot; srcset=&quot;/static/351da696e6a37d5df6740dce2c23f8d6/0913d/3.jpg 160w,
/static/351da696e6a37d5df6740dce2c23f8d6/cb69c/3.jpg 320w,
/static/351da696e6a37d5df6740dce2c23f8d6/c3c84/3.jpg 388w&quot; sizes=&quot;(max-width: 388px) 100vw, 388px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;first&lt;/small&gt;
&lt;/center&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 423px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f7734853d3675663d3f814199fd26135/b7bea/4.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 92.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGQABAQADAQAAAAAAAAAAAAAAAAQBAgMF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAfXlqkq9sjPMOoP/xAAbEAACAgMBAAAAAAAAAAAAAAABAhEhAAMSE//aAAgBAQABBQL0g9uShlTrsKJWgbzhZz//xAAVEQEBAAAAAAAAAAAAAAAAAAABIP/aAAgBAwEBPwEj/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGhAAAgMBAQAAAAAAAAAAAAAAEBEAASExMv/aAAgBAQAGPwJKYLt5PR4P/8QAGhABAQEBAQEBAAAAAAAAAAAAAREAITEQcf/aAAgBAQABPyFt6Qz2DzNZ9wUTlHpn7gCDcARKYPx+f//aAAwDAQACAAMAAAAQ9898/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EBs1J//EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAECAQE/EBCP/8QAHRABAQACAwADAAAAAAAAAAAAAREAMSFBUWGx0f/aAAgBAQABPxCxKhH2X8xw1bCgF89wyOyOAVINjq2/eJoBUQ8dmRNJv35yISbHvHCUJvnDg4z/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;4&quot; title=&quot;&quot; src=&quot;/static/f7734853d3675663d3f814199fd26135/b7bea/4.jpg&quot; srcset=&quot;/static/f7734853d3675663d3f814199fd26135/0913d/4.jpg 160w,
/static/f7734853d3675663d3f814199fd26135/cb69c/4.jpg 320w,
/static/f7734853d3675663d3f814199fd26135/b7bea/4.jpg 423w&quot; sizes=&quot;(max-width: 423px) 100vw, 423px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;second&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;타입 클래스 정의는 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;을 기반으로 두 개의 함수에 대한 기본 구현을 제공한다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Bifunctor&lt;/code&gt;의 인스턴스를 선언할 때는 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;을 구현하고, &lt;code class=&quot;language-text&quot;&gt;first&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;second&lt;/code&gt;의 기본 값을 사용하거나, 반대로 &lt;code class=&quot;language-text&quot;&gt;first&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;second&lt;/code&gt;를 모두 구현하고 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;의 기본 값을 사용하는 선택권을 가질 수 있다. (물론 세 가지 모두를 구현할 수는 있겠지만, 그러면 이들이 위와 같은 성질을 가질 수 있도록 보장해줘야 한다.)&lt;/p&gt;
&lt;h2 id=&quot;82-곱과-합-이항-펑터product-and-coproduct-bifunctors&quot; style=&quot;position:relative;&quot;&gt;8.2 곱과 합 이항 펑터(Product and Coproduct Bifunctors)&lt;a href=&quot;#82-%EA%B3%B1%EA%B3%BC-%ED%95%A9-%EC%9D%B4%ED%95%AD-%ED%8E%91%ED%84%B0product-and-coproduct-bifunctors&quot; aria-label=&quot;82 곱과 합 이항 펑터product and coproduct bifunctors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이항 펑터의 예시 중 특히 중요한 것은 카테고리적 곱(Categorical Product)이다. 이는 두 대상의 곱으로, &lt;a href=&quot;/2024/02/27/category-theory-for-programmers-5-products-and-coproducts&quot;&gt;보편적 구성(Universial Construction)&lt;/a&gt;에 의해 정의된다. 만약 어떤 두 대상에 대한 곱이 존재한다면, 해당 대상들에서 곱으로의 매핑은 이항 펑터적(Bifunctorial)이다. 이것은 일반적으로 참이며, 특히 Haskell에서도 마찬가지이다.&lt;/p&gt;
&lt;p&gt;아래는 가장 간단한 곱 타입인 쌍 생성자에 대한 &lt;code class=&quot;language-text&quot;&gt;Bifunctor&lt;/code&gt; 인스턴스이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;은 단순히 쌍의 첫 번째 구성 요소에 첫 번째 함수를 적용하고, 두 번째 구성 요소에는 두 번째 함수를 적용하고 있기 때문에, 딱히 고민할만한 부분이 없다. 이렇게 명확하고 간단한 동작이 요구사항으로 주어진다면 코드 작성 자체는 간단하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 이항 펑터의 작용은 타입들의 쌍을 만드는 것이다. 예를 들면 이런 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;쌍대성에 의해 이 정의가 카테고리 내의 모든 대상 쌍에 대해서 정의된다면, 합(Coproduct) 또한 이항 펑터라고 할 수 있다. Haskell에서는 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt; 타입 생성자를 &lt;code class=&quot;language-text&quot;&gt;Bifunctor&lt;/code&gt;의 인스턴스인 것으로 나타낼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;워낙 동작이 간단하고 요구사항이 명확하니 코드 작성은 어렵지 않다.&lt;/p&gt;
&lt;p&gt;혹시 모노이드 카테고리(Monoidal Category)에 대해 이야기했던 것을 기억하는가? 모노이드 카테고리는 단위 대상과 함께 대상에 작용하는 이항 연산자인 모노이드 곱(Monoidal Product)을 정의한다.&lt;/p&gt;
&lt;p&gt;예전에 이야기했듯이 &lt;em&gt;Set&lt;/em&gt;(집합의 카테고리)은 데카르트 곱 연산을 이항 연산으로 사용하여 대상 간의 결합을 정의하는 모노이드 카테고리이며, 이때 단위 대상은 단일 원소 집합이다. 또한 서로소 합집합 연산에 대해서도 모노이드 카테고리라고 볼 수 있으며, 이때의 단위 대상은 공집합이 된다.&lt;/p&gt;
&lt;p&gt;당시 필자가 언급하지 않은 것이 하나가 있다. 바로 모노이드 카테고리의 요구 사항 중 하나는 이항 연산자가 이항 펑터여야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;우리는 모노이드 곱의 연산 구조가 사상에 의해 정의된 카테고리의 구조와 호환되도록 만들어야 하며, 이것은 매우 중요한 요구 사항이다. 물론 완전한 이해를 하기에는 아직 자연성(Naturality)이라는 큰 산이 하나 남아 있기는 하지만, 그래도 모노이드 카테고리의 전체 정의에 한 발짝 더 가까워졌다.&lt;/p&gt;
&lt;h2 id=&quot;83-펑터적인-대수적-데이터-자료형functorial-algebraic-data-types&quot; style=&quot;position:relative;&quot;&gt;8.3 펑터적인 대수적 데이터 자료형(Functorial Algebraic Data Types)&lt;a href=&quot;#83-%ED%8E%91%ED%84%B0%EC%A0%81%EC%9D%B8-%EB%8C%80%EC%88%98%EC%A0%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%90%EB%A3%8C%ED%98%95functorial-algebraic-data-types&quot; aria-label=&quot;83 펑터적인 대수적 데이터 자료형functorial algebraic data types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지 펑터가 될 수 있는 몇 가지 파라미터화된 데이터 타입을 살펴봤다. 우리는 이러한 타입들에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 정의할 수 있었다. 복잡한 데이터 타입은 더 간단한 데이터 타입을 기반으로 하여 구성되는데, 합과 곱의 개념을 사용하여 대수적 데이터 타입(ADT)을 생성하는 것이 바로 그 예이다.&lt;/p&gt;
&lt;p&gt;앞선 섹션에서 우리는 이미 합과 곱이 펑터적이라는 사실을 확인했고, 펑터가 합성 가능하다는 사실도 알게 되었다. 결국 우리가 대수적 데이터 타입의 기본 구성 요소가 펑터라는 사실을 보일 수만 있다면, 파라미터화된 대수적 데이터 타입도 결국 펑터라는 사실로 이어질 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;파라미터화된 대수적 데이터 타입이라는 것이 무엇을 의미하는걸까? 먼저 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;처럼 펑터의 타입 파라미터에 의존하지 않는 녀석들이 있으며, 이들은 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터와 동등하다. &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터는 자신이 받는 타입 파라미터를 무시한다는 사실을 기억해보자. (정확히 말하면 첫 번째 타입 파라미터는 고정이며, 두 번째 파라미터를 무시하는 것이다.)&lt;/p&gt;
&lt;p&gt;또한 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;처럼 단순히 타입 파라미터 자체를 캡슐화하는 녀석들도 있다. 이들은 항등 펑터와 동등하다. 이전에 &lt;em&gt;Cat&lt;/em&gt;에서의 항등 사상에 대한 이야기를 하면서 항등 펑터를 언급한 적이 있었지만, Haskell에서의 정의는 보여주지 않았었다. 이것이 바로 항등 펑터의 정의다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Identity&lt;/code&gt;는 항상 타입이 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;인 하나의 불변 값만을 가지는 간단한 컨테이너라고 생각해볼 수 있다. 대수적 데이터 구조에서 이 개념을 제외한 나머지 것들은 모두 두 가지 원시적 요소를 합하거나 곱하여 생성된다.&lt;/p&gt;
&lt;p&gt;이 새로운 지식을 토대로 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 타입 생성자를 다시 한번 살펴보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이건 결국 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt; 두 타입의 합이며, 합은 펑터적이다. 첫 번째 부분인 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;Const ()&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 작용하는 것이라고 볼 수 있다. (여기서 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt;의 첫 번째 타입 파라미터는 유닛으로 설정한다.) 그리고 두 번째 부분인 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;는 그저 항등 펑터의 다른 이름일 뿐이다. 그럼 이제 우리는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;를 동형적으로 아래와 같이 다시 정의할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;는 이항 펑터 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;를 사용하여 &lt;code class=&quot;language-text&quot;&gt;Const ()&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Identify&lt;/code&gt;라는 두 개의 펑터를 조합한 것이다. (실제로는 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 또한 이항 펑터이지만, 여기서는 항상 부분적용된 상태로만 사용한다.)&lt;/p&gt;
&lt;p&gt;우리는 이미 펑터의 합성 또한 펑터라는 것을 알고 있으며, 이항 펑터 또한 이와 마찬가지로 동일한 원칙이 적용될 것이라는 점을 쉽게 예상해볼 수 있다. 한번 이항 펑터와 두 펑터의 합성이 사상에 어떤 식으로 작용하는지 알아보도록 하자. 먼저 두 개의 사상 중 하나를 한 펑터로 리프팅한 후, 다른 하나를 또 하나의 다른 펑터로 리프팅할 것이다. 그 다음 여기서 얻어진 두 사상의 쌍을 이항 펑터로 리프팅하는 순서로 진행하면 된다.&lt;/p&gt;
&lt;p&gt;이 과정을 Haskell로 한번 표현해보자. 이 데이터 타입의 매개변수는 다음과 같다. 두 개의 타입을 인자로 받는 타입 생성자를 의미하는 이항 펑터 &lt;code class=&quot;language-text&quot;&gt;bf&lt;/code&gt;, 각각 하나의 타입 변수를 받는 타입 생성자인 두 개의 펑터 &lt;code class=&quot;language-text&quot;&gt;fu&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;gu&lt;/code&gt;와 두 개의 일반적인 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;이다. 이제 펑터 &lt;code class=&quot;language-text&quot;&gt;fu&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 적용하고, 펑터 &lt;code class=&quot;language-text&quot;&gt;gu&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에 적용한 다음, 이 결과로 나온 타입 두 개에 이항 펑터 &lt;code class=&quot;language-text&quot;&gt;bf&lt;/code&gt;를 적용할 것이라는 것을 표현하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것은 객체 또는 타입에 대한 합성이다. Haskell에서는 타입 생성자를 타입에 적용하는 것이 마치 함수를 인수에 적용하는 것과 동일한 방식으로 이루어지며, 심지어 구문 또한 동일하다.&lt;/p&gt;
&lt;p&gt;조금 헷갈린다면, &lt;code class=&quot;language-text&quot;&gt;BiComp&lt;/code&gt;의 매개변수로 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Const ()&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Identity&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;가 들어온다고 생각해보자. 결과적으로 &lt;code class=&quot;language-text&quot;&gt;Maybe b&lt;/code&gt;를 얻을 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;왜 &lt;code class=&quot;language-text&quot;&gt;BiComp Either Const () Identity a b&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Maybe b&lt;/code&gt;인지는 의사코드로 작성해보면 단번에 알 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;새로운 타입인 &lt;code class=&quot;language-text&quot;&gt;Bicomp&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에 대한 이항 펑터라고 할 수 있지만, 이 정의는 매개변수인 &lt;code class=&quot;language-text&quot;&gt;bf&lt;/code&gt;가 이항 펑터이고 &lt;code class=&quot;language-text&quot;&gt;fu&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;gu&lt;/code&gt;가 펑터일 경우에만 성립할 수 있다. 즉, 컴파일러가 이 매개변수들을 추론했을때, &lt;code class=&quot;language-text&quot;&gt;bf&lt;/code&gt;에 대한 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt; 정의와 &lt;code class=&quot;language-text&quot;&gt;fu&lt;/code&gt; 및 &lt;code class=&quot;language-text&quot;&gt;gu&lt;/code&gt;에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 정의가 있다는 사실이 보장되어야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;Haskell에서는 인스턴스 선언 시 클래스 제약 조건 집합 다음에 위치하는 이중 화살표(&lt;code class=&quot;language-text&quot;&gt;=&gt;&lt;/code&gt;)로 이러한 전제조건을 표현해줄 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BiComp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;BiComp&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt; 구현은 &lt;code class=&quot;language-text&quot;&gt;bf&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;fu&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;gu&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 사용하여 정의한다. 컴파일러는 &lt;code class=&quot;language-text&quot;&gt;BiComp&lt;/code&gt;가 사용될 때 이 타입들을 자동으로 추론하고 오버로드된 함수를 선택할 것이다.&lt;/p&gt;
&lt;p&gt;위의 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt; 정의에서 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;의 타입은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것은 꽤나 복잡한 정의처럼 보인다. 외부 &lt;code class=&quot;language-text&quot;&gt;bimap&lt;/code&gt;은 외부 &lt;code class=&quot;language-text&quot;&gt;bf&lt;/code&gt; 레이어를 통과하며, 두 개의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;들은 각각 &lt;code class=&quot;language-text&quot;&gt;fu&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;gu&lt;/code&gt; 아래로 파고들게 된다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;f1&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;f2&lt;/code&gt;의 타입이 아래와 같은 상황이라고 가정해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&apos;&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러면 최종 결과는 &lt;code class=&quot;language-text&quot;&gt;bf (fu a&apos;) (gu b&apos;)&lt;/code&gt; 타입이 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;fu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;gu&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 여러분이 직소 퍼즐을 좋아한다면, 이런 종류의 타입 조작에서 꽤나 큰 즐거움을 느낄 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;결론적으로 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;는 두 펑터적인 요소의 합으로 구성되었기 때문에, 굳이 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;가 펑터라는 것을 증명하지 않아도 당연히 펑터라는 사실이 성립하는 것이다.&lt;/p&gt;
&lt;p&gt;만약 예리한 독자들은 대수적 데이터 타입에 대한 펑터 인스턴스의 유도가 이렇게 논리적으로 명확하게 정의될 수 있다면, 그냥 컴파일러에서 자동화해서 처리할 수는 없냐고 질문할 수도 있다.&lt;/p&gt;
&lt;p&gt;물론 가능하다. 이는 Haskell의 확장기능(Extensions)를 사용하면 되는데, 특정 확장기능을 사용하려면 소스 파일의 맨 위에 아래와 같은 라인을 추가하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그 이후 데이터 구조에 &lt;code class=&quot;language-text&quot;&gt;deriving Functor&lt;/code&gt;를 추가하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 &lt;code class=&quot;language-text&quot;&gt;DeriveFunctor&lt;/code&gt; 확장 기능을 사용하면 특정 데이터 구조에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이 자동으로 구현되도록 할 수 있다.&lt;/p&gt;
&lt;p&gt;이런 기능이 제공될 수 있는 이유는 대수적 데이터 구조의 규칙성으로 인해 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt;뿐 아니라 앞서 언급했던 &lt;code class=&quot;language-text&quot;&gt;Eq&lt;/code&gt;와 같은 여러 다른 타입 클래스 인스턴스를 논리적으로 유도하는 것이 가능하기 때문이다.&lt;/p&gt;
&lt;p&gt;이와 더불어 컴퍼일러에게 사용자 정의 타입 클래스의 인스턴스를 유도하는 것도 가능하지만 이것은 조금 더 고급 기능이다. 하지만 결국 사용자 정의 타입 클래스라고 해도 기본적인 구성 요소, 그리고 합과 곱의 동작을 제공하는 것 뿐이므로 근본적인 원리는 동일하다.&lt;/p&gt;
&lt;h2 id=&quot;84-c에서의-펑터functors-in-c&quot; style=&quot;position:relative;&quot;&gt;8.4 C++에서의 펑터(Functors in C++)&lt;a href=&quot;#84-c%EC%97%90%EC%84%9C%EC%9D%98-%ED%8E%91%ED%84%B0functors-in-c&quot; aria-label=&quot;84 c에서의 펑터functors in c permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;만약 여러분이 C++ 프로그래머라면 펑터를 처음부터 끝까지 오롯이 혼자서 구현해야할 것이다. 그러나 이를 위해서는 C++이 가진 대수적 데이터 구조의 몇 가지 타입을 이해할 수 있어야하며, 이런 데이터 구조를 일반적인 템플릿으로 구현하고 이 구조에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 또한 직접 구현할 수 있어야한다.&lt;/p&gt;
&lt;p&gt;먼저 Haskell에서 재귀적인 합 타입으로 정의된 트리 데이터 구조를 한번 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서 언급한 대로, C++에서 합 타입을 구현하는 방법 중 하나는 바로 클래스 계층 구조를 이용하는 것이다. 객체지향 언어에서는 기본 클래스 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt;의 가상 함수(Virtual functions)로 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 구현한 뒤 모든 하위 클래스에서 이를 재정의하는 방향이 자연스러울 것이다.&lt;/p&gt;
&lt;p&gt;하지만 아쉽게도 이런 방법을 사용하는 것은 불가능하다. 왜냐하면 결국 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;은 템플릿이며, 이는 &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; 포인터로 전달되는 객체의 타입 뿐 아니라 적용된 함수의 반환 타입이 매개변수화되어야 한다는 것을 의미한다. 하지만 C++에서는 가상 함수를 템플릿화 할 수 없다. 대신 우리는 &lt;code class=&quot;language-text&quot;&gt;dynamic_cast&lt;/code&gt;를 사용하여 패턴 매칭을 대체하고 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 일반적인 자유 함수로 구현할 것이다.&lt;/p&gt;
&lt;p&gt;기본 클래스는 동적 캐스팅을 지원하기 위해 최소 하나의 가상 함수를 정의해야하며, 이 경우 우리는 소멸자(Destructor)를 가상 함수로 정의할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;숨겨진 &lt;code class=&quot;language-text&quot;&gt;Identity&lt;/code&gt; 펑터인 &lt;code class=&quot;language-text&quot;&gt;Leaf&lt;/code&gt;를 정의하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    T _label&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Leaf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Node&lt;/code&gt;는 곱 타입으로 정의할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Tree&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; _left&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Tree&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; _right&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Tree&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Tree&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 구현할 때는 &lt;code class=&quot;language-text&quot;&gt;Tree&lt;/code&gt;의 타입에 따른 동적 디스패치를 활용할 것이다. &lt;code class=&quot;language-text&quot;&gt;Leaf&lt;/code&gt;의 경우에는 &lt;code class=&quot;language-text&quot;&gt;Identify&lt;/code&gt; 버전의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 적용하고, &lt;code class=&quot;language-text&quot;&gt;Node&lt;/code&gt;의 경우에는 두 개의 &lt;code class=&quot;language-text&quot;&gt;Tree&lt;/code&gt; 펑터의 복사본과 결합된 이항 펑터처럼 처리할 것이다. 물론 C++ 프로그래머들은 이런 사고 방식과 용어로 코드를 분석하는 것에 익숙하지 않을 수 있지만, 이 모든 과정이 결국 카테고리론적 사고를 연습하는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Tree&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Tree&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Leaf&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; pl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;dynamic_cast&lt;/span&gt; &lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Leaf&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Leaf&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pl&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_label&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Node&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; pn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;dynamic_cast&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Node&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pn&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_left&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pn&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;_right&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서는 간결함을 위해 메모리나 리소스 관리 문제를 무시하고 있지만, 실제 코드에서는 정책에 따라 &lt;code class=&quot;language-text&quot;&gt;unique&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;shared&lt;/code&gt; 같은 스마트 포인트를 사용할 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 C++로 작성한 &lt;code class=&quot;language-text&quot;&gt;Tree&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 Haskell에서 작성한 버전으로 바꿔보자면 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 이 역시 &lt;code class=&quot;language-text&quot;&gt;DeriveFunctor&lt;/code&gt; 확장 기능을 사용하면 컴파일러에 의해 자동으로 구현될 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;85-writer-펑터&quot; style=&quot;position:relative;&quot;&gt;8.5 Writer 펑터&lt;a href=&quot;#85-writer-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;85 writer 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이전에 설명했던 &lt;a href=&quot;/2024/02/20/category-theory-for-programmers-4-kleisli-category&quot;&gt;크라이슬리 카테고리(Kleisli Category)&lt;/a&gt; 섹션에서 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 펑터에 대해서 다시 설명하겠다고 했던 것을 기억하는가? 해당 카테고리에서의 사상들은 꾸며진(embellished) 함수로 표현되어 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 데이터 구조를 반환했었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;필자는 이렇게 꾸며진 기능이 어떤 방식으로든 엔도 펑터와 관련이 있다고 말했다. 그리고 실제로 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 타입 생성자는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대해 펑터적이다. 심지어 이를 위해 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 구현할 필요도 없다. 왜냐하면 반환된 타입은 단순한 곱 타입이기 떄문이다.&lt;/p&gt;
&lt;p&gt;일반적으로 크라이슬리 카테고리와 펑터 간의 관계는 다음과 같다. 크라이슬리 카테고리는 카테고리이기 때문에 합성과 항등성을 정의해야한다. 그리고 합성은 fish(&lt;code class=&quot;language-text&quot;&gt;&gt;=&gt;&lt;/code&gt;) 연산자에 의해 제공된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;=&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;m1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m2&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 항등 사상은 &lt;code class=&quot;language-text&quot;&gt;return&lt;/code&gt;이라고 불리는 함수를 통해 제공했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 이 두 함수들의 타입을 오랜 시간 들여다 보다보면, &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;으로 사용할 수 있는 올바른 타입의 함수를 생성하는 방법을 찾을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 예시에서 fish 연산자는 우리에게 익숙한 &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, 그리고 인수에 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 적용한 결과에 다시 &lt;code class=&quot;language-text&quot;&gt;return&lt;/code&gt;을 적용한 람다, 두 함수를 합성한다.&lt;/p&gt;
&lt;p&gt;아마 여기서 가장 이해하기 어려운 부분은 &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;의 사용법일 것이다. fish 연산자의 인수는 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;과 같은 일반 타입을 가져와서 꾸며진(embellished) 타입을 반환하는 함수여야 한다고 생각할 수 있겠지만 사실은 아니다. 아무도 &lt;code class=&quot;language-text&quot;&gt;a -&gt; Writer b&lt;/code&gt;에서의 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 일반 타입이어야 한다고 한 적은 없다. 이것은 그저 타입 변수일뿐이므로 어떤 것이든 될 수 있으며, 심지어 &lt;code class=&quot;language-text&quot;&gt;Writer b&lt;/code&gt;와 같이 이미 꾸며진 타입이 될 수도 있다.&lt;/p&gt;
&lt;p&gt;그래서 &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;Writer a&lt;/code&gt;를 받아서 그대로 &lt;code class=&quot;language-text&quot;&gt;Writer a&lt;/code&gt;를 반환할 것이다. fish 연산자는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 값을 꺼내어 람다의 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; 인자로 전달할 것이다. 이후 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;는 그것을 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 변환하고, &lt;code class=&quot;language-text&quot;&gt;return&lt;/code&gt;은 이 결과를 꾸며 최종적으로 &lt;code class=&quot;language-text&quot;&gt;Writer b&lt;/code&gt;로 만들 것이다. 이 모든 것을 조합한다면 우리는 &lt;code class=&quot;language-text&quot;&gt;Writer a&lt;/code&gt;를 가져와 &lt;code class=&quot;language-text&quot;&gt;Writer b&lt;/code&gt;를 반환하는 함수를 얻게된다. 즉, &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이 해야하는 것과 정확히 같은 일을 하는 것이다.&lt;/p&gt;
&lt;p&gt;이 정의에서 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt;는 다른 임의의 타입 생성자로 변경될 수 있기 때문에 이 인자는 매우 일반적이라고 할 수 있다. 뭐가 되었던 fish 연산자와 &lt;code class=&quot;language-text&quot;&gt;return&lt;/code&gt;을 지원한다면 이를 활용하여 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 정의할 수 있다는 것이다. 따라서 크라이슬리 카테고리에서의 장식(embellishment)은 항상 펑터라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;사실 우리가 방금 정의했던 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;과 &lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;deriving Functor&lt;/code&gt;&lt;/strong&gt; 확장 기능을 통해 컴파일러가 생성해주는 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;은 동일하다. 이는 Haskell이 다형성 함수를 구현하는 방식 때문인데, 이를 매개변수 다형성(Parametric polymorphism)이라고 하며, 공짜 정리(Theorems for free)라고 불리는 정리의 원천이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;매개변수 다형성(Parametric polymorphism)은 함수나 데이터 유형이 여러 타입에 대해 동작할 수 있도록 하는 기능이며, 타입스크립트의 Generic Type도 매개변수 다형성의 구현 중 하나이다.&lt;/p&gt;
&lt;p&gt;공짜 정리(Theorems for free)는 어떤 하나의 정리를 통해 다른 정리가 추가적인 증명없이도 자동으로 성립하는 것을 의미하므로, 매개변수 다형성 또한 공짜 정리의 한 측면이라고 볼 수 있는 것이다. 타입스크립트로 예를 들자면 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;nonEmptyArray&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;nonEmptyArray&lt;/code&gt; 함수는 인자가 &lt;code class=&quot;language-text&quot;&gt;number[]&lt;/code&gt; 타입이든 &lt;code class=&quot;language-text&quot;&gt;string[]&lt;/code&gt; 타입이든 상관없이 일관된 동작을 제공한다. 즉, 다형적인 동작이 제대로 정의되었다면, &lt;code class=&quot;language-text&quot;&gt;number[]&lt;/code&gt; 타입에 대해 제대로 작동한다는 사실이 증명됨과 함께 &lt;code class=&quot;language-text&quot;&gt;string[]&lt;/code&gt; 타입에 대한 동작이 제대로 작동한다는 보장도 함께 공짜로 성립되는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이러한 정리가 의미하는 것 중 하나는 특정 타입 생성자에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이 존재하고 이 함수가 항등성을 보존하고 있다면, 그 구현 방법은 유일해야 한다는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;86-공변적-펑터와-반공변적-펑터covariant-and-contravariant-functors&quot; style=&quot;position:relative;&quot;&gt;8.6 공변적 펑터와 반공변적 펑터(Covariant and Contravariant Functors)&lt;a href=&quot;#86-%EA%B3%B5%EB%B3%80%EC%A0%81-%ED%8E%91%ED%84%B0%EC%99%80-%EB%B0%98%EA%B3%B5%EB%B3%80%EC%A0%81-%ED%8E%91%ED%84%B0covariant-and-contravariant-functors&quot; aria-label=&quot;86 공변적 펑터와 반공변적 펑터covariant and contravariant functors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 펑터에 대해서 살펴보았으니, &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터도 다시 한번 살펴보자. 다시 한번 이야기하지만 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터는 부분적용된 함수 화살표 타입 생성자를 기반으로 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 정의를 타입 동의어를 사용하여 다시 작성해보면 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt; 인스턴스는 아래와 같이 정의된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;쌍 타입 생성자나 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt; 타입 생성자와 마찬가지로 함수 타입 생성자 또한 두 개의 타입 인자를 받는다. 기억을 되짚어보면 쌍과 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;는 자신들이 받는 각각의 인자에 대해 펑터적이었고, 이를 이항 펑터(bifunctor)라고 한다고 했다. 그렇다면 함수 생성자도 두 개의 타입 인자를 받고 있으니 이들과 동일하게 이항 펑터일까?&lt;/p&gt;
&lt;p&gt;백문이불여일견이니 직접 확인해보자. 우선 첫 번째 인자에 대해 펑터적인지 확인해보겠다. 우선 타입 동의어에서부터 시작해볼 것이다. 아래 정의는 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt;에서 단지 인수의 순서만 뒤바뀐 형태이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 반환 타입인 &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;을 고정하고 인수 타입인 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 변형을 가할 것이다. 그리고 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 변형하는 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 구현하기 위한 타입 시그니처는 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;인수로 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 받고 각각 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;을 반환하는 두 개의 함수만 있는 경우, 이들을 사용하여 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;를 받아 &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;을 반환하는 함수를 만들 수 있는 방법은 존재하지 않는다.&lt;/p&gt;
&lt;p&gt;하지만 첫 번째 함수를 반대로 뒤집을 수 있다면 상황은 달라진다. 즉, 첫 번째 함수가 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;를 받아 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 반환하는 함수가 되도록 만들어주면 되는 것이다. 우리는 임의의 함수를 막 뒤집을 수는 없지만, 반대 카테고리로 이동해볼 수는 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;필자가 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt;에 대한 설명을 하다가 갑자기 반대 카테고리에 대한 이야기를 하고 있어서 설명의 흐름이 어색하다. 결과적으로 말하자면 &lt;code class=&quot;language-text&quot;&gt;Reader r a&lt;/code&gt;는 두 인자를 받아 &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 변형하는 매핑을 의미하기 때문에 이항 펑터가 아니다.&lt;/p&gt;
&lt;p&gt;앞서 보았던 쌍이나 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;의 경우 자신들이 받는 인수의 순서를 변경하더라도 연산의 결과는 동일하게 보장된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;bimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 패턴 매칭을 통해 연산을 적용하기 때문에&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 인자의 순서가 g f (x, y)가 되어도 f는 x에, g는 y에 적용된다.&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;은 함수의 합성이기 때문에 첫 번째 인자의 결과가 두 번째 인자에 의존하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
	  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 만약 합성의 순서가 g . f가 된다면 연산 결과가 달라지거나&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 혹은 합성 자체가 불가능한 상황이 발생할 수도 있다.&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;필자는 이러한 &lt;code class=&quot;language-text&quot;&gt;Reader&lt;/code&gt; 펑터의 특성을 보이기 위해, 인수의 순서를 반대로 뒤집은 &lt;code class=&quot;language-text&quot;&gt;Op&lt;/code&gt;라는 타입을 예로 들어 설명하고 있는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;반대 카테고리가 기억나지 않을 수 있으니 간단하게 복습해보자. 모든 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 대한 반대 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 같은 대상들을 가지고 있지만 모든 화살표(사상)의 방향이 반대로 뒤집어진 카테고리이다.&lt;/p&gt;
&lt;p&gt;그럼 이제 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 다른 임의의 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 사이를 이동하는 펑터를 떠올려보자.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F::C^{op} → D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;이런 펑터는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 어떤 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f^{op} :: a → b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F f^{op} :: F a → F b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 매핑한다. 그러나 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 원래 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서의 어떤 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f :: b → a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 해당한다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 서로 반전되어있음에 주목하자.&lt;/p&gt;
&lt;p&gt;이렇게 반대 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 나아가는 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 정의했다. 그렇다면 이제 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 사용하여 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 바로 나아가는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 매핑도 생각해볼 수 있다. 즉, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로의 매핑이다. 하지만 사실 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 펑터가 아니다. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 마찬가지로 대상들을 동일하게 매핑하지만, 사상을 매핑할 때는 반대로 뒤집어서 매핑하기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f :: b → a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 반대 사상인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f^{op} :: a → b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 매핑한 다음, 이를 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 적용하여 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F f^{op} :: F a→F b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 얻어야 한다.&lt;/p&gt;
&lt;p&gt;주어진 조건에 따라 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Fa&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Ga&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 동일하고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Fb&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Gb&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 동일하다고 가정할 때, 전체적인 흐름은 아래와 같이 나타내볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G f :: (b → a) → (G a → G b) 		&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;이렇게 사상의 방향을 반전하는 카테고리 간의 매핑을 반공변적 펑터(Contravariant Functor)라고 한다. 반공변적 펑터는 반대 카테고리에서의 일반적인 펑터일 뿐이다. 그리고 우리가 지금까지 공부해왔던 일반적인 펑터는 공변적 펑터(Covariant Functor)라고 한다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 530px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2675b6c5c6369f38ae301b55685cd3b0/d0861/5.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 98.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGQABAQEAAwAAAAAAAAAAAAAAAAIBAwQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAfTrYbuIFOA8oT//xAAbEAACAwADAAAAAAAAAAAAAAABAgADEhEhMv/aAAgBAQABBQKx3BqZiY/OjrKeGUGFBkdD/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEQESEx/9oACAEBAAY/AqQ75GMeiLn/xAAbEAACAgMBAAAAAAAAAAAAAAAAARFBITFREP/aAAgBAQABPyGplMqy742MHZDRa3g7JxslGmR9l0SBKj//2gAMAwEAAgADAAAAEMMIvP/EABYRAAMAAAAAAAAAAAAAAAAAABARQf/aAAgBAwEBPxBxCD//xAAWEQADAAAAAAAAAAAAAAAAAAARICH/2gAIAQIBAT8QgT//xAAcEAEBAQEAAgMAAAAAAAAAAAABESEAUWEQMZH/2gAIAQEAAT8QZnGXyeeLLQNEV9evjYwTJsXzxm5dOP3lb5xq3ldAT75DDobmcddABe//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;5&quot; title=&quot;&quot; src=&quot;/static/2675b6c5c6369f38ae301b55685cd3b0/d0861/5.jpg&quot; srcset=&quot;/static/2675b6c5c6369f38ae301b55685cd3b0/0913d/5.jpg 160w,
/static/2675b6c5c6369f38ae301b55685cd3b0/cb69c/5.jpg 320w,
/static/2675b6c5c6369f38ae301b55685cd3b0/d0861/5.jpg 530w&quot; sizes=&quot;(max-width: 530px) 100vw, 530px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;아래는 Haskell에서 반공변적인 (엔도)펑터를 정의하는 타입 클래스이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 아까 정의했던 타입 생성자 &lt;code class=&quot;language-text&quot;&gt;Op&lt;/code&gt;의 인스턴스는 아래와 같이 정의될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
  	&lt;span class=&quot;token comment&quot;&gt;-- (b -&gt; a) -&gt; Op r a -&gt; Op r b&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Op&lt;/code&gt;의 내용인 함수 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;의 앞에 자신을 삽입한다는 것에 주목하자. (함수 합성의 연산 순서는 오른쪽에서 왼쪽이다.)&lt;/p&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;Op&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;contramap&lt;/code&gt;의 정의는 단지 인자를 뒤집은 함수 합성 연산자일 뿐이라는 것을 알 수 있으며, 이 사실을 알았다면 이제 더 간결하게 만들어 볼 수도 있다.&lt;/p&gt;
&lt;p&gt;여기 인자를 뒤집는데 사용되는 특수한 함수인 &lt;code class=&quot;language-text&quot;&gt;flip&lt;/code&gt;이 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;flip&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;flip&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러면 이제 &lt;code class=&quot;language-text&quot;&gt;contramap&lt;/code&gt;의 정의를 이렇게 간단하게 바꿔볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;contramap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;flip&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;87-프로펑터profunctors&quot; style=&quot;position:relative;&quot;&gt;8.7 프로펑터(Profunctors)&lt;a href=&quot;#87-%ED%94%84%EB%A1%9C%ED%8E%91%ED%84%B0profunctors&quot; aria-label=&quot;87 프로펑터profunctors permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;우리는 함수 화살표 연산자가 첫 번째 인자에서 반공변 변형이 되고, 두 번째 인자에서 공변 변형이 되는 상황을 보았다. 이런 개념에 대한 명칭도 있을까?&lt;/p&gt;
&lt;p&gt;만약 대상 카테고리가 &lt;em&gt;Set&lt;/em&gt;이라면 이 개념을 프로펑터(Profunctor)라고 부른다. 반공변적 펑터는 반대 카테고리에서의 공변적 펑터와 동일하기 때문에, 프로펑터는 아래와 같이 정의된다.&lt;/p&gt;
&lt;div class=&quot;math math-display&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C^{op} × D → Set 	&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7977em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;일단 Haskell 타입을 집합이라고 가정해보면, 우리는 첫 번째 인자에 대해 반공변적 펑터적이고 두 번째 인자에 대해서는 펑터적인 두 개의 인자를 받는 타입 생성자 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;Profuctor&lt;/code&gt;라는 이름을 부여할 수 있다. 아래는 &lt;code class=&quot;language-text&quot;&gt;Data.Profuctor&lt;/code&gt; 라이브러리에서 가져온 타입 클래스의 모습이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;dimap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;d&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;dimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;lmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;rmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;lmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;lmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;
  	&lt;span class=&quot;token hvariable&quot;&gt;rmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;rmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dimap&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;세 함수 모두 기본 구현이 제공된다. &lt;code class=&quot;language-text&quot;&gt;Bifunctor&lt;/code&gt;와 마찬가지로 &lt;code class=&quot;language-text&quot;&gt;Profuctor&lt;/code&gt;의 인스턴스를 선언할 때는 &lt;code class=&quot;language-text&quot;&gt;dimap&lt;/code&gt;을 구현하고 &lt;code class=&quot;language-text&quot;&gt;lmap&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;rmap&lt;/code&gt;에 대한 기본값을 사용하거나, 혹은 &lt;code class=&quot;language-text&quot;&gt;lmap&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;rmap&lt;/code&gt;을 모두 구현하고 &lt;code class=&quot;language-text&quot;&gt;dimap&lt;/code&gt;에 대한 기본값을 사용할 수 있는 선택권이 있다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 497px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8c3e7c302a315abaa1d56875acd0c0f8/fce5f/6.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 81.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHXTVAto0T/xAAaEAEAAgMBAAAAAAAAAAAAAAABAAIDERIx/9oACAEBAAEFAu0u5LTHvlqQGHn/xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwEJ/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAwADAAAAAAAAAAAAAAAAABARITJB/9oACAEBAAY/ApxZLKaL/8QAGxABAAICAwAAAAAAAAAAAAAAAQARITFRgZH/2gAIAQEAAT8hdKZU4rp1PYl1dnEKtMzBQxU//9oADAMBAAIAAwAAABAbz//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/EGZ//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/ENCf/8QAHBABAAMBAQADAAAAAAAAAAAAAQARITFRQWFx/9oACAEBAAE/EEiAW29I9Djvo5+zSoVenzHWlK+2QAU1W3V3WQhFAc8n/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;6&quot; title=&quot;&quot; src=&quot;/static/8c3e7c302a315abaa1d56875acd0c0f8/fce5f/6.jpg&quot; srcset=&quot;/static/8c3e7c302a315abaa1d56875acd0c0f8/0913d/6.jpg 160w,
/static/8c3e7c302a315abaa1d56875acd0c0f8/cb69c/6.jpg 320w,
/static/8c3e7c302a315abaa1d56875acd0c0f8/fce5f/6.jpg 497w&quot; sizes=&quot;(max-width: 497px) 100vw, 497px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;여기까지 왔으면 이제 함수 화살표 연산자가 &lt;code class=&quot;language-text&quot;&gt;Profuctor&lt;/code&gt;의 인스턴스라는 것을 단언할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;dimap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;ab&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;bc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;ab&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;lmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;flip&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;rmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;프로펑터는 Haskell 렌즈 라이브러리에서 응용되고 있으며, 추후 ends와 coends에 대해 이야기할 때 다시 한번 자세히 설명할 것이다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 7. 펑터]]></title><description><![CDATA[이번 챕터에서는 펑터(Functor)에 대해서 이야기를 해보려고 한다. 펑터는 간단하지만 매우 강력한 개념이며 카테고리 이론은 이처럼 간단하지만 강력한 아이디어로 가득 차있다.]]></description><link>https://evan-moon.github.io/2024/03/15/category-theory-for-programmers-7-functors/</link><guid isPermaLink="false">20240315-category-theory-for-programmers-7-functors</guid><pubDate>Tue, 19 Mar 2024 10:30:00 GMT</pubDate><content:encoded>&lt;p&gt;이번 챕터에서는 펑터(Functor)에 대해서 이야기를 해보려고 한다. 펑터는 간단하지만 매우 강력한 개념이며 카테고리 이론은 이처럼 간단하지만 강력한 아이디어로 가득 차있다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;펑터는 카테고리 간의 매핑이다. 즉, 두 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 주어졌을 때, 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상을 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상으로 매핑하는 것이며, 결국 대상들에 대한 함수라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;만약 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라고 한다면, 우리는 매핑된 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대상을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라고 표현할 수 있다. 하지만 카테고리는 대상으로만 구성되어있지 않으며 대상과 그들을 연결하는 사상까지 모두 포함하는 개념이다. 즉, 펑터는 대상 뿐 아니라 사상 또한 매핑하며, 이런 경우에는 사상에 대한 함수라고 볼 수도 있다. 그렇다고 펑터가 마음대로 사상을 매핑하는 것은 아니고, 반드시 사상으로 연결된 대상들의 구조를 그대로 보존해야 한다.&lt;/p&gt;
&lt;p&gt;만약 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 있는 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 연결하고 있다면,&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;펑터를 통해 매핑된 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 있는 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 또한 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 동일한 구조로 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 연결해야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 548px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/53ed4e9ec17829d825f87748ed6a6e02/a8866/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 87.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAMCBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB9adM10MorISoX//EABoQAQACAwEAAAAAAAAAAAAAAAECEgARIjH/2gAIAQEAAQUCktpOiG6zenyCpgFs/8QAFREBAQAAAAAAAAAAAAAAAAAAESD/2gAIAQMBAT8BY//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABoQAAICAwAAAAAAAAAAAAAAAAAQAREhUcH/2gAIAQEABj8CNmVfXK//xAAbEAACAwEBAQAAAAAAAAAAAAABEQAhMUFREP/aAAgBAQABPyEVHT9hC0CfJQ7hlByUwfFaYknwwh7MmPn/2gAMAwEAAgADAAAAEODAvP/EABgRAAMBAQAAAAAAAAAAAAAAAAABMRAR/9oACAEDAQE/EOUUdWf/xAAWEQEBAQAAAAAAAAAAAAAAAAABEDH/2gAIAQIBAT8QCGT/xAAfEAEAAgICAgMAAAAAAAAAAAABETEAIUFREIGRwdH/2gAIAQEAAT8Q3IVVhAlz6yHKYJk/cvqubuOMAcKrQd85WGzaKH3iBSTs5MAQBOkw0XxeP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/53ed4e9ec17829d825f87748ed6a6e02/a8866/1.jpg&quot; srcset=&quot;/static/53ed4e9ec17829d825f87748ed6a6e02/0913d/1.jpg 160w,
/static/53ed4e9ec17829d825f87748ed6a6e02/cb69c/1.jpg 320w,
/static/53ed4e9ec17829d825f87748ed6a6e02/a8866/1.jpg 548w&quot; sizes=&quot;(max-width: 548px) 100vw, 548px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;여기서 알 수 있듯이 펑터는 카테고리의 구조를 그대로 보존한다. 한 카테고리 내에서 연결되어있는 것들은 펑터를 통해 매핑된 카테고리에서도 그대로 연결되어 있는 것이다. 이에 더해 카테고리에는 단순히 대상을 사상으로 연결하는 것 뿐 아니라 사상 간의 합성이라는 개념 또한 존재한다.&lt;/p&gt;
&lt;p&gt;사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;h&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 합성사상인 상황을 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그렇다면 펑터 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 통해 만들어진 카테고리의 사상들의 합성 관계도 이와 동일하게 유지된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 384px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6c626a002083ba1ab990172bf55de07e/4ecad/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 108.74999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAWABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMCBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe3msioEwqD/xAAaEAACAwEBAAAAAAAAAAAAAAAAAQIRIRAS/9oACAEBAAEFAnI9ULVaFURaUhR5/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGhAAAwADAQAAAAAAAAAAAAAAAAEhEDFRQf/aAAgBAQAGPwKJnct+ENFvMf/EABwQAQADAAIDAAAAAAAAAAAAAAEAESEQUWFxgf/aAAgBAQABPyGnFPqWvrm4qHuJNLvUYUUtiBasmy03xN3IH4OP/9oADAMBAAIAAwAAABBTxzz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEBAAMBAAMAAAAAAAAAAAABEQAhMUGBkcH/2gAIAQEAAT8QZINb4MQEg2zXeW5NRIsfMJBvlbfjFom723m8HkXiNHFUK9MbyEyDc6TX3+YAGgPdZ//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/6c626a002083ba1ab990172bf55de07e/4ecad/2.jpg&quot; srcset=&quot;/static/6c626a002083ba1ab990172bf55de07e/0913d/2.jpg 160w,
/static/6c626a002083ba1ab990172bf55de07e/cb69c/2.jpg 320w,
/static/6c626a002083ba1ab990172bf55de07e/4ecad/2.jpg 384w&quot; sizes=&quot;(max-width: 384px) 100vw, 384px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;마지막으로 우리는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 안의 모든 항등사상들이 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 항등사상들로 매핑되는 상황 또한 생각해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;id_a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;id_Fa&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;id_a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 항등사상이며, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;id_Fa&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 항등사상이다. 이처럼 항상 카테고리의 구조를 보존해야한다는 조건들로 인해 펑터는 일반적인 함수보다 더 제한적인 개념이 된다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 302px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b3c6b68dbbf4939beb37c24ad5731725/7a297/3.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 133.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHuU0ErCuO4JH//xAAbEAACAgMBAAAAAAAAAAAAAAAAAQIRAyAiIf/aAAgBAQABBQKVnTFY1ZGKih+LH09P/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGhAAAQUBAAAAAAAAAAAAAAAAAQAQESAhMf/aAAgBAQAGPwLDC6taA5INf//EABwQAQACAgMBAAAAAAAAAAAAAAEAERAhMUFRYf/aAAgBAQABPyE1vSHq4fCnJU0cL+TX2leToZhWMQgJe/LwglJcAOMf/9oADAMBAAIAAwAAABBDCDD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAdEAEAAgIDAQEAAAAAAAAAAAABESEAQRAxUWGB/9oACAEBAAE/EHbOPb38vK5B42BPO+3NWPpWHfOzaJ+OEDYbWVfV28GghBti8E+IR7Qsvz5viBAeJOAUCWaOP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3&quot; title=&quot;&quot; src=&quot;/static/b3c6b68dbbf4939beb37c24ad5731725/7a297/3.jpg&quot; srcset=&quot;/static/b3c6b68dbbf4939beb37c24ad5731725/0913d/3.jpg 160w,
/static/b3c6b68dbbf4939beb37c24ad5731725/7a297/3.jpg 302w&quot; sizes=&quot;(max-width: 302px) 100vw, 302px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;만약 어떤 카테고리를 각 대상들이 사상으로 연결되어있는 일종의 네트워크라고 상상해보자. 펑터는 각 대상과 사상을 그저 매핑하는 개념일뿐이므로 네트워크의 요소들을 서로 분리해내는 것은 절대 불가능하다. 펑터로 대상들을 합칠 수도 있고 여러 사상들을 하나로 붙혀놓을 수도 있겠지만 분해하는 것은 불가능한 것이다.&lt;/p&gt;
&lt;p&gt;이와 같이 분해가 불가능하다는 제약은 미적분에서 볼 수 있는 연속성의 조건과 유사하다. 이런 의미에서 펑터는 “연속적”이라고 볼 수도 있다. 또한 마치 정의역과 공역의 관계를 축소나 포함이라는 시각으로 바라보는 것과 유사하게 펑터 또한 동일한 시각으로 바라볼 수 있다. 예를 들면 펑터의 소스가 되는 카테고리가 대상 카테고리보다 더 작을 때는 포함과 같은 개념으로 볼 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;한번 극단적인 예시를 생각해보자. 펑터의 소스가 되는 카테고리는 단 하나의 대상과 하나의 항등사상만으로 이루어진 단일대상 카테고리가 될 수도 있다. 이처럼 단일대상 카테고리를 다른 카테고리로 매핑하는 펑터는 단순히 해당 카테고리에서 하나의 대상을 선택하는 것과 다를 게 없다. 이는 단일원소집합에서 하나의 원소를 선택하는 사상의 특성과 완전히 유사하다.&lt;/p&gt;
&lt;p&gt;소스 카테고리를 최대한 축소하는 펑터는 상수 펑터(Constant Functor), &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Δ&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\Delta c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;Δ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 불린다. 이 펑터는 소스 카테고리의 모든 대상을 대상 카테고리에서 선택된 하나의 대상인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로, 그리고 소스 카테고리의 모든 사상을 항등사상인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;id_c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 매핑한다. 이 펑터는 마치 블랙홀처럼 작동하여 모든 것을 하나의 특이점으로 압축해버린다. 우리가 추후 한계(Limits)와 공한계(Colimits)에 대해 이야기할 때 이러한 펑터를 더 자세히 살펴볼 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;작가의 설명만 보면 마치 상수 펑터(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Δ&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\Delta c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;Δ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)가 어떤 카테고리를 다른 카테고리로 매핑하며 압축하는 녀석으로 보일 수 있지만, 사실 상수 펑터는 특정 카테고리를 자기 자신으로 매핑하는 엔도펑터(EndoFunctor)이다. (엔도펑터에 대한 설명은 바로 다음 섹션에 나온다.)&lt;/p&gt;
&lt;p&gt;즉, 상수 펑터는 어떤 카테고리의 모든 대상을 그 카테고리 내의 대상 하나로 매핑(압축)하는 개념이라고 보면 된다. 이 과정에서 카테고리의 대상들을 연결하던 임의의 사상들은 모두 선택된 대상의 항등 사상으로 매핑된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;71-프로그래밍에서의-펑터&quot; style=&quot;position:relative;&quot;&gt;7.1 프로그래밍에서의 펑터&lt;a href=&quot;#71-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%97%90%EC%84%9C%EC%9D%98-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;71 프로그래밍에서의 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이제부터는 실질적인 프로그래밍에 대해서 이야기해보자. 이미 우리는 프로그래밍의 세계에서 타입과 함수로 이루어진 카테고리를 다루고 있다. 이번에는 이 카테고리를 자기 자신으로 매핑하는 펑터, 엔도펑터(EndoFunctor)에 대해서 생각해보려고 한다.&lt;/p&gt;
&lt;p&gt;자, 타입으로 이루어진 카테고리에서의 엔도펑터는 무엇일까? 이 펑터는 타입을 타입으로 매핑하는 펑터일 것이다. 사실 여러분은 이미 이러한 매핑의 예시를 숱하게 봐왔을테지만 단지 그것이 엔도펑터라는 것을 깨닿지 못 했을 뿐이다. 아래 몇 가지 예시를 한번 살펴보자.&lt;/p&gt;
&lt;h3 id=&quot;711-maybe-펑터&quot; style=&quot;position:relative;&quot;&gt;7.1.1 Maybe 펑터&lt;a href=&quot;#711-maybe-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;711 maybe 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;의 정의는 어떠한 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;Maybe a&lt;/code&gt;라는 타입으로 매핑하는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 중요한 포인트가 하나 있다. &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 자체는 타입이 아니라 타입 생성자(Type Constructor)라는 것이다. 타입 생성자를 타입으로 변환하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;과 같은 타입 인자를 생성자에게 제공해야 한다. 즉, 아무 인자로 받지 않는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;는 타입에 대한 함수를 나타내는 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;를 펑터로 변환해볼 수 있을까? (프로그래밍 맥락에서 펑터에 대해 이야기할 때는 거의 항상 엔도펑터를 이야기한다는 사실을 유념하자.) 펑터는 대상(타입)의 매핑 뿐만 아니라 사상(함수)의 매핑도 모두 포함하는 개념이다. 한번 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 나아가는 임의의 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 있다고 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 &lt;code class=&quot;language-text&quot;&gt;Maybe a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;Maybe b&lt;/code&gt;로 나아가는 함수를 생성하고 싶다. 이러한 함수를 제대로 정의하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;를 구성하는 두 생성자인 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;에 대해 고려해야한다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;의 경우에는 그저 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;을 반환해주기만 하면 되니 간단하다. 그리고 인자가 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;인 경우에는 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;가 가지고 있는 값에 적용해주면 될 것이다.&lt;/p&gt;
&lt;p&gt;즉, &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;라는 펑터를 거친 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;의 모습은 아래와 같은 함수가 된다. (Haskell에서는 변수명에 아포스트로피(&lt;code class=&quot;language-text&quot;&gt;’&lt;/code&gt;)를 사용할 수 있으며, 이 기능은 아래와 같은 경우에 매우 편리하다.)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&apos;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서는 펑터가 사상을 매핑하는 행위를 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이라는 고차함수로 구현하며, &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;의 경우에는 아래와 같은 정의가 될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 469px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b4a1919d61c677ca0dd43a79a5bfd207/a76eb/4.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 73.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHbS2BwD//EABoQAQABBQAAAAAAAAAAAAAAAAESABARITH/2gAIAQEAAQUCllWLT3Zb/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAwADAAAAAAAAAAAAAAAAAAEQEUFR/9oACAEBAAY/AsI24js//8QAHhABAAICAQUAAAAAAAAAAAAAAQARMUEQIWFxgZH/2gAIAQEAAT8hr9DtELroxBsuk8xIAZ3KIp9+P//aAAwDAQACAAMAAAAQQM//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAdEAEAAgIDAQEAAAAAAAAAAAABABEhQTFRYXGB/9oACAEBAAE/EHMd7InjUDW2mS38OcblXkNCmCU530ryaYHJgv7BUFKep//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;4&quot; title=&quot;&quot; src=&quot;/static/b4a1919d61c677ca0dd43a79a5bfd207/a76eb/4.jpg&quot; srcset=&quot;/static/b4a1919d61c677ca0dd43a79a5bfd207/0913d/4.jpg 160w,
/static/b4a1919d61c677ca0dd43a79a5bfd207/cb69c/4.jpg 320w,
/static/b4a1919d61c677ca0dd43a79a5bfd207/a76eb/4.jpg 469w&quot; sizes=&quot;(max-width: 469px) 100vw, 469px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;우리는 종종 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이 함수를 리프트(lift)한다고 말한다. 이렇게 리프팅된 함수는 이제 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 타입의 값에 작용하는 함수가 되었다.&lt;/p&gt;
&lt;p&gt;또한 커링(Currting)으로 인해 위 정의는 하나의 함수 &lt;code class=&quot;language-text&quot;&gt;a → b&lt;/code&gt;를 받아서 다른 함수 &lt;code class=&quot;language-text&quot;&gt;Maybe a → Maybe b&lt;/code&gt;를 반환하는 함수, 그리고 &lt;code class=&quot;language-text&quot;&gt;a → b&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Maybe a&lt;/code&gt;라는 두 개의 인자를 받아 &lt;code class=&quot;language-text&quot;&gt;Maybe b&lt;/code&gt;를 반환하는 함수, 총 두 가지 방식으로 해석될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 특성들을 기반으로 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 구현해보면 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 적용할 함수 f와 Just x를 인자로 받아,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- Just가 가진 값에 함수 f가 적용된 꼴인 Just (f x)를 반환한다.&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리가 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 타입 생성자와 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 함수가 펑터를 형성한다는 것을 보이기 위해서는 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 함수가 항등과 합성의 개념을 보존한다는 것을 증명해야한다. 이러한 것들을 “펑터 법칙(The Functor Laws)”이라는 거창한 이름으로 부르긴 하지만 사실은 그저 펑터가 카테고리의 구조를 보존한다는 것을 보장해야한다는 의미이다.&lt;/p&gt;
&lt;h3 id=&quot;712-방정식-추론equational-reasoning&quot; style=&quot;position:relative;&quot;&gt;7.1.2 방정식 추론(Equational Reasoning)&lt;a href=&quot;#712-%EB%B0%A9%EC%A0%95%EC%8B%9D-%EC%B6%94%EB%A1%A0equational-reasoning&quot; aria-label=&quot;712 방정식 추론equational reasoning permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;펑터 법칙을 증명하기 위해 방정식 추론(Equational Reasoning)을 사용해보려고 한다. 이는 Haskell에서 흔하게 사용되는 증명 기법인데, Haskell 함수가 좌변이 우변과 같다는 동등성(Equality)으로 정의된다는 사실을 이용하는 기법이다. 어떤 코드를 동작이 동일한 다른 코드로 대체할 수도 있고 변수명의 충돌을 피하기 위해 변수명을 변경할 수도 있는데, 이는 함수를 인라인화하는 행위나 반대로 표현식을 함수로 리팩토링하는 행위로 생각할 수도 있다. 한번 항등함수를 예시로 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 함수가 존재한다면 이제 우리는 어떤 표현식에서 &lt;code class=&quot;language-text&quot;&gt;id y&lt;/code&gt;를 보았을 때, 이 코드를 &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt;로 바꿔볼 수 있다(인라인화). 더 나아가서 &lt;code class=&quot;language-text&quot;&gt;id (y + 2)&lt;/code&gt;와 같이 &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;가 표현식에 적용되어있다면 이를 표현식 그 자체인 &lt;code class=&quot;language-text&quot;&gt;(y + 2)&lt;/code&gt;로 바꿀 수도 있다. 또한 이 치환은 양방향으로 적용되기 때문에 표현식 &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;id e&lt;/code&gt;로 치환할 수도 있다.(리팩토링)&lt;/p&gt;
&lt;p&gt;함수가 패턴 매칭에 의해 정의된 경우, 각각의 하위 정의를 독립적으로 사용할 수도 있다. 예를 들어 위의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 정의에서 &lt;code class=&quot;language-text&quot;&gt;fmap f Nothing&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;으로 바꿀 수 있으며, 반대로도 가능하다. 이제 이 개념이 실제로 어떻게 작동하는지를 살펴보자. 먼저 항등 보존을 살펴보겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;라는 두 가지 케이스를 고려해야한다. 먼저 첫 번째 경우를 살펴보겠다. 왼쪽의 항을 오른쪽 항으로 변환하기 위해 Haskell 문법의 Pseudo Code를 사용하겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;가장 마지막 단계에서는 &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;의 정의를 활용하여 표현식 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;id Nothing&lt;/code&gt;으로 대체했다. 실제로는 양 끝에서 촛불을 태우는 방식과 유사하게 이러한 증명을 수행해나가며, 중간에서 동일한 표현식을 만날 때까지 진행하게 된다. 위 케이스에서는 세 번째 라인의 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;이 이에 해당한다.&lt;/p&gt;
&lt;p&gt;두 번째 경우도 어렵지 않다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 항등 보존에 대한 증명이 끝났으니, &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이 합성을 보존한다는 것도 표현해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;의 케이스이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 두 번째 케이스인 &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;에 대해서는 이렇게 표현한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 합성의 결합법칙에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 합성의 결합법칙에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이러한 추론 방식이 조금 어색하게 느껴지는 독자 분들도 계실텐데, 사실 위 예시에 작성된 모든 코드들은 모두 같은 동작을 하는 코드이다.&lt;/p&gt;
&lt;p&gt;방정식 추론이라는 말이 어려워보여서 그렇지 결국은 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;x + 0&lt;/code&gt;이 동형(Isomorphic)임을 밝혀나가는 노가다와 유사하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;addZero&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; identify &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;identify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addZero&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; identify의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;addZero&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; addZero의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   x
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; identify의 정의에 의하면 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;identify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수가 참조 투명성을 보장하는 이상 함수를 함수의 본문으로 치환이 가능하기 때문에 이렇게 노가다로 정합성을 확인해나가는 행위가 가능한 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이와 같은 방정식 추론을 사용할 때는 이 추론 방법이 사이드 이펙트를 가진 C++ 스타일의 함수에 대해서는 동작하지 않는다는 점을 잘 알아야 한다. 아래 코드를 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; c&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;방정식 추론을 사용하면 &lt;code class=&quot;language-text&quot;&gt;square&lt;/code&gt;를 인라인화하여 아래와 같은 정의를 얻을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;double&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이는 확실히 유효한 변환이 아니며 매번 동일한 결과를 생성하지도 않을 것이다. 그럼에도 불구하고 매크로를 통해 &lt;code class=&quot;language-text&quot;&gt;square&lt;/code&gt;를 구현한 경우 C++ 컴파일러는 방정식 추론을 시도할 것이고, 그 결과는 참혹할 것이다.&lt;/p&gt;
&lt;h3 id=&quot;713-optional&quot; style=&quot;position:relative;&quot;&gt;7.1.3 Optional&lt;a href=&quot;#713-optional&quot; aria-label=&quot;713 optional permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;물론 Haskell을 사용하여 펑터를 쉽게 정의할 수 있기는 하지만, 사실 꼭 Haskell이 아니더라도 제네릭 프로그래밍과 고차함수를 지원하는 어떤 언어든 펑터를 정의할 수 있다. C++의 Maybe에 해당하는 템플릿 타입 &lt;code class=&quot;language-text&quot;&gt;optional&lt;/code&gt;을 생각해보자. 아래는 &lt;code class=&quot;language-text&quot;&gt;optional&lt;/code&gt; 구현에 대한 스케치이다. (실제 구현은 인수가 전달될 수 있는 여러가지 방법, Deep Copy/Shallow Copy와 같은 Copy Semantics, C++ 특유의 자원 관리 문제 등 을 고려해야하기 때문에 훨씬 더 복잡하다.)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;optional&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; _isValid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// the tag&lt;/span&gt;
		T _v&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// Nothing&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Just&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _isValid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    T &lt;span class=&quot;token function&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _v&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 템플릿은 타입 &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt;를 새로운 타입 &lt;code class=&quot;language-text&quot;&gt;optional&amp;lt;T&gt;&lt;/code&gt;로 매핑하여 펑터의 정의 중 하나인 타입에 대한 매핑을 제공한다. 이제 함수에 대한 동작을 정의해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
						&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
						&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것은 함수를 인자로 받고 다시 함수를 반환하는 고차함수이다. 커링되지 않는 버전은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이외에 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;optional&lt;/code&gt;의 템플릿 메서드로 만드는 선택지도 있다. 이처럼 다양한 선택지들은 C++에서 펑터 패턴을 추상화하는 난이도를 더 높히는 주범이다. 펑터를 상속할 수 있는 인터페이스로 정의해야할까? 펑터는 커링된 함수인가 아니면 커링되지 않은 프리 템플릿 함수인가? C++ 컴퍼일러는 누락된 타입을 올바르게 추론할 수 있을까, 아니면 우리가 직접 명시적으로 지정해줘야 하는걸까?&lt;/p&gt;
&lt;p&gt;한번 입력 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt;를 받아 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;을 반환한다고 생각해보자. 이 경우에 컴파일러는 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;의 타입을 어떻게 결정할까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; g &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;특히 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 오버로딩하는 여러 가지 펑터가 있는 경우에는 어떻게 될까? (곧 우리는 더 많은 펑터들을 만나게 될 것이다)&lt;/p&gt;
&lt;h3 id=&quot;714-타입-클래스typeclasses&quot; style=&quot;position:relative;&quot;&gt;7.1.4 타입 클래스(Typeclasses)&lt;a href=&quot;#714-%ED%83%80%EC%9E%85-%ED%81%B4%EB%9E%98%EC%8A%A4typeclasses&quot; aria-label=&quot;714 타입 클래스typeclasses permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;그렇다면 Haskell이 펑터를 추상화하는 방법은 무엇일까? 이를 위해서 Haskell은 타입 클래스 매커니즘을 사용한다. 타입 클래스는 공통 인터페이스를 지원하는 타입의 집합을 정의한다. 예를 들어, 동등성을 지원하는 객체들의 클래스는 아래와 같이 정의된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 정의는 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Eq&lt;/code&gt; 클래스의 멤버인 경우, 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 두 인자를 받아 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;을 반환하는 &lt;code class=&quot;language-text&quot;&gt;==&lt;/code&gt; 연산자를 지원한다는 것을 나타낸다.&lt;/p&gt;
&lt;p&gt;만약 Haskell에게 특정 타입이 &lt;code class=&quot;language-text&quot;&gt;Eq&lt;/code&gt; 타입 클래스의 인스턴스라는 것을 알려주고 싶다면, 먼저 이 클래스의 인스턴스로 선언하고 &lt;code class=&quot;language-text&quot;&gt;==&lt;/code&gt;의 구현을 제공해줘야 한다. 예를 들어 두 개의 &lt;code class=&quot;language-text&quot;&gt;Float&lt;/code&gt;로 이루어진 곱 타입인 2D Point 타입의 정의가 주어졌다고 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pt&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 각 점의 동등성을 이렇게 정의해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Pt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Pt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&apos;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서는 두 개의 패턴 &lt;code class=&quot;language-text&quot;&gt;(Pt x y)&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;(Pt x’ y’)&lt;/code&gt;에게 중위 연산자 &lt;code class=&quot;language-text&quot;&gt;==&lt;/code&gt;를 사용해보았다. 함수의 본문은 단일 등호를 보면 이해가 쉽다. 이처럼 &lt;code class=&quot;language-text&quot;&gt;Point&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Eq&lt;/code&gt;의 인스턴스로 선언된다면 이제 직접적으로 연산자를 통해 각 점의 동등성을 비교할 수 있다.&lt;/p&gt;
&lt;p&gt;Haskell에서는 C++이나 Java와는 다르게 &lt;code class=&quot;language-text&quot;&gt;Point&lt;/code&gt;를 정의할 때, 이 타입이 직접 &lt;code class=&quot;language-text&quot;&gt;Eq&lt;/code&gt;클래스의 멤버라는 것을 명시할 필요는 없으며, 이는 추후 사용자가 직접 작성하는 클라이언트 코드에서 작성할 수 있다. 이러한 타입 클래스는 Haskell에서 함수나 연산자를 오버로딩할 수 있는 유일한 방법이다.&lt;/p&gt;
&lt;p&gt;다양한 펑터들에서 fmap의 동작을 오버로딩하여 활용하기 위해서는 이와 같은 타입 클래스 기법이 필요하다. 그러나 한 가지 복잡한 점이 있다. 펑터는 타입으로 정의되는 것이 아니라 타입들의 매핑인 타입 생성자로 정의된다. 즉, 펑터를 제대로 정의하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;Eq&lt;/code&gt;의 경우처럼 타입들의 집합이 아닌 타입 생성자들의 집합으로 정의된 타입 클래스가 필요하다는 것이다. 다행히도 Haskell의 타입 클래스는 타입 뿐만 아니라 타입 생성자 또한 잘 지원해준다. 그럼 이제 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt; 클래스를 한번 정의해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt;인 경우, 지정된 타입 시그니처를 가진 함수 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 가지고 있다는 사실을 명시하고 있다. 여기서 소문자 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;는 타입 변수이며, 타입 변수 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;이 받고 있는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;와 동일한 개념이다.&lt;/p&gt;
&lt;p&gt;컴파일러는 &lt;code class=&quot;language-text&quot;&gt;f a&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;f b&lt;/code&gt;와 같이 이 타입 변수가 다른 타입을 처리하고 있다는 사실을 참고하여 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 타입이 아닌 타입 생성자라는 사실을 추론할 수 있다. 따라서 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt;의 인스턴스를 선언할 때는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;와 같은 타입 생성자를 지정해줘야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 우리가 정의한 &lt;code class=&quot;language-text&quot;&gt;Functor&lt;/code&gt; 클래스, 그리고 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;와 같이 간단한 데이터 타입에 대한 인스턴스 정의들은 이미 표준 Prelude에 포함되어있다.&lt;/p&gt;
&lt;h3 id=&quot;715-c에서의-펑터functor-in-c&quot; style=&quot;position:relative;&quot;&gt;7.1.5 C++에서의 펑터(Functor in C++)&lt;a href=&quot;#715-c%EC%97%90%EC%84%9C%EC%9D%98-%ED%8E%91%ED%84%B0functor-in-c&quot; aria-label=&quot;715 c에서의 펑터functor in c permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;그렇다면 C++에서도 이와 동일한 접근 방식을 시도해볼 수 있을까? 타입 생성자는 &lt;code class=&quot;language-text&quot;&gt;optional&lt;/code&gt;과 같은 템플릿 클래스에 해당하므로, &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 템플릿 템플릿 매개변수 &lt;code class=&quot;language-text&quot;&gt;F&lt;/code&gt;로 매개화해볼 수 있을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; F&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
F&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; F&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 이 템플릿을 다른 펑터들에 대해서 특수화(Specialize)하면 좋을 것 같다. 하지만 슬프게도 C++에서는 템플릿 함수의 부분 특수화를 금지하고 있기 때문에 아래처럼 작성할 수가 없다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;optional&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;대신 우리는 함수 오버로딩을 사용할 것이다. 이렇게 되면 우리는 다시 커링되지 않은 펑터의 원래 정의로 돌아가게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 두 번째 인자가 오버로드를 선택하기 때문에 이 정의 자체가 작동하기는 하지만, 이러한 방법은 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 일반적인 정의에서는 많이 벗어나있다.&lt;/p&gt;
&lt;h3 id=&quot;716-list-펑터&quot; style=&quot;position:relative;&quot;&gt;7.1.6 List 펑터&lt;a href=&quot;#716-list-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;716 list 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;프로그래밍에서 펑터가 어떤 역할을 하는지에 대해 감을 잡기 위해서는 조금 더 많은 예제를 살펴봐야할 것 같다. 다른 타입으로 매개화된 어떤 타입이든 모두 펑터의 후보라고 볼 수 있다. 제네릭 컨테니어는 저장된 요소의 타입에 의해 매개화되므로, 매우 간단한 컨테이너인 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;를 한번 살펴보자.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;제네릭 컨테이너는 여러 타입의 데이터를 저장할 수 있는 데이터 컨테이너이다. 즉, 타입 파라미터를 받음으로써 동일한 구조를 유지하면서도 서로 다른 유형의 데이터를 저장할 수 있는 것이다. TypeScript에서는 &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;T&gt;&lt;/code&gt;와 같은 타입이 일종의 제네릭 컨테이너라고 볼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;라는 타입 생성자가 있다. 이 타입 생성자는 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 타입 &lt;code class=&quot;language-text&quot;&gt;List a&lt;/code&gt;로 매핑한다. 이때 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;가 펑터라는 것을 보이기 위해서는 함수 &lt;code class=&quot;language-text&quot;&gt;a → b&lt;/code&gt;가 주어졌을 때 함수 &lt;code class=&quot;language-text&quot;&gt;List a → List b&lt;/code&gt;로 나아가는 리프팅 함수를 정의해야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;List a&lt;/code&gt;에 작용하는 함수는 두 리스트 생성자인 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt; 두 가지 경우를 고려해야한다. &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;의 경우에는 어차피 빈 리스트에 대해서 할 수 있는게 없으니, 그냥 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;을 반환해주면 되므로 간단하게 처리가 가능하다.&lt;/p&gt;
&lt;p&gt;그러나 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt; 케이스의 경우에는 약간 까다롭다. 왜냐하면 재귀를 포함해야하기 때문이다. 일단 잠시 생각을 멈추고 우리가 정확히 어떤 것을 하려고 하는 것인지 다시 살펴보자. &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 인자로 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 리스트, 그리고 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 변환하는 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;가 주어졌고, 이제 이것들을 가지고 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 리스트를 생성해야한다.&lt;/p&gt;
&lt;p&gt;리스트의 각 요소를 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 변환하는 것은 당연하게도 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 사용하면 된다. 다만 비어있지 않은 리스트는 하나의 원소가 아닌 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt;로 표현되는 헤드(Head)와 나머지 꼬리(Tail)로 구성될텐데, 어떻게 모든 원소에 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 적용해야 하는걸까?&lt;/p&gt;
&lt;p&gt;우리는 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 헤드에 먼저 적용하고, 리프팅한(&lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;한) &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 나머지 꼬리에 적용할 것이다. 이는 리프팅된 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 또 다시 리프팅한 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;로 정의하고 있기 때문에 재귀적인 정의가 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Haksell에 익숙하지 않은 독자들을 위해 조금 더 읽기 쉬운 변수명으로 바꿔보면 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; 원소에적용할&lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; 헤드원소 나머지테일&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;원소에적용할&lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt; 헤드원소&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; 원소에적용할&lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt; 나머지테일&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이를 TypeScript로 다시 작성해보자면 대략 이런 느낌이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-typescript line-numbers&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// List 펑터 인터페이스&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Cons&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; tail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 헤드에 fn를 적용해서 T를 U로 변경&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 이후 꼬리(List)가 가진 fmap을 호출하여 같은 행위를 재귀적으로 반복한다.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Cons&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;head&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tail&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haksell은 &lt;code class=&quot;language-text&quot;&gt;Cons (f x)&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;(fmap f t)&lt;/code&gt;와 같은 패턴매칭을 통해 헤드에 적용할 동작과 꼬리에 적용할 동작을 구분하지만, TypeScript는 그런 패러다임을 가진 언어가 아니기 때문에 직접 &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;를 통해 원하는 동작을 호출하고 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;우항의 &lt;code class=&quot;language-text&quot;&gt;fmap f&lt;/code&gt; 구문은 정의하려는 리스트보다 더 짧은 리스트, 즉, 꼬리에 적용된다. 결국 점점 더 짧은 리스트로 재귀하다가 결국 최종적으로는 빈 리스트인 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;에 도달하게 될 것이다.&lt;/p&gt;
&lt;p&gt;앞서 정의한대로 &lt;code class=&quot;language-text&quot;&gt;fmap f&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;에 적용되면 재귀가 종료된다. 최종 결과를 얻으려면 새로운 헤드 &lt;code class=&quot;language-text&quot;&gt;(f x)&lt;/code&gt;와 새로운 꼬리 &lt;code class=&quot;language-text&quot;&gt;(fmap f t)&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt; 생성자를 통해 결합한다. 지금까지 이야기한 모든 내용을 하나로 합쳐보면 아래와 같이 List 펑터의 인스턴스 선언이 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nil&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 여러분이 C++에 익숙하다면, 일반적인 C++ 컨테이너인 &lt;code class=&quot;language-text&quot;&gt;std::vector&lt;/code&gt;를 한번 생각해보면 된다. &lt;code class=&quot;language-text&quot;&gt;std::vector&lt;/code&gt;에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 구현은 단순히 &lt;code class=&quot;language-text&quot;&gt;std::transform&lt;/code&gt;의 얇은 캡슐화에 불과하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;back_inserter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이를 사용하면 숫자 시퀀스인 원소를 제곱하는 등의 행위가 가능하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
					&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
					&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ostream_iterator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;cout&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;, &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;대부분의 C++ 컨테이너는 &lt;code class=&quot;language-text&quot;&gt;std::transform&lt;/code&gt;에 전달할 수 있는 이터레이터를 구현함으로써 펑터가 되며, 이는 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 원시적인 버전과도 같다. 그러나 안타깝게도 이터레이터와 임시 개체(Temporaries)의 혼란스러움으로 인해 펑터의 단순함이 상당 부분 사라져버린다(위의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 구현을 참조해보자). 하지만 새롭게 제안된 &lt;a href=&quot;https://learn.microsoft.com/ko-kr/cpp/standard-library/ranges?view=msvc-170&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;range&lt;/a&gt; 라이브러리는 특정한 범위 내에서 펑터적인 성질을 더 명확하게 표현해주고 있다.&lt;/p&gt;
&lt;h3 id=&quot;717-reader-펑터&quot; style=&quot;position:relative;&quot;&gt;7.1.7 Reader 펑터&lt;a href=&quot;#717-reader-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;717 reader 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;여기까지 봤다면 이제 펑터가 어떤 컨테이너의 한 종류인 것 같다는 생각을 가지게 되었을 것이라 생각한다. 그렇다면 이제는 그 생각을 깨버리기 위해 지금까지와 매우 다른 것처럼 보이는 예제를 보여주려고 한다. 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 반환하는 함수로 매핑하는 상황을 생각해보자.&lt;/p&gt;
&lt;p&gt;아직 함수 타입에 대한 깊이 있는 이야기를 나누지는 않았지만, 사실 프로그래머라면 함수에 대한 기본적인 이해 정도는 가지고 있다. Haskell에서 함수 타입은 두 개의 타입과 화살표 타입 생성자(&lt;code class=&quot;language-text&quot;&gt;-&gt;&lt;/code&gt;)를 사용하여 구성된다. 이 생성자는 인수 타입, 그리고 결과 타입이라는 두 가지 타입 사이의 중위 표현으로 등장한다. 기본적으로는 &lt;code class=&quot;language-text&quot;&gt;a -&gt; b&lt;/code&gt;의 형태이지만 괄호를 사용하면 전위 표현으로도 사용이 가능하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;정규 함수와 마찬가지로 하나 이상의 인수를 가진 타입 함수는 부분적용이 가능하다. 따라서 아래 예시와 같이 화살표에 하나의 타입 인수만 제공한다면 결과 타입을 의미하는 다른 인수가 들어오는 것을 기다릴 수 있다는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것이 바로 위 표현이 타입 생성자인 이유이다. &lt;code class=&quot;language-text&quot;&gt;a -&gt; b&lt;/code&gt; 를 완전한 타입으로 만들기 위해서는 타입 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;까지 제공되어야 하기 때문이다. 즉, 위 예시는 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 매개변수로 사용하는 타입 생성자 집합을 정의하고 있다고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 이제 이 케이스가 펑터가 맞는지 살펴보도록 하자. 두 개의 타입 매개변수를 다루는 것은 어려울 수 있으니 이름을 조금 변경해보겠다. 이전에 정의했던 펑터의 정의와 일치하도록 인수의 타입을 &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;로, 결과 타입을 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 지정해보겠다.&lt;/p&gt;
&lt;p&gt;즉, 이 타입 생성자는 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;r -&gt; a&lt;/code&gt; 타입으로 매핑하는 녀석이다. 이것이 펑터가 되려면 함수 &lt;code class=&quot;language-text&quot;&gt;a -&gt; b&lt;/code&gt;, 함수 &lt;code class=&quot;language-text&quot;&gt;r -&gt; a&lt;/code&gt;를 인자로 받고 함수 &lt;code class=&quot;language-text&quot;&gt;r -&gt; b&lt;/code&gt;를 반환하는 함수로 리프팅해야 한다. 이들은 각각 타입 생성자(&lt;code class=&quot;language-text&quot;&gt;-&gt;&lt;/code&gt;) &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;이 작용하는 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;를 사용하여 형성된 타입이다.&lt;/p&gt;
&lt;p&gt;이제 이 케이스를 표현할 수 있는 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 정의를 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 함수 &lt;code class=&quot;language-text&quot;&gt;f::a -&gt; b&lt;/code&gt;와 함수 &lt;code class=&quot;language-text&quot;&gt;g::r -&gt; a&lt;/code&gt;가 주어졌을 때 함수 &lt;code class=&quot;language-text&quot;&gt;r -&gt; b&lt;/code&gt;를 생성해야하는 퍼즐을 풀어야 한다. 두 함수를 합성할 수 있는 방법은 오직 하나 뿐이며, 결과 또한 우리가 원하는 방향과 정확히 일치한다. 따라서 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 구현은 아래와 같을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;g::r → a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;f::a → b&lt;/code&gt;가 합성됨으로써 &lt;code class=&quot;language-text&quot;&gt;r → a → b&lt;/code&gt;, 즉 &lt;code class=&quot;language-text&quot;&gt;r → b&lt;/code&gt;가 성립된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;굉장히 간결하지만 우리가 원하는 동작은 정확히 구현되었다. 만약 더 간결한 표기를 선호한다면, 함수 합성에 대한 표현을 전위 표기법으로 바꿔볼 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 인수를 생략해서 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;과 함수 합성을 의미하는 &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; 연산자, 두 함수의 직접적인 동등성을 표현할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 &lt;code class=&quot;language-text&quot;&gt;(-&gt;) r&lt;/code&gt; 타입 생성자와 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 구현의 결합을 Reader 펑터라고 한다.&lt;/p&gt;
&lt;h2 id=&quot;72-컨테이너로써의-펑터&quot; style=&quot;position:relative;&quot;&gt;7.2 컨테이너로써의 펑터&lt;a href=&quot;#72-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A1%9C%EC%8D%A8%EC%9D%98-%ED%8E%91%ED%84%B0&quot; aria-label=&quot;72 컨테이너로써의 펑터 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지 프로그래밍 언어에서 일반적인 용도의 컨테이너를 정의하는 펑터의 몇 가지 예시를 살펴보았다.&lt;/p&gt;
&lt;p&gt;우리는 보통 함수를 일종의 데이터라고 생각하지않기 때문에 Reader 펑터같은 녀석들이 조금 어색해보이기도 한다. 그러나 순수함수는 메모이제이션될 수 있으며 함수의 실행은 일종의 테이블 조회 행위로 변환될 수도 있다. 그리고 테이블은 데이터이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;함수의 실행을 일종의 테이블 조회 행위로 변환할 수 있다는 말은 어떤 함수가 순수하고 불변적이며 입력에 따라 항상 같은 출력을 반환한다는 가정을 전제로 하는 설명이다.&lt;/p&gt;
&lt;p&gt;위와 같은 전제가 지켜진다면 함수의 실행 결과를 테이블에 저장하고 함수의 입력 값을 키로 사용하여 함수의 실행 결과를 “검색”할 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 메모이제이션에 사용되는 자료구조가 꼭 테이블이어야만 하는 것은 아니지만, 작가는 순수한 함수의 이러한 특성으로 인해 순수함수의 실행이 일종의 데이터 조회 행위가 될 수 있다는 사실을 강조하고 있는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;반대로 Haskell의 게으른 평가(지연평가) 때문에 전통적인 컨테이너인 리스트는 함수로 구현될 수도 있다. 예를 들어 자연수의 무한한 리스트는 아래와 같이 간결하게 정의할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;nats&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;nats&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 라인의 대괄호 쌍은 Haskell의 리스트에 대한 내장 타입 생성자이다. 두 번째 라인의 대괄호는 리스트 리터럴을 만드는 데 사용된다.&lt;/p&gt;
&lt;p&gt;당연하겠지만 이런 방식의 무한 리스트는 메모리에 저장할 수 없다. 그래서 필요할 때마다 &lt;code class=&quot;language-text&quot;&gt;Integer&lt;/code&gt;를 생성하는 함수로 이러한 동작을 구현하는 것이다. Haskell은 사실상 데이터와 코드 사이의 구분을 명확하게 하지 않는다. 리스트는 함수로 간주될 수도 있고, 함수는 인수를 결과에 매핑하는 테이블로 간주될 수도 있다. 특히 후자는 함수의 정의역이 유한하고 크기가 크지 않은 경우에는 꽤나 실용적인 개념이다.&lt;/p&gt;
&lt;p&gt;그러나 &lt;code class=&quot;language-text&quot;&gt;strlen&lt;/code&gt;을 테이블 조회로 구현하는 것은 현실적이지 않다. 왜냐하면 무한히 많은 서로 다른 문자열들이 존재하기 때문이다. 프로그래머로써 우리는 무한을 좋아하지 않겠지만, 카테고리 이론에서는 무한을 아침식사처럼 즐기는 방법을 배워볼 수 있다. 모든 문자열의 집합이나 우주의 과거, 현재, 미래의 상태 같이 무한한 것들도 다뤄볼 수 있다는 말이다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 펑터 객체(엔도펑터에 의해 생성된 타입의 객체)를 어떤 타입을 가진 값 또는 값들을 추상적으로 가지고 있는 무언가로 생각하는 것을 추천한다. 물리적으로 그 값을 가지고 있지는 않지만 말이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;여기서 작가가 펑터가 특정 타입의 값을 직접 가지고 있는 것이 아니라 추상적으로 가지고 있다고 표현하는 의미는 다음과 같다. TypeScript의 Array를 예로 들어보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numbers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 숫자 타입의 배열&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; doubledNumbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [2, 4, 6]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;number[]&lt;/code&gt; 타입의 배열은 사실 “모든 숫자를 가진 배열”으로 정의되었다고 봐야 한다. 하지만 현재 이 배열이 실제로 모든 숫자를 가지고 있는 것은 아니며, 단지 &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;과 같은 메소드를 사용하여 배열 내부의 값들을 간접적으로 다룰 수 있는 방법만을 제공하고 있다.&lt;/p&gt;
&lt;p&gt;이러한 방법들을 통해 이 배열은 이론상 모든 숫자를 가질 수 있겠지만, 실제로 이 배열이 모든 숫자를 가지고 있는 것은 아니기에 “추상적으로 가지고 있다”라는 표현을 사용한 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C++에서의 예시를 보자면 &lt;code class=&quot;language-text&quot;&gt;std::future&lt;/code&gt;가 있다. 언젠가는 값을 가지게 될테지만 반드시 그렇다는 보장은 없으며, Future 내부의 값에 접근하려면 다른 스레드의 실행이 완료될 때까지 기다려야할 수도 있다.&lt;/p&gt;
&lt;p&gt;또 다른 예시로는 Haskell의 &lt;code class=&quot;language-text&quot;&gt;IO&lt;/code&gt; 객체가 있다. 이 객체는 사용자의 입력을 받거나 “Hello World!”가 모니터에 표시된 우주의 상태를 포함할 수도 있다.&lt;/p&gt;
&lt;p&gt;이러한 해석들에 따르면 펑터 객체는 매개변수화된 타입의 값을 포함하거나 그런 값을 생성하는 방법을 포함하고 있는 무언가로 바라볼 수 있다. 펑터 내부의 값에 접근하는 동작은 완전히 선택사항이며 펑터의 범위에 꼭 포함되어야 하는 동작도 아니다. 우리가 관심을 가져야하는 부분은 함수를 사용해서 그 값을 조작할 수 있다는 것 뿐이다.&lt;/p&gt;
&lt;p&gt;만약 그 값에 접근할 수 있다면 그 조작에 대한 결과를 볼 수 있어야 한다. 그러나 접근할 수 없다면 우리가 오직 신경써야하는 것은 그 조작들이 올바르게 합성되었는지, 그리고 항등 함수를 통한 조작은 아무것도 바꾸지 않는다는 사실 뿐이다. 펑터 객체 내부의 값에 접근하는 것이 그렇게 중요한 일이 아니라는 것을 보여주기 위해 한 가지 예시를 보여주겠다. 여기 인자 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 완전히 무시하는 타입 생성자가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 타입 생성자는 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 두 개의 타입을 받는다. 화살표 생성자 때와 마찬가지로 이를 부분적으로 적용해서 펑터를 만들어볼 것이다. &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt;라고 하는 데이터 생성자는 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt; 타입의 값 하나만을 취하며, 이는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대한 의존성이 없다는 것을 의미한다. 이 타입 생성자에 대한 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 타입 정의는 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;펑터가 타입 인수를 무시하고 있기 때문에, &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;의 구현에서도 함수 인수를 무시할 수 있다. 함수에 적용할 대상 자체가 없기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;오히려 이런 부분은 컴파일 시간에 발생하는 타입 인자와 런타임에 발생하는 값 사이의 더 강한 구분이 있는 C++에서 더 명확하게 나타날 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;Const&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;C v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		C _v&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C++으로 구현된 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt; 또한 함수의 인자를 무시하고 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 인자를 본래 값과 함께 다시 캐스팅하는 역할을 수행한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Const&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Const&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Const&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_v&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;당장 이해하기는 어려울 수 있지만 사실 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터는 많은 구조들에서 굉장히 중요한 역할을 담당한다. 카테고리 이론에서 &lt;code class=&quot;language-text&quot;&gt;Const&lt;/code&gt; 펑터는 앞서 언급했던 블랙홀의 엔도펑터, 즉, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Δ&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\Delta c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;Δ&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 펑터의 특수한 경우이다. 추후 이러한 개념에 대해서도 더 자세히 다뤄보도록 하겠다.&lt;/p&gt;
&lt;h2 id=&quot;73-펑터-합성functor-composition&quot; style=&quot;position:relative;&quot;&gt;7.3 펑터 합성(Functor Composition)&lt;a href=&quot;#73-%ED%8E%91%ED%84%B0-%ED%95%A9%EC%84%B1functor-composition&quot; aria-label=&quot;73 펑터 합성functor composition permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;펑터가 마치 함수와 같이 합성될 수 있다라는 것은 꽤 직관적인 이해가 가능한 사실이다. 결국 두 펑터의 합성이라는 것은 펑터가 특정 카테고리 내의 객체나 사상에 매핑되는 행위들의 합성이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;합성된 두 개의 펑터를 거치더라도 항등 사상은 그대로 항등 사상으로 남게 되며, 사상들의 합성 규칙은 여전히 동일한 규칙을 가지게 된다. 이는 굉장히 단순하고 간단한 규칙이며, 특히 엔도펑터를 합성하는 것은 더더욱 쉽다. 혹시 &lt;code class=&quot;language-text&quot;&gt;maybeTail&lt;/code&gt; 함수를 기억하는가?&lt;/p&gt;
&lt;p&gt;이 함수를 Haskell의 내장 리스트 구현을 사용해서 다시 작성해보겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;maybeTail&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;maybeTail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;maybeTail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;지금까지 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;로 호출하던 빈 리스트 생성자는 빈 대괄호 쌍인 &lt;code class=&quot;language-text&quot;&gt;[]&lt;/code&gt;으로 대체되었고, &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt; 생성자는 중위 연산자 &lt;code class=&quot;language-text&quot;&gt;:&lt;/code&gt;으로 대체되었다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;maybeTail&lt;/code&gt;의 결과는 두 펑터 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;[]&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 작용하는 형태를 지니고 있다. 만약 여기서 합성된 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 리스트의 원소에 어떤 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;를 적용하려고 한다면 어떻게 접근해야할까?&lt;/p&gt;
&lt;p&gt;함수가 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 리스트의 원소에 도달하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;[]&lt;/code&gt;라는 두 겹의 펑터를 뚫어야 한다. 가장 먼저 외부의 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;를 뚫기 위해 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;을 사용할 수 있다. 그러나 함수 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;는 리스트에 대해서는 작동하지 않기 때문에 이대로 이 함수를 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt;의 안쪽으로 보낼 수는 없다. 우리는 내부 리스트에서 작동할 &lt;code class=&quot;language-text&quot;&gt;(fmap f)&lt;/code&gt;를 보내야 한다. 한번 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 리스트의 정수 원소들을 제곱하는 예시를 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;square&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;mis&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;mis&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;mis2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;mis&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;먼저 컴파일러는 타입을 분석한 후, 외부의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;에 대해서는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 인스턴스의 구현을 사용하고, 내부의 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;에 대해서는 리스트 펑터의 구현을 사용해야한다는 것을 추론해낼 것이다. 물론 지금 시점에서 위 코드가 아래와 같은 코드로 다시 작성될 수 있다는 사실이 바로 이해가 되지는 않을 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;mis2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;square&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;mis&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;은 하나의 인수에 대한 함수로 간주될 수 있다는 것을 기억해야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 경우 &lt;code class=&quot;language-text&quot;&gt;(fmap . fmap)&lt;/code&gt;안의 두 번째 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;은 다음과 같은 타입의 인수를 취한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;square&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 다음과 같은 타입의 함수를 반환할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이후 첫 번째 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;은 이 함수를 취하고 다음과 같은 타입의 함수를 반환한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 비로소 이 함수가 &lt;code class=&quot;language-text&quot;&gt;mis&lt;/code&gt;에 적용된다. 따라서 두 펑터의 합성은 해당 &lt;code class=&quot;language-text&quot;&gt;fmap&lt;/code&gt;들의 합성인 펑터라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;다시 카테고리 이론으로 돌아가보자. 대상들의 매핑이 결합법칙을 만족하며, 사상들의 매핑도 결합법칙을 만족하니 펑터의 합성 또한 결합법칙을 만족한다는 사실은 명확하다. 그리고 모든 카테고리에는 당연히 항등 펑터 또한 존재한다. 항등 펑터는 모든 대상과 사상이 자기자신에게 매핑되는 펑터이다.&lt;/p&gt;
&lt;p&gt;즉, 펑터는 마치 어떠한 카테고리의 사상들과 동일한 특성을 가지게 된다. 그렇다면 그 카테고리란 무엇일까?&lt;/p&gt;
&lt;p&gt;바로 대상이 카테고리이고, 사상이 펑터인 카테고리이다. 즉, 카테고리들의 카테고리라고 할 수 있다. 그러나 모든 카테고리들의 카테고리 또한 카테고리이니, 자기 자신을 자기 자신 안에 포함해야하는 모순에 빠지게 된다.&lt;/p&gt;
&lt;p&gt;모든 “작은” 카테고리의 카테고리인 &lt;strong&gt;Cat&lt;/strong&gt;이라는 개념이 있다. 작은 카테고리는 대상들이 집합을 형성하는 카테고리를 가리키며, 심지어 무한하여 셀 수 없는 집합도 “작은” 카테고리로 간주된다. 필자는 이런 개념들이 다양한 추상화 수준에서 동일한 구조가 반복되는 것을 표현할 수 있다는 것에 매우 놀라웠다. 심지어 나중에는 펑터들이 카테고리를 형성하는 케이스도 보게 될 것이다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 6. 단순한 대수적 타입]]></title><description><![CDATA[앞서 우리는 곱과 합이라는 두 가지 기본적인 방법을 통해 타입을 결합하는 것을 보았다. 사실 우리가 일상적인 프로그래밍에서 자주 접하는 데이터 구조는 이 두 가지 메커니즘만으로도 충분히 표현할 수 있다.]]></description><link>https://evan-moon.github.io/2024/03/05/category-theory-for-programmers-6-simple-algebraic-data-types/</link><guid isPermaLink="false">20240305-category-theory-for-programmers-6-simple-algebraic-data-types</guid><pubDate>Tue, 05 Mar 2024 01:35:40 GMT</pubDate><content:encoded>&lt;p&gt;앞서 우리는 곱과 합이라는 두 가지 기본적인 방법을 통해 타입을 결합하는 것을 보았다. 사실 우리가 일상적인 프로그래밍에서 자주 접하는 데이터 구조는 이 두 가지 메커니즘만으로도 충분히 표현할 수 있다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;이처럼 데이터 구조의 많은 속성들을 합성할 수 있다는 사실은 굉장히 중요한 포인트이다. 예를 들어 동등성을 사용하여 기본적인 타입의 값들을 비교하는 방법과 이러한 비교 행위를 곱과 합 타입으로 일반화하는 방법을 알고 있다면, 우리는 자연스럽게 합성 타입에 대한 동등 연산자라는 개념을 유도할 수 있다. Haskell에서는 이렇게 합성된 타입의 하위 집합에 대해 동등성, 비교, 문자열로의 변환과 같은 연산들을 유도할 수 있다.&lt;/p&gt;
&lt;p&gt;그럼 프로그래밍에서 곱 및 합 타입이 나타나는 방식에 대해서 자세히 살펴보도록 하자.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 409px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fcf5139ae1c84cc62f66e0f43c59f1ba/e9a96/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.12499999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB0lsLLOMUf//EABoQAAMBAAMAAAAAAAAAAAAAAAECAwAREjH/2gAIAQEAAQUCejKwsRlPKvLuXiG3m//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAICAwAAAAAAAAAAAAAAAAABEBEhMVH/2gAIAQEABj8C3ZmmJss5H//EABoQAQEBAAMBAAAAAAAAAAAAAAERACExUaH/2gAIAQEAAT8hgQCyB8wZdekzQFfMVTOMmJ1OJ7gBAgb/2gAMAwEAAgADAAAAENgP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EKF//8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EIV//8QAHhABAQACAQUBAAAAAAAAAAAAAREAITFBUWGBkfD/2gAIAQEAAT8QcsEhUefb9rIZxuzvshgYALvT7myGQQ63nGIptMi1fOqYZMCAEDP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/fcf5139ae1c84cc62f66e0f43c59f1ba/e9a96/1.jpg&quot; srcset=&quot;/static/fcf5139ae1c84cc62f66e0f43c59f1ba/0913d/1.jpg 160w,
/static/fcf5139ae1c84cc62f66e0f43c59f1ba/cb69c/1.jpg 320w,
/static/fcf5139ae1c84cc62f66e0f43c59f1ba/e9a96/1.jpg 409w&quot; sizes=&quot;(max-width: 409px) 100vw, 409px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2 id=&quot;61-곱-타입product-types&quot; style=&quot;position:relative;&quot;&gt;6.1 곱 타입(Product Types)&lt;a href=&quot;#61-%EA%B3%B1-%ED%83%80%EC%9E%85product-types&quot; aria-label=&quot;61 곱 타입product types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;프로그래밍 언어에서 두 타입의 곱의 대표적인 구현은 바로 쌍(Pair)이다. Haskell에서는 쌍이 원시 타입 생성자이며, C++에서는 표준 라이브러리에서 정의된 템플릿이다.&lt;/p&gt;
&lt;p&gt;엄밀히 말해 쌍은 교환 법칙을 따르지 않는다. 어떠한 쌍 &lt;code class=&quot;language-text&quot;&gt;(Int, Bool)&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;(Bool, Int)&lt;/code&gt;으로 대체될 수 없다는 것이다. 하지만 이 두 타입은 동형성(Isomorphism)을 지니고 있다. 이 동형성은 Swap 함수에 의해 제공되며, Swap 함수는 아래와 같이 정의할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 두 쌍은 동일한 데이터를 저장하지만 단순히 다른 형식을 사용하고 있는 것이라고 생각할 수 있다. 이는 마치 빅 엔디안(Big Endian) vs 리틀 엔디안(Little Endian)의 관계와도 비슷하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;엔디안(Endian)은 컴퓨터 메모리에 데이터를 저장하는 방식을 의미한다. 빅 엔디안(Big Endian)은 가장 상위 바이트(Most Significant Byte, MSB)를 가장 낮은 주소에 저장하고, 반대로 리틀 엔디안은 MSB를 가장 높은 주소에 저장한다. 즉, 같은 데이터를 다루더라도 저장하는 방식만 다르다는 것이다.&lt;/p&gt;
&lt;p&gt;이는 &lt;code class=&quot;language-text&quot;&gt;(Int, Bool)&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;(Bool, Int)&lt;/code&gt; 쌍처럼 같은 타입들의 곱이지만 각 구성 요소의 위치만 다른 상황과도 유사하기에 작가는 이러한 예시를 든 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;만약 임의의 개수인 타입들을 곱으로 결합하려면 그저 쌍을 중첩시키는 것만으로도 표현할 수 있지만 더 쉬운 방법도 있다. 이렇게 중첩된 쌍은 튜플과 동일한데, 이는 쌍을 중첩하는 다양한 방법들이 동형(Isomorphic)이기 때문이다. 세가지 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;를 순서대로 곱으로 결합하려면 아래와 같은 두 가지 방법을 사용해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 또는&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 타입들은 분명히 다른 타입이다. &lt;code class=&quot;language-text&quot;&gt;((a, b), c)&lt;/code&gt; 타입을 받을 수 있는 함수에 &lt;code class=&quot;language-text&quot;&gt;(a, (b, c))&lt;/code&gt; 타입을 전달할 수 없다는 것을 생각해보면 된다. 하지만 이 타입들이 가진 각각의 요소들은 분명 일대일 대응 관계에 놓여있다.&lt;/p&gt;
&lt;p&gt;여기 이 두 타입을 서로 매핑해주는 함수가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 이 함수에는 역함수 또한 존재한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;alpha_inv&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;alpha_inv&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 이 매핑 함수는 동형사상(Isomorphism)이며, 이 과정에서 이 타입들이 결국 동일한 데이터를 여러 방법으로 패키징하고 있을 뿐이라는 사실을 알 수 있다.&lt;/p&gt;
&lt;p&gt;이렇게 생성된 곱 타입을 타입에 대한 이항 연산이라고 생각해볼 수도 있다. 이 관점에서 바라보면 위에서 알아본 동형사상은 모노이드(Monoid)에서 본 결합 법칙과 매우 유사한 형태를 띄고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 모노이드의 경우 이 두 가지 방법이 완전히 동일하다고 말할 수 있겠지만, 곱 타입의 경우 완전히 동일하다는 의미가 아닌 동형사상에 따라 동일하다고 말할 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;(a * b) * c&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;a * (b * c)&lt;/code&gt;를 모노이드인 곱 연산의 관점에서 바라본다면, 이 연산은 교환법칙을 만족하기 때문에 완벽히 동일(Equal)하다고 이야기할 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 곱 타입의 경우 각 튜플 안에 있는 요소들이 서로 정보의 손실 없이 매핑될 수 있는 일대일 대응함수가 존재하는 동형(Isomorphic)일 뿐이다.&lt;/p&gt;
&lt;p&gt;즉, 두 곱 타입이 동형사상을 통해 서로 매핑이 가능하므로 “동형성에 의해 같다”고 말할 수는 있겠지만 엄밀한 의미에서 동일하지는 않다는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;만약 우리가 동형사상을 수용할 수 있고 엄격한 동일성을 요구하지 않는다면, 유닛 타입인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;이 곱셈의 항등원인 1과 같이  작동한다는 것을 보일 수도 있다. 실제로 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;인 값과 Unit을 쌍으로 묶는 것은 어떠한 정보도 추가하지 않는다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 이 타입은 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 동형(Isomorphic)이다. 아래와 같이 동형사상을 정의할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;rho&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;rho&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;rho_inv&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;rho_inv&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 분석을 통해 집합의 카테고리가 모노이드 카테고리(Monoidal Category)라는 것을 형식적으로 설명할 수 있다. 결국 집합의 카테고리는 각 대상을 데카르트 곱(Cartesian Product)의 형태로 곱할 수 있는 카테고리라는 것이다. 이에 대한 자세한 정의는 추후 다시 논의해보도록 하자.&lt;/p&gt;
&lt;p&gt;Haskell에서는 곱 타입을 더 일반적인 방식으로 정의할 수 있는 방법을 제공하고 있다. 나중에 다시 보겠지만 이런 방법은 특히 곱 타입이 합 타입과 합쳐질 때 빛을 발하게 된다. 이 방법은 여러 개의 인자를 받는 생성자로 표현되는데, 쌍의 경우는 아래와 같이 정의될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;Pair a b&lt;/code&gt;는 매개변수화된 두 개의 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;, 그리고 데이터 생성자인 &lt;code class=&quot;language-text&quot;&gt;P&lt;/code&gt;를 의미한다. 우리는 &lt;code class=&quot;language-text&quot;&gt;Pair&lt;/code&gt; 타입 생성자에 두 개의 타입을 전달함으로써 간단하게 쌍이라는 타입을 생성할 수 있다. 그리고 &lt;code class=&quot;language-text&quot;&gt;P&lt;/code&gt;에는 정의해둔 타입에 맞는 두 값을 전달하여 쌍 타입의 값을 생성할 수 있다.&lt;/p&gt;
&lt;p&gt;한번 &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;의 쌍으로 값을 정의해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;stmt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;stmt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;This statements is&quot;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 줄은 타입 선언부이다. 여기서 &lt;code class=&quot;language-text&quot;&gt;Pair&lt;/code&gt; 타입 생성자를 사용하며, 일반화했었던 &lt;code class=&quot;language-text&quot;&gt;Pair&lt;/code&gt; 정의의 매개변수인 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 대신에 &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;을 직접 넘겨준다. 두 번째 줄은 데이터 생성자 &lt;code class=&quot;language-text&quot;&gt;P&lt;/code&gt;를 사용하여 구체적인 문자열과 부울값을 전달하여 실제 값을 정의하고 있다. 타입 생성자는 타입을 생성할 때 사용되고, 데이터 생성자는 해당 타입을 가진 값을 생성할 때 사용되는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;완전히 동일하지는 않지만, 위 Haskell 코드를 TypeScript로 표현해보자면 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 데이터 생성자&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 타입 생성자&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ReturnType&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stmt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This statements is&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Haskell에서는 타입 생성자와 데이터 생성자의 네임스페이스가 분리되어있기 때문에 아래와 같이 동일한 이름도 종종 사용되고는 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;더 깊게 들여다보면 &lt;code class=&quot;language-text&quot;&gt;Pair&lt;/code&gt;를 이항 연산자인 &lt;code class=&quot;language-text&quot;&gt;(,)&lt;/code&gt;으로 대체하고 있는 것 또한 결국은 빌트인 쌍(Pair) 타입의 선언을 변형한 것이라고 볼 수 있다. 실제로 &lt;code class=&quot;language-text&quot;&gt;(,)&lt;/code&gt;을 전위 연산자로 표현하여 타입 생성자처럼 사용할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;stmt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;This statement is&quot;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이와 유사하게 &lt;code class=&quot;language-text&quot;&gt;(,,)&lt;/code&gt;을 사용하면 트리플(원소가 3개인 튜플)을 생성할 수 있으며, 같은 방법으로 계속 해서 튜플을 확장해나갈 수도 있다. 또한 일반적인 쌍이나 튜플 대신 원하는 곱 타입을 정의할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Stmt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Stmt&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 타입은 단순히 &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;의 곱이지만 이 타입은 자체적인 이름과 생성자를 가지고 있다. 이러한 선언 방법의 장점은 동일한 내용을 가지지만 의미와 기능이 다른 타입을 다양하게 정의할 수 있다는 것이다. 또한 이렇게 선언된 각 타입들은 서로 대체될 수 없다.&lt;/p&gt;
&lt;p&gt;이처럼 튜플과 다중 인자 생성자를 사용하는 생성자는 각 구성 요소가 무엇을 나타내고 있는지 추적하기 어렵기 떄문에 종종 혼란스러운 표현이 되기 쉽고 오류가 발생하기도 쉽다. 그래서 때로는 각 구성 요소에 이름을 지정해주는 것이 나을 수도 있다. 이처럼 이름이 지정된 필드를 가진 곱 타입을 Haskell에서는 &lt;code class=&quot;language-text&quot;&gt;record&lt;/code&gt;라고 하며, C에서는 &lt;code class=&quot;language-text&quot;&gt;struct&lt;/code&gt;라고 한다.&lt;/p&gt;
&lt;h2 id=&quot;62-레코드records&quot; style=&quot;position:relative;&quot;&gt;6.2 레코드(Records)&lt;a href=&quot;#62-%EB%A0%88%EC%BD%94%EB%93%9Crecords&quot; aria-label=&quot;62 레코드records permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;본격적인 설명에 앞서 간단한 예시를 먼저 살펴보도록 하자. 우리는 화학 원소들을 설명하기 위해 원소의 이름과 원소 기호로 이루어진 두 개의 문자열과 원자 번호를 표현하는 하나의 정수가 결합된 데이터 구조를 만드려고 한다. 먼저 &lt;code class=&quot;language-text&quot;&gt;(String, String, Int)&lt;/code&gt;와 같이 튜플을 사용하여 각 구성 요소를 표현해볼 수 있다. 그 다음 원소 기호가 원소 이름의 접두사가 맞는지 확인하는 함수로 패턴 매칭하여 구성 요소들을 추출할 것이다. 아래는 &lt;code class=&quot;language-text&quot;&gt;He&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;Helium&lt;/code&gt;의 접두사인지 확인하는 함수이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;startsWithSymbol&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;startsWithSymbol&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isPrefixOf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 이 코드는 에러가 발생할 가능성이 있고 유지 보수하기도 쉽지 않은 코드이다. 이런 경우에는 레코드를 정의하는 것이 훨씬 더 낫다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
                       &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
                       &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;atomicNumber&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 표현과 튜플을 사용한 표현은 동형(Isomorphic)이다.이는 서로 역함수의 관계를 가지는 두 개의 변환 함수를 통해 확인할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;tupleToElem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;tupleToElem&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;atomicNumber&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;elemToTuple&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;elemToTuple&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;atomicNumber&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 레코드 필드의 이름은 필드에 액세스하기 위한 함수로도 작동한다는 사실에 주목하도록 하자. 예를 들어 &lt;code class=&quot;language-text&quot;&gt;atomicNumber e&lt;/code&gt;라는 표현은 &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;atomicNumber&lt;/code&gt;필드를 검색한다. 이처럼 &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt;라는 레코드의 필드에 액세스하는 &lt;code class=&quot;language-text&quot;&gt;atomicNumber&lt;/code&gt; 함수의 타입은 다음과 같이 표현된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;atomicNumber&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Element&lt;/code&gt;의 레코드 문법을 사용하면 이제 &lt;code class=&quot;language-text&quot;&gt;startWithSymbol&lt;/code&gt; 함수도 더 읽기 쉬운 형태로 다시 표현해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;startsWithSymbol&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;startsWithSymbol&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isPrefixOf&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;심지어 Haskell이 제공하는 트릭을 사용하여 함수인 &lt;code class=&quot;language-text&quot;&gt;isPrefixOf&lt;/code&gt;를 중위 연산자로 표현하여 거의 하나의 자연어 문장처럼 읽히도록 만들어 볼 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;startsWithSymbol&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;`isPrefixOf`&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;63-합-타입sum-types&quot; style=&quot;position:relative;&quot;&gt;6.3 합 타입(Sum Types)&lt;a href=&quot;#63-%ED%95%A9-%ED%83%80%EC%9E%85sum-types&quot; aria-label=&quot;63 합 타입sum types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;집합의 카테고리의 곱 연산에서 곱 타입을 유도할 수 있듯이, 합 연산에서 합 타입을 유도해볼 수도 있다. Haskell에서 합 타입을 표현하는 전형적인 방법은 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;쌍과 마찬가지로 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;도 두 연산 대상이 동형성(Isomorphic)인 경우에 한해 교환 법칙을 만족하고 중첩도 가능하다. 또한 두 대상이 동형이라는 전제 하에 중첩 순서 또한 중요하지 않다. 그런 이유로 다음과 같이 세 개의 구성 요소를 가진 합 타입을 정의해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OneOfThree&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sinistral&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Medial&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Dextral&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 집합의 카테고리가 합을 기준으로 대칭적인 모노이드 카테고리라는 것이 밝혀졌다. 여기서 이항 연산의 역할은 서로소 합에 의해 수행되며 단위 원소의 역할은 초기 대상에 의해 수행된다.&lt;/p&gt;
&lt;p&gt;타입 관점에서 바라보면 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;는 모노이드 연산자, 그리고 Uninhabited(아무런 값도 가질 수 없는) 타입인 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;는 이 연산에 대한 항등원으로 볼 수 있다. &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;를 덧셈으로, &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;를 0이라고 생각해보자. 실제로 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;를 합 타입에 추가하더라도 해당 타입의 내용은 변하지 않는다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 정의는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 동형(Isomorphic)이다. 그 이유는 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;는 아무런 값도 가질 수 없는 타입이기 때문에 이 합 타입에서 &lt;code class=&quot;language-text&quot;&gt;Right&lt;/code&gt; 생성자 부분을 채워넣을 방법이 없기 때문이다. &lt;code class=&quot;language-text&quot;&gt;Either a Void&lt;/code&gt; 타입을 가질 수 있는 유일한 값은 &lt;code class=&quot;language-text&quot;&gt;Left&lt;/code&gt; 생성자를 사용하여 생성되기 때문에 결과적으로는 그저 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 값을 캡슐화하는 역할만 하게 될 것이다. 따라서 형식적으로 &lt;code class=&quot;language-text&quot;&gt;a + 0 = a&lt;/code&gt;와 같은 관점이 성립한다.&lt;/p&gt;
&lt;p&gt;이처럼 Haskell에서는 합 타입이라는 개념이 일상적으로 사용되지만, C++의 합 타입이라고 할 수 있는 &lt;code class=&quot;language-text&quot;&gt;union&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;variants&lt;/code&gt;은 Haskell처럼 일상적으로 사용되지는 않는다.&lt;/p&gt;
&lt;p&gt;이에는 여러 이유가 있다. 일단 C++에서 간단한 합 타입은 굳이 &lt;code class=&quot;language-text&quot;&gt;union&lt;/code&gt;을 사용하지 않더라도 &lt;code class=&quot;language-text&quot;&gt;enum&lt;/code&gt; 키워드를 사용하여 선언하는 열거형(Enumerations)으로 표현할 수 있다.&lt;/p&gt;
&lt;p&gt;Haskell에서 합 타입을 표현하는 방법을 다시 살펴보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 합 타입을 C++에서 다시 표현해보면 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Red&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Green&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Blue &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;마찬가지로 Haskell에서는 간단한 합 타입 중 하나인 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;을 아래와 같이 합 타입임을 명시하여 표현된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 C++에서 이러한 합 타입은 그저 원시 자료형인 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;일 뿐이다.&lt;/p&gt;
&lt;p&gt;C++에서 값의 존재나 부재를 인코딩하는 간단한 합 타입은 여러가지 트릭과 빈 문자열, 음수, Null 포인터와 같이 “불가능한” 값들을 사용하여 다양하게 구현되고 있다. 이렇게 선택적으로 값이 존재할 수 있는 경우 Haskell에서는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 타입을 사용하여 표현한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 타입은 두 타입의 합 타입으로 구성되어있다. Maybe 타입을 구성하는 두 생성자를 각각의 개별적인 타입으로 분리하면 아래와 같이 보일 것이다. 먼저 첫 번째 생성자를 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NothingType&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 타입은 값이 단 하나뿐인 열거형(Enumeration)이며, &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;이라는 하나의 값만 가지고 있다. 다시 말해 이 타입은 싱글톤, 즉 단일 원소 집합이며 이는 유닛 타입인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;와 동등하다.&lt;/p&gt;
&lt;p&gt;이제 두 번째 생성자도 한번 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JustType&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 위 타입은 그저 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 캡슐화한 것에 불과하다. 결과적으로 우리는 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 타입을 다음과 같이 표현할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C++에서 이보다 더 복잡한 합 타입을 표현하고 싶을 때는 포인터를 사용하여 일종의 모방을 한다. 포인터는 &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;이거나 특정 타입인 값을 가리킬 수 있다. 예를 들어 Haskell의 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 타입은 재귀적인 합 타입으로 정의될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C++에서 이 표현을 모방하려면 Null 포인터 트릭을 사용하여 빈 리스트를 구현하는 방법으로 시도해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Node&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; _head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Nil&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// Cons&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;두 개의 Haskell 생성자인 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt;는 오버로딩된 두 개의 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 생성자로 번역된다. &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 클래스는 합 타입의 두 구성 요소를 구별하는데 별도의 태그가 필요하지는 않지만, 리스트의 헤드를 의미하는 &lt;code class=&quot;language-text&quot;&gt;_head&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;nullptr&lt;/code&gt;로 초기화함으로써 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt; 생성자를 표현하고 있다.&lt;/p&gt;
&lt;p&gt;Haskell과 C++ 타입 간의 주요한 차이는 Haskell의 데이터 구조가 불변(Immutable)하다는 점에서 발생한다. 특정한 생성자를 사용하여 객체를 생성하면 해당 객체는 자신을 생성할 때 어떤 생성자가 사용되었는지, 그리고 어떤 인수가 전달되었는지 영원히 기억하고 있다. 따라서 &lt;code class=&quot;language-text&quot;&gt;Just &quot;energy&quot;&lt;/code&gt;로 생성된 &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; 객체는 절대 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;으로 변하지 않는다는 것이다. 마찬가지로 빈 리스트는 영원히 빈 상태로 유지되며, 세 개의 원소를 가진 리스트는 영원히 동일한 세 개의 원소를 가진다.&lt;/p&gt;
&lt;p&gt;이러한 불변성은 구성 자체를 뒤집을 수 있도록 만들어주기도 한다. 주어진 객체를 항상 해당 구성에 사용된 부분으로 분해할 수 있다는 뜻이다. 이러한 분해에는 패턴 매칭이 사용되며 주어진 생성자를 패턴으로 다시 사용한다. 생성자에 인자가 주어진 경우 해당 인자는 변수로 대체된다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt; 데이터 타입은 두 개의 생성자를 가지고 있기 때문에 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;를 해체할 때는 해당 생성자들에 각각 대응하는 두 가지 패턴을 사용해야 한다. 하나는 빈 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt; 리스트와 매칭될 것이고 다른 하나는 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt;로 생성된 리스트와 매칭될 것이다. 아래는 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;에 대한 간단한 함수의 정의들이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;maybeTail&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;maybeTail&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;maybeTail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;maybeTail&lt;/code&gt;의 정의의 첫 번째 부분은 &lt;code class=&quot;language-text&quot;&gt;Nil&lt;/code&gt; 생성자를 패턴으로 사용하여 &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;을 반환하고 있다. 두 번째 부분은 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt; 생성자를 패턴으로 사용하고 있는데, 생성자에게 주어진 첫 번째 인자는 필요없기 때문에 와일드 카드인 &lt;code class=&quot;language-text&quot;&gt;_&lt;/code&gt;로 대체하고 있다. 생성자에게 주어진 두 번째 인자는 변수 &lt;code class=&quot;language-text&quot;&gt;t&lt;/code&gt;에 바인딩되며 최종 반환 값은 &lt;code class=&quot;language-text&quot;&gt;Just t&lt;/code&gt;이다. 이제 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;가 어떻게 생성되었느냐에 따라 두 정의 중 하나와 패턴 매칭이 될 것이다. 만약 &lt;code class=&quot;language-text&quot;&gt;Cons&lt;/code&gt;를 사용하여 생성되었다면 생성자에 전달된 두 인자 중 두 번째인자가 검색될 것이고 이후 &lt;code class=&quot;language-text&quot;&gt;Just t&lt;/code&gt;의 형태로 반환될 것이다.&lt;/p&gt;
&lt;p&gt;C++에서 이보다 더 복잡한 합 타입은 다형적인 클래스 계층을 사용하여 구현한다. 공통 조상을 가진 클래스 패밀리는 숨겨진 태그로 이해될 수 있으며, Haskell에서 생성자에 대한 패턴 매칭을 통해 수행되는 작업은 C++의 vtable 포인터를 기반으로 가상 함수 호출을 디스패치함으로써 수행된다.&lt;/p&gt;
&lt;p&gt;사실 C++에서는 합 타입을 온전하게 구현하기 어려운 여러가지 제약 때문에 &lt;code class=&quot;language-text&quot;&gt;union&lt;/code&gt;이 많이 사용되지는 않는다. 심지어 &lt;code class=&quot;language-text&quot;&gt;string::std&lt;/code&gt;이 복사 생성자(Copy Constructor)를 가지고 있기 때문에 &lt;code class=&quot;language-text&quot;&gt;std::string&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;union&lt;/code&gt;에 넣을 수 조차 없다.&lt;/p&gt;
&lt;h2 id=&quot;64-타입의-대수학&quot; style=&quot;position:relative;&quot;&gt;6.4 타입의 대수학&lt;a href=&quot;#64-%ED%83%80%EC%9E%85%EC%9D%98-%EB%8C%80%EC%88%98%ED%95%99&quot; aria-label=&quot;64 타입의 대수학 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;곱 타입과 합 타입 모두 각각 데이터 구조를 정의할 때 유용하게 사용할 수 있지만, 실질적인 강점은 이 둘을 결합할 때 나타난다. 여기서 다시 한번 우리는 합성의 힘을 느끼게된다.&lt;/p&gt;
&lt;p&gt;먼저 우리가 지금까지 발견한 내용을 요약해보도록 하자. 타입 시스템의 기초에는 교환 법칙을 만족하는 두 가지 모노이달(Monoidal) 구조가 있다. 바로 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;를 항등원으로 가지는 합 타입과 유닛 타입인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;을 항등원으로 가지는 곱 타입이다. 우리는 이 개념들을 덧셈과 곱셉에 비유해서 생각해보려고 한다. 이 비유에서 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;는 덧셈의 항등원인 0, 그리고 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;는 곱셈의 항등원인 1에 해당할 것이다.&lt;/p&gt;
&lt;p&gt;이 비유를 한번 어디까지 확장해서 적용할 수 있는지 보도록 하자. 우리는 이미 어떤 수에 0을 곱하게 되면 0이라는 결과를 얻는다는 사실을 알고 있다. 그렇다면 곱 타입인 쌍의 한 요소가 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;라면 이 타입은 Void와 동형일까? 예를 들면 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;를 구성요소로 가진 쌍을 만드는 것이 가능하냐는 것이다.&lt;/p&gt;
&lt;p&gt;쌍이라는 타입을 가진 값을 생성하기 위해서는 쌍의 구성 요소가 될 두 개의 값이 필요하다. 문제는 정수는 쉽게 만들 수 있지만 문제는 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입의 값이 존재하지 않는다는 것이다. 따라서 모든 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에 대해 타입 &lt;code class=&quot;language-text&quot;&gt;(a, Void)&lt;/code&gt;는 값을 가질 수 없는 타입(Uninhabited Type)이며, 결과적으로 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;와 동등하다. 다시 말해 &lt;code class=&quot;language-text&quot;&gt;a*0 = 0&lt;/code&gt;인 것이다.&lt;/p&gt;
&lt;p&gt;덧셈과 곱셈을 연결하는 또 다른 속성은 분배 법칙이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;곱셈과 덧셈의 분배 법칙이라는 속성은 일반적으로 곱 타입과 합 타입에도 적용될 수 있다. 위 식의 좌변은 아래와 같은 타입에 해당한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 우변은 아래와 같은 타입에 해당한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;좌변과 우변에 해당하는 타입들은 아래와 같은 방법을 통해 상호 변환될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;prodToSum&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;prodToSum&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;  &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;또한 위 함수의 역함수도 존재한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;sumToProd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;sumToProd&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;  &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;case of&lt;/code&gt; 문은 함수 내에서 패턴 매칭에 사용된다. 주어진 변수가 화살표 왼쪽의 패턴과 일치한다면 화살표 오른쪽의 표현식이 실행되는 것이다. 예를 들어 &lt;code class=&quot;language-text&quot;&gt;prodToSum&lt;/code&gt; 함수를 호출해보는 상황을 한번 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;prod1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;prod1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hi!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;case e&lt;/code&gt; 구문의 &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;Left &quot;Hi!&quot;&lt;/code&gt;에 해당한다. 이는 &lt;code class=&quot;language-text&quot;&gt;Left y&lt;/code&gt;라는 패턴과 일치하기 때문에 &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;“Hi!”&lt;/code&gt;라는 값으로 대체된다. 이 경우 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;2&lt;/code&gt;에 매칭될 것이기 때문에 &lt;code class=&quot;language-text&quot;&gt;case&lt;/code&gt; 문을 사용한 전체 함수의 결과는 &lt;code class=&quot;language-text&quot;&gt;Left(2, &quot;Hi!&quot;)&lt;/code&gt;가 되는 것이다.&lt;/p&gt;
&lt;p&gt;여기서 굳이 이 두 함수가 서로의 역함수임을 증명할 생각은 없지만, 가만 생각해보면 이 두 함수는 서로의 역함수여야하는 것이 당연하다. 왜냐하면 이 두 함수는 그저 자신이 받은 두 데이터 구조의 내용을 간단하게 재포장하는 것에 불과하기 때문이다. 즉, 데이터는 동일하지만 표현 방식이 다른 것 뿐이다.&lt;/p&gt;
&lt;p&gt;수학자들은 이처럼 얽혀있는 두 개의 모노이드에 대해 반환(Semiring)이라는 이름을 붙혔다. 이것은 이 경우 타입 간의 뺄셈에 대해서는 정의할 수 없기 때문에 완전한 “환(Ring)”이라고 말할 수는 없는 것이다.&lt;/p&gt;
&lt;p&gt;반환(Semiring)은 환(Ring)에서 음의 요소(&lt;strong&gt;N&lt;/strong&gt;egative) n이 빠진 것이므로, 말장난처럼 “Rig”라고 부르기도 한다.&lt;/p&gt;
&lt;p&gt;하지만 음의 요소가 빠진 반환만으로도 자연수의 관한 명제를 타입에 관한 명제로 번역하여 많은 이점을 얻을 수 있다. 여기 몇 가지 흥미로운 항목들을 담은 번역 표가 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Numbers&lt;/th&gt;
&lt;th&gt;Types&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;a+b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`Either a b = Left a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;a*b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;(a, b)&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;Pair a b = Pair a b&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;2=1+1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`data Bool = True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;1+a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`data Maybe = Nothing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;리스트 타입은 특히 더 흥미로운데, 이 타입은 방정식의 해로 정의되기 때문이다. 우리가 정의하려는 타입은 일종의 방정식이며 아래와 같이 표현된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 방정식의 &lt;code class=&quot;language-text&quot;&gt;List a&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;로 치환해서 이 식을 일반화하면 아래와 같은 방정식을 얻을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 타입의 세계에는 뺄셈이나 나눗셈이 없으니 우리는 이 문제를 전통적인 대수적 방법론으로는 해결할 수 없다. 하지만 이 식에 표현되어있는 녀석들을 치환하는 것 정도는 할 수 있다. 우변에 있는 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;(1 + a * x)&lt;/code&gt;로 계속 해서 치환하고 분배 법칙을 사용해보자. 그러면 이제 이러한 식으로 이어질 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 이 식은 무한한 곱(튜플)의 합으로 끝나게 되는데, 이것은 리스트가 빈 경우 &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;, 단일 값인 경우 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;, 쌍인 경우는 &lt;code class=&quot;language-text&quot;&gt;a*a&lt;/code&gt;, 트리플인 경우 &lt;code class=&quot;language-text&quot;&gt;a*a*a&lt;/code&gt;처럼 무한히 나아갈 것이라고 해석할 수 있다. 이게 결국 리스트의 정의 그 자체이다.&lt;/p&gt;
&lt;p&gt;이외에도 리스트에 대한 더 많은 내용들이 있지만, 다른 내용들에 대해서는 추후 펑터(Functor)와 고정점(Fixed Point)에 대해서 배운 후에 리스트와 같은 기타 재귀적인 데이터 구조에 대해서 다시 다룰 때 이야기를 해볼 것이다.&lt;/p&gt;
&lt;p&gt;결국 이처럼 기호로 표현되는 변수를 사용하여 어떠한 방정식을 해결하는 것이 바로 대수(Algebra)이며, 대수학으로 표현할 수 있는 타입에 이름을 붙힌 것이 대수적 데이터 타입(Algebraic Data Type)이다.&lt;/p&gt;
&lt;p&gt;마지막으로 타입의 대수에 대한 아주 중요한 해석 중 하나를 이야기하려고 한다. 두 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 곱 타입에는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 타입의 값과 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 타입의 값이 모두 포함되어야 하지만, 두 타입의 합 타입에는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 타입이나 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 타입의 값이 둘 중 하나라도 포함되어 있으면 충분하다. 이는 논리식인 AND와 OR도 반환(Semiring)을 형성한다는 것을 의미하며, 결국 논리식 또한 타입 이론으로 매핑될 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Logic&lt;/th&gt;
&lt;th&gt;Types&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`a&lt;/td&gt;
&lt;td&gt;b`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;a &amp;amp;&amp;amp; b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;(a, b)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;논리식과 타입 이론 간의 유사성은 이외에도 더 깊게 이어질 수 있으며, 커리-하워드 동형성(Curry-Howard Isomorphism)의 기초라고 할 수 있다. 이 내용에 대해서는 추후 함수 타입에 대해 이야기할 때 다시 살펴보도록 하겠다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 5. 곱과 합]]></title><description><![CDATA[고대 그리스의 시인 에우리피데스가 “사귀는 친구를 보면 그 사람을 알 수 있다.”라고 말했듯이, 우리의 존재는 우리가 가진 관계를 통해 정의된다. 카테고리 이론에서는 이 개념이 더더욱 중요하다. 만약 우리가 어떤 카테고리 내에 존재하는 특정 대상에 대해 명확하게 설명하기 위해서는 그 대상과 다른 대상들과의 관계까지도 함께 보아야 하기 때문이다. 그리고 이러한 관계는 사상(Morphism)에 의해 정의된다. (물론 여기서 관계라 함은 항등 사상으로 표현되는 자기 자신과의 관계 또한 포함된다.)]]></description><link>https://evan-moon.github.io/2024/02/27/category-theory-for-programmers-5-products-and-coproducts/</link><guid isPermaLink="false">20240227-category-theory-for-programmers-5-products-and-coproducts</guid><pubDate>Tue, 27 Feb 2024 09:29:20 GMT</pubDate><content:encoded>&lt;p&gt;고대 그리스의 시인 에우리피데스가 “사귀는 친구를 보면 그 사람을 알 수 있다.”라고 말했듯이, 우리의 존재는 우리가 가진 관계를 통해 정의된다. 카테고리 이론에서는 이 개념이 더더욱 중요하다. 만약 우리가 어떤 카테고리 내에 존재하는 특정 대상에 대해 명확하게 설명하기 위해서는 그 대상과 다른 대상들과의 관계까지도 함께 보아야 하기 때문이다. 그리고 이러한 관계는 사상(Morphism)에 의해 정의된다. (물론 여기서 관계라 함은 항등 사상으로 표현되는 자기 자신과의 관계 또한 포함된다.)&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;카테고리 이론에는 “보편적 구성(Universal Construction)”이라고 불리는 방법이 존재한다. 이 구조는 각 대상들이 가지고 있는 관계를 통해 대상 자체를 정의하는 방법 중 하나이다. 이 방법은 먼저 특정 대상, 그리고 그 대상과 다른 대상 간의 관계를 나타내는 사상으로 구성된 특별한 패턴을 선택하고, 이 패턴이 카테고리 안에서 어떤 방식으로 나타나는지를 찾아내는 방식으로 진행된다. 만약 이 패턴이 일반적이고 카테고리의 크기가 충분히 크다면 이 패턴과 매칭되는 결과 또한 매우 많을 것이다. 결국 이 구성 방법의 핵심은 이렇게 찾아낸 무수한 결과들을 특정한 기준으로 평가하고 랭킹을 매겨 가장 적합한 결과를 찾아내는 것이다.&lt;/p&gt;
&lt;p&gt;이 과정은 마치 웹에서 검색을 하는 방식과 유사하다. 검색 쿼리는 일종의 패턴이다. 만약 이 쿼리가 매우 일반적인 쿼리라면 무수히 많은 쿼리 결과가 노출될 것이다. 이 결과 중 일부는 우리가 질의한 쿼리와 관련이 있을 수도 있지만 어떤 것들은 관련이 없을 수도 있다. 결국 우리는 관련없는 결과들을 제외하기 위해 쿼리를 더 세밀하게 다듬어가며 검색의 정확도를 높혀나간다. 최종적으로 검색 엔진은 이렇게 질의된 검색 결과들에게 랭킹을 매겨 결과를 순위 별로 나열하고, 사용자가 가장 관심을 가질만한 결과를 검색 결과 리스트의 최상단에 위치시킬 것이다.&lt;/p&gt;
&lt;h2 id=&quot;51-초기-대상initial-object&quot; style=&quot;position:relative;&quot;&gt;5.1 초기 대상(Initial Object)&lt;a href=&quot;#51-%EC%B4%88%EA%B8%B0-%EB%8C%80%EC%83%81initial-object&quot; aria-label=&quot;51 초기 대상initial object permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;카테고리 내에서 가장 단순한 형태는 단일 대상 그 자체이다. 아마 이렇게 단순한 형태의 패턴을 가진 무언가를 카테고리 내에서 찾아본다면, 당연히 패턴에 매칭되는 결과는 매우 많을 것이다.&lt;/p&gt;
&lt;p&gt;이처럼 일반적인 패턴을 사용하면 너무 많은 매칭 결과가 나오기 때문에, 우리는 이 결과들에 랭킹을 매길 수 있는 기준을 정하고 이 랭킹에서 비롯된 계층구조 내에서 가장 최상위에 있는 대상을 찾아야 한다. 앞서 말했듯이 이러한 대상을 정의하기 위해 우리가 사용해볼 수 있는 유일한 수단은 바로 사상이다.&lt;/p&gt;
&lt;p&gt;사상을 대상에서 다른 대상으로 향하는 일종의 화살표라고 생각해보자. 이 경우 카테고리의 한쪽 끝에서 다른쪽 끝으로 향하는 전반적인 화살표의 흐름이 존재할 수 있고, 만약 카테고리가 부분순서(Partial Order)와 같이 정렬되었다면 이 가정은 반드시 참이다. 그렇다면 어떠한 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 다른 대상 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로 향하는 화살표(사상)가 존재하는 경우, “&lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;보다 더 초기적(Initial)이다”라고 정의하여 대상의 선행성이라는 개념을 일반화해볼 수 있다.&lt;/p&gt;
&lt;p&gt;이제 우리는 초기 대상이라는 개념을 “다른 모든 대상들로 향하는 화살표를 가진 대상”이라고 정의할 것이다. 물론 카테고리 내에 이런 대상이 반드시 존재하리란 보장은 없겠지만, 사실 이 문제보다는 오히려 이런 성질을 가진 대상이 너무 많을 수 있다는 것이 문제가 될 것이다. 다시 말해 쿼리의 검출율(Recall)은 높지만 정밀도(Precision)가 부족하다는 뜻이다.&lt;/p&gt;
&lt;p&gt;이 문제의 해결책에 대한 힌트는 정렬되어있는 카테고리(Ordered Categories)에서 얻을 수 있다. 대상 간의 순서가 명확하게 정의된 카테고리에서는 두 대상 간 최대 하나의 화살표만 허용되기 때문이다. 이러한 카테고리에서 어떤 대상이 다른 대상보다 작거나 같을 수 있는 방법은 하나 뿐이다. 이러한 사실을 토대로 우리는 초기 대상에 대해 다음과 같은 정의를 내려볼 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;👉  “초기 대상”은 해당 카테고리 내에서 다른 대상으로 향하는 단 하나의 사상을 가진 유일한 대상이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 608px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/38374193f4fa1493e2383b55a5a4734c/640be/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAVABQDASIAAhEBAxEB/8QAGAABAQADAAAAAAAAAAAAAAAAAAMCBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7kaQjcFSoGIP/8QAGxABAAICAwAAAAAAAAAAAAAAAgABERIDEyH/2gAIAQEAAQUCa1I5d1Eveo0ohmYqA6V//8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAgICAwAAAAAAAAAAAAAAABEBIQIQElFh/9oACAEBAAY/AmmKNcWO1jqqnsn0R//EABwQAQADAAMBAQAAAAAAAAAAAAEAESExUWEQQf/aAAgBAQABPyGyup+EEQK7v4NsGt3SWAeZUNJzV3A1nU9QaSvrP//aAAwDAQACAAMAAAAQF8g8/8QAFREBAQAAAAAAAAAAAAAAAAAAIHH/2gAIAQMBAT8Qo//EABcRAAMBAAAAAAAAAAAAAAAAAAERIEH/2gAIAQIBAT8QLyP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMRBBUWGB/9oACAEBAAE/EHMP11nzlQ4V2z6k741a2UdCBr97gej2OlltNuIBGjswmbIQIHq50EPQ65C6qq1Vz//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/38374193f4fa1493e2383b55a5a4734c/640be/1.jpg&quot; srcset=&quot;/static/38374193f4fa1493e2383b55a5a4734c/0913d/1.jpg 160w,
/static/38374193f4fa1493e2383b55a5a4734c/cb69c/1.jpg 320w,
/static/38374193f4fa1493e2383b55a5a4734c/640be/1.jpg 608w&quot; sizes=&quot;(max-width: 608px) 100vw, 608px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;그러나 비록 이렇게 초기 대상에 대해 정의를 했고 실제로 초기 대상이 카테고리 안에 존재하는 것이 확인되었다고 해서 초기 대상이 카테고리 내에 유일하게 존재한다는 사실을 보장하는 것은 또 다른 이야기이다. 초기 대상의 유일성을 보장하기 위해 우리가 사용해볼 수 있는 유용한 아이디어는 바로 동형성(Isomorphism)이다. 동형성은 카테고리 이론에서 굉장히 중요한 부분을 차지하기 때문에 조만간 이에 대해서도 다룰테지만, 일단 지금은 동형성에 따라 초기 대상의 유일성을 보장할 수 있다는 점만 언급하고 넘어가도록 하겠다.&lt;/p&gt;
&lt;p&gt;간단한 예시를 한 번 보자. Poset이라고도 부르는 부분순서집합(Paritally Ordered Set)에서의 초기 대상은 이 집합에서 가장 작은 요소이다. 물론 이 개념이 모든 Poset에 적용되는 것은 아니고, 모든 정수(양수, 0, 음수)의 집합에 “작거나 같음” 관계를 적용한 특정 Poset같은 경우는 초기 대상이 존재하지 않는다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;초기 대상은 카테고리 내의 다른 모든 대상으로 향하는 사상을 가져야 한다. 그러나 “작거나 같음”이라는 사상을 가진 정수 집합은 무한 집합이기 때문에 “모든 정수에 대해 작거나 같기만 하는 관계를 가진 대상”이 존재할 수 없으므로 초기 대상이 존재하지 않는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;반면 집합과 함수로 이루어진 카테고리에서 초기 대상은 공집합으로 정의할 수 있으며, 공집합은 Haskell에서의 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입에 해당한다. 지난 챕터에서 우리가 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt; 타입에서 임의의 다른 타입 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 나아가는 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt; 함수를 정의했던 것을 기억하는가?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;absurd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;바로 이러한 종류의 사상들이 타입으로 이루어진 카테고리에서 &lt;code class=&quot;language-text&quot;&gt;Void&lt;/code&gt;를 초기 대상으로 만들어주는 녀석들이다.&lt;/p&gt;
&lt;h2 id=&quot;52-종결-대상terminal-object&quot; style=&quot;position:relative;&quot;&gt;5.2 종결 대상(Terminal Object)&lt;a href=&quot;#52-%EC%A2%85%EA%B2%B0-%EB%8C%80%EC%83%81terminal-object&quot; aria-label=&quot;52 종결 대상terminal object permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자, 단일 대상에 대한 패턴 이야기를 계속 해보자. 이번에는 대상에 대한 랭킹을 매기는 방식을 변경해볼 것이다. 우리는 어떠한 대상 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에서 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 향하는 사상이 있는 경우 ”&lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;보다 더 종결적(Terminal)이다”라고 이야기할 수 있다. 앞서 보았던 초기 대상과는 방향이 정반대라는 점에 주목하자. 우리는 카테고리 안에서 다른 대상들보다 더 많이 종결적인 대상을 찾아볼 것이다. 그리고 다시 한번 말하지만 이 검색 결과는 고유성을 가져야 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 종결 대상은 카테고리 내의 모든 객체로부터 오는 유일한 화살표를 가진 유일한 대상이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ccbd3fc68e5ce8c978d1487a138556c0/c08c5/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 99.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBQT/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB2oy4k0EiqiLRX//EABwQAAICAgMAAAAAAAAAAAAAAAECAAMQMREhIv/aAAgBAQABBQJt8mDVillq6OAvqf/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABkQAAIDAQAAAAAAAAAAAAAAABARAAEhMf/aAAgBAQAGPwJHLU6y9H//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEQITFhof/aAAgBAQABPyFqBZADT7HezuVu324X5WRHZVwXH//aAAwDAQACAAMAAAAQW8i8/8QAFhEAAwAAAAAAAAAAAAAAAAAAESAh/9oACAEDAQE/EKU//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFA1iT//xAAdEAEBAAEFAQEAAAAAAAAAAAABEQAQITFRYYGx/9oACAEBAAE/EA77GMfuIS6yrQJ3vjhuDZxk8nYOvzJRZXiW+i+GEDYnmj05igC8un//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/ccbd3fc68e5ce8c978d1487a138556c0/c08c5/2.jpg&quot; srcset=&quot;/static/ccbd3fc68e5ce8c978d1487a138556c0/0913d/2.jpg 160w,
/static/ccbd3fc68e5ce8c978d1487a138556c0/cb69c/2.jpg 320w,
/static/ccbd3fc68e5ce8c978d1487a138556c0/c08c5/2.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;초기 대상과 마찬가지로 종결 대상 또한 동형성에 따라 카테고리 내에서 유일하게 존재한다고 이야기할 수 있다. 이에 대해서는 조만간 다시 설명하겠다.&lt;/p&gt;
&lt;p&gt;먼저 몇 가지 예제를 한번 살펴보도록 하겠다. 만약 Poset 내부에 종결 대상이 존재한다면 이는 아마 가장 큰 요소일 것이다. 집합의 카테고리에서의 종결 대상은 단일원소집합이다. 이미 우리는 단일원소집합에 대해서도 한번 이야기를 했었는데, 단일원소집합은 C++의 &lt;code class=&quot;language-text&quot;&gt;void&lt;/code&gt; 타입, Haskell에서는 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;로 표현되는 Unit 타입에 해당한다.&lt;/p&gt;
&lt;p&gt;이것은 단 하나의 값만을 가진 타입으로, C++에서는 이러한 사실을 암묵적으로 표현하지만 Haskell에서는 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt; 라는 빈 괄호의 형태를 통해 명시적으로 표현하고 있다. 또한 이전 챕터에서 어떤 임의의 타입에서 Unit 타입으로 향하는 순수 함수는 단 하나만 존재할 수 있다는 사실 또한 언급했었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 종결 대상에 대한 모든 조건이 만족되었다.&lt;/p&gt;
&lt;p&gt;종결 대상에 대한 예시에서 유일성에 대한 조건이 중요한 이유는 결국 공집합을 제외한 다른 모든 집합들도 각각의 집합으로부터 오는 사상을 가질 수 있기 때문이다. 예를 들면 모든 타입을 받을 수 있고 &lt;code class=&quot;language-text&quot;&gt;Boolean&lt;/code&gt; 타입의 값을 반환하는 사상인 Predicate 함수가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;yes&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;yes&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt; 타입은 종결 대상이 아니다. 다른 타입에서 Bool 타입으로 향하는 함수는 &lt;code class=&quot;language-text&quot;&gt;yes _ = True&lt;/code&gt; 외에도 하나가 더 있기 때문에 유일한 사상이라고 말할 수 없기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 우리는 종결 대상은 유일해야한다는 조건을 통해 종결 대상의 정의를 단 하나의 타입으로 좁힐 수 있는 정밀도를 만들어낼 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;53-쌍대성duality&quot; style=&quot;position:relative;&quot;&gt;5.3 쌍대성(Duality)&lt;a href=&quot;#53-%EC%8C%8D%EB%8C%80%EC%84%B1duality&quot; aria-label=&quot;53 쌍대성duality permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;여기까지 오면 여러분은 아마 초기 대상과 종결 대상을 정의하는 방식 간에 대칭성이 존재한다는 사실을 눈치챘을 것이다. 이 두 정의 사이의 유일한 차이점은 그저 사상의 방향 뿐이었다. 여기서 한발짝 더 나아가보자면 이제 우리는 어떤 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 모든 사상의 방향을 반대로 뒤집어서 반대 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 정의할 수도 있을 것이다.&lt;/p&gt;
&lt;p&gt;반대 카테고리는 그저 특정 카테고리의 사상의 방향을 반대로 뒤집은 것 뿐이니 당연히 사상의 합성 규칙이나 다른 요구사항도 만족한다. 만약 원래 카테고리에서 사상 &lt;code class=&quot;language-text&quot;&gt;f::a-&gt;b&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;g::b-&gt;c&lt;/code&gt;가 사상 &lt;code class=&quot;language-text&quot;&gt;h::a-&gt;c&lt;/code&gt;로 합성되었다면, 반대 카테고리의 뒤집힌 사상인 &lt;code class=&quot;language-text&quot;&gt;f^op::b-&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;g^op::c-&gt;b&lt;/code&gt;  또한 &lt;code class=&quot;language-text&quot;&gt;h^op::c-&gt;a&lt;/code&gt;로 합성된다는 것이다. 그리고 각 대상에 대한 항등사상을 반대로 뒤집는 것은 의미가 없으므로, 항등사상은 그대로 유지된다.&lt;/p&gt;
&lt;p&gt;쌍대성(Duality)이라는 개념은 수학자들이 카테고리 이론을 사용할 때의 생산성을 두 배로 높혀주기 때문에 꽤 중요한 속성으로 취급된다. 우리가 구성한 모든 것들에는 그와 대응하는 것들이 존재하며, 증명하는 모든 정리들에 대응하는 정리들 또한 자동으로 따라오기 때문이다.&lt;/p&gt;
&lt;p&gt;반대 카테고리의 구성 요소들은 곱(product)와 쌍대곱(coproduct), 모나드(monad)와 쌍대모나드(comonad), 콘(cone)과 쌍대콘(cocone), 극한(limit)과 쌍대극한(colimit)과 같이 “co 또는 쌍대”라는 접두사가 붙어있다. 그러나 cocomonad와 같은 개념은 존재하지 않는다. 왜냐하면 화살표를 두 번 뒤집으면 다시 원래 상태로 돌아오기 때문이다.&lt;/p&gt;
&lt;p&gt;즉, 위의 정의에 따라 반대 카테고리에서의 초기 대상은 종결 대상이다.&lt;/p&gt;
&lt;h2 id=&quot;54-동형성isomorphisms&quot; style=&quot;position:relative;&quot;&gt;5.4 동형성(Isomorphisms)&lt;a href=&quot;#54-%EB%8F%99%ED%98%95%EC%84%B1isomorphisms&quot; aria-label=&quot;54 동형성isomorphisms permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;우리는 프로그래머로서 같다는 개념, 즉 동등성(Equality)을 정의한다는 것이 쉽지 않다는 것을 이미 잘 알고 있다. 두 개의 대상이 같다는 것은 무엇을 의미하는 걸까? 메모리에서 동일한 위치를 차지하는 것을 의미할까? 이 대상이 집합이라면 원소들이 전부 동일하면 같다고 봐야할까? 혹은 하나는 실수부와 허수부로 표현되고, 다른 하나는 크기와 각도로 표현되는 복소수라면 이 두 복소수는 같다고 봐야할까?&lt;/p&gt;
&lt;p&gt;아마 여러분은 수학자들이 이미 동등성에 대한 의미를 찾아냈을 것이라고 생각하겠지만, 사실 수학자들도 아직 동등성이 무엇인가에 대한 명확한 정의를 내리지 못 했다. 동등성에 대한 정의에는 명제 동등성, 의미 동등성, 확장 동등성, 호모토피 유형 이론에서의 경로로 정의되는 동등성 등 여러가지 방법이 제시된다. 그리고 동등성보다 더 약한 개념인 동형성, 그리고 동형성보다도 더 약한 개념인 등가성이라는 개념도 있다.&lt;/p&gt;
&lt;p&gt;우선 동형에 대해 직관적으로 이해해보자면 동형이라는 의미는 동일한 형태를 가지고 있다는 말이니 동형인 대상들은 서로 비슷하게 보일 것이다. 비슷하게 보인다는 것은 어떤 한 대상의 각 부분들이 다른 대상의 어떠한 부분과 일대일로 대응된다는 것을 의미한다. 즉, 상대적인 상황에 따라 조금씩 달라질 수는 있지만 대체로 동형인 두 대상은 서로 완벽한 복사본처럼 보일 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;수학적으로 이야기해보자면 어떤 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 대상 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;로의 매핑이 존재하고 대상 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에서 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;로 향하는 매핑이 존재하며, 이 두 매핑이 서로의 역함수라는 것을 의미한다. 또한 우리는 이미 카테고리 이론에서 이러한 매핑을 사상이라고 한다는 것을 잘 알고 있다. 정리해보자면 두 대상이 동형이라는 의미는 두 대상이 서로에게 향하는 사상을 가지고 있고, 이 사상들이 서로의 반대 개념인 역사상(Inverse Morphism)이 되어야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;이러한 역사상에 대한 개념은 합성과 항등이라는 개념을 통해 이해하는 것이 쉽다. 사상 &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt;가 사상 &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;의 역사상이라면, 이 두 사상의 합성사상은 항등사상이 되어야 한다. 이러한 관계를 나타낼 수 있는 식은 총 두 가지가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서 필자가 초기 대상이나 종결 대상이 동형성을 기준으로 했을때 카테고리 내에 유일하게 존재한다고 말한 것은 어떤 두 초기 대상 또는 종결 대상이 서로 동형(Isomorphic) 관계에 있다는 것을 의미한다는 설명이었다.&lt;/p&gt;
&lt;p&gt;말이 조금 어렵게 느껴지지만 조금만 생각해보면 쉽게 이해할 수 있다. 한번 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;과 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 두 초기 대상이 있다고 가정해보자. &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 초기 대상이니 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 유일한 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 존재할 것이다. 마찬가지로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;또한 초기 대상이니 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 유일한 사상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 존재한다. 그렇다면 이 두 사상의 합성은 무엇일까?&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/516e915f7161e4ca2ff7bc7baff41e50/cb69c/3.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 63.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdp0ihh//8QAGRABAAMBAQAAAAAAAAAAAAAAARESIQAi/9oACAEBAAEFAre1qGkE1zv/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAXEAADAQAAAAAAAAAAAAAAAAAAESAh/9oACAEBAAY/AkbP/8QAGhABAQEBAQEBAAAAAAAAAAAAAREAITFRcf/aAAgBAQABPyEdPt8y08335m0SOWpNPHf3BCG//9oADAMBAAIAAwAAABBgz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABoQAQADAQEBAAAAAAAAAAAAAAEAESExQbH/2gAIAQEAAT8QBkLPmqxH7ET2uHLOQSLgg3TCVxCqeTW1W3rTYAAAcDyf/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3&quot; title=&quot;&quot; src=&quot;/static/516e915f7161e4ca2ff7bc7baff41e50/cb69c/3.jpg&quot; srcset=&quot;/static/516e915f7161e4ca2ff7bc7baff41e50/0913d/3.jpg 160w,
/static/516e915f7161e4ca2ff7bc7baff41e50/cb69c/3.jpg 320w&quot; sizes=&quot;(max-width: 320px) 100vw, 320px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이 다이어그램에 존재하는 모든 사상은 전부 유일하게 존재한다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;위 그림을 보면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 합성한 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g\circ f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 사상은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 출발해 다시 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 돌아가는 사상이 된다. 그러나 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 초기 대상이니 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 사상은 반드시 항등 사상 하나만 존재해야하는데, 모든 카테고리에는 항등 사상이 반드시 존재해야 하기 때문에 이 사상을 제거할 수는 없다. 결국 이러한 제약으로 인해 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g\circ f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 항등 사상일 수 밖에 없는 것이다. 마찬가지로 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 사상도 결국 하나만 존재할테니, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f\circ g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;도 항등사상이라고 할 수 있다. 이렇게 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 서로의 역이 되어야 한다는 것이 입증됨으로써 어떤 두 초기 대상이든 모두 동형 관계에 놓인다는 사실 또한 증명되었다.&lt;/p&gt;
&lt;p&gt;위 증명 과정에서는 초기 대상에서 다시 자기 자신에게 향하는 사상의 유일성을 사용했다. 만약 이 유일성이 보장되지 않는다면 “동형성을 기준으로 유일하다”라는 명제를 증명할 수 없다.&lt;/p&gt;
&lt;p&gt;그런데 왜 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 유일성이 필요한걸까? 그 이유는 두 초기 대상이 동형이라는 가정에서 출발하여 초기 대상의 유일함을 증명하기 위해서는 이 동형성마저도 유일하다는 조건이 만족되어야 하기 때문이다. 원칙적으로는 두 대상 간의 여러 개의 동형성이 존재할 수 있겠지만, 이번에 살펴본 예시에서의 두 초기 대상은 서로에게 동형이 될 수 있는 케이스가 단 하나만 존재한다. 이처럼 “유일한 동형성을 기준으로 유일하다”는 것은 보편적 구성의 매우 중요한 특징이다.&lt;/p&gt;
&lt;h2 id=&quot;55-곱products&quot; style=&quot;position:relative;&quot;&gt;5.5 곱(Products)&lt;a href=&quot;#55-%EA%B3%B1products&quot; aria-label=&quot;55 곱products permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;다음으로 살펴볼 보편적 구성은 바로 곱의 개념이다. 우리는 두 집합의 데카르트 곱(Cartesian Product)이 쌍으로 이루어진 집합이라는 것을 알고 있다. 그렇다면 곱 집합과 곱 집합 내부의 쌍을 이루는 구성 요소 집합들을 연결해주는 패턴은 무엇일까? 우리가 이 패턴을 이해할 수만 있다면 이제 다른 카테고리에도 일반화해서 적용해볼 수 있을 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;만약 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A = \{1, 2\}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고, 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B = \{a, b\}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라면 이 두 집합의 데카르트 곱은 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A\times B = \{(1,a),(1,b),(2,a),(2,b)\}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 같이 각 집합의 원소로 구성된 튜플을 원소로 가진 집합으로 정의된다. 즉, 구성 요소 집합이라는 의미는 데카르트 곱 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A\times B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 원소들인 각 튜플을 구성하고 있는 값들의 집합이라는 의미이며, 결국 곱 연산의 재료로 사용된 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 집합 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 의미하는 것이다.&lt;/p&gt;
&lt;p&gt;여기서 역자가 데카르트 곱의 원소가 쌍(Pair)이 아닌 튜플(Tuple)이라고 설명한 이유는, 데카르트 곱이 이항연산이 아니기 때문이다. 즉, 이 연산에는 두 개 이상의 집합이 사용될 수 있으며 데카르트 곱의 원소의 형태도 (x, y, z, …)처럼 계속 길어질 수 있다는 의미이다. 쌍이란 순서가 있는 2개의 구성요소를 가진 개념이고, 튜플은 n개의 구성요소를 가진 개념이므로 엄밀한 정의는 튜플이라고 하는 것이 맞다.&lt;/p&gt;
&lt;p&gt;다만 작가는 여기서 “두 집합의 데카르트 곱”이라는 전제를 깔고 있기 때문에 데카르트 곱의 원소들이 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(1,a)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 같은 쌍의 형태라고 말하고 있는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;일단 우리가 당장 확실하게 이야기할 수 있는 것은 곱 집합에서 각 구성 요소로 향하는 두 개의 함수, 즉 투영 사상(Projections)이 존재한다는 것이다. Haskell에서는 이 두 함수를 &lt;code class=&quot;language-text&quot;&gt;fst&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;snd&lt;/code&gt;라고 부르며, 이 함수들은 각각 쌍의 첫 번째와 두 번째 구성요소를 선택한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수들은 인자를 패턴 매칭하는 형태로 정의된다. 임의의 쌍에 매칭되는 패턴은 위 코드의 &lt;code class=&quot;language-text&quot;&gt;(x, y)&lt;/code&gt;이며, 최종적으로는 이렇게 매칭된 쌍에 접근하여 각 구성요소를 변수 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt;로 추출한다.&lt;/p&gt;
&lt;p&gt;이 정의는 와일드카드(&lt;code class=&quot;language-text&quot;&gt;_&lt;/code&gt;)를 사용하면 더 간단하게 표현해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C++에서 이와 같은 동작은 템플릿 함수를 사용하여 구현해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; A
&lt;span class=&quot;token function&quot;&gt;fst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 내용을 토대로 집합의 카테고리에서 두 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 곱집합을 구성할 수 있는 대상과 사상의 패턴을 정의해보겠다.&lt;/p&gt;
&lt;p&gt;이 패턴은 대상 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;와 그것을 각각 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에 연결해주는 두 개의 사상 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;로 구성된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 417px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/21474f37fbfc536731aa732ab1037274/6eca5/4.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEDAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB70aahiK//8QAGxABAAICAwAAAAAAAAAAAAAAARESAAIQITH/2gAIAQEAAQUCWMs68V7SQ8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAADAAMAAAAAAAAAAAAAAAAAECEBEYH/2gAIAQEABj8CLxWmsr//xAAbEAEAAwADAQAAAAAAAAAAAAABABEhEDFRQf/aAAgBAQABPyEaX9gLPbW9eNWeGw8hv0MuabfZ/9oADAMBAAIAAwAAABALD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABYRAAMAAAAAAAAAAAAAAAAAABARIf/aAAgBAgEBPxBUf//EAB0QAAIBBAMAAAAAAAAAAAAAAAERACExQVEQYdH/2gAIAQEAAT8QNtW2BFx4Cy4u+8rXF7ahCnpYMFkSBFFGCCF2ic//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;4&quot; title=&quot;&quot; src=&quot;/static/21474f37fbfc536731aa732ab1037274/6eca5/4.jpg&quot; srcset=&quot;/static/21474f37fbfc536731aa732ab1037274/0913d/4.jpg 160w,
/static/21474f37fbfc536731aa732ab1037274/cb69c/4.jpg 320w,
/static/21474f37fbfc536731aa732ab1037274/6eca5/4.jpg 417w&quot; sizes=&quot;(max-width: 417px) 100vw, 417px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;이 패턴에 부합하는 모든 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 곱집합의 후보라고 볼 수 있다. 하지만 문제는 이런 후보들이 한두개가 아니라는 것이다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/497145782e1ce89bc605805e3ade82a8/c08c5/5.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 50.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAIDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAduNwA//xAAZEAEAAgMAAAAAAAAAAAAAAAABAAIQITH/2gAIAQEAAQUCbbVhzP8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAAREAICH/2gAIAQEABj8CQjOV/8QAGRABAAMBAQAAAAAAAAAAAAAAAQARQSAh/9oACAEBAAE/IazQsEHoMyKw8f/aAAwDAQACAAMAAAAQMM//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAQUBAAAAAAAAAAAAAAABEQAQITFBof/aAAgBAQABPxDIoyo1M0BmUrzlaIycsk2//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;5&quot; title=&quot;&quot; src=&quot;/static/497145782e1ce89bc605805e3ade82a8/c08c5/5.jpg&quot; srcset=&quot;/static/497145782e1ce89bc605805e3ade82a8/0913d/5.jpg 160w,
/static/497145782e1ce89bc605805e3ade82a8/cb69c/5.jpg 320w,
/static/497145782e1ce89bc605805e3ade82a8/c08c5/5.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;예를 들어 두 개의 Haskell 타입, &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;을 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;라고 생각하고 이 타입(집합)들에 대한 곱집합 후보를 한번 살펴보자.&lt;/p&gt;
&lt;p&gt;자, &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt; 타입은 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt; 타입의 곱집합 후보가 맞을까? 맞다. 아래 투영 사상들을 한번 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 정의는 단순 그 자체이지만, 우리가 정의했던 기준에는 부합한다. 그러면 이번에는 세 개의 구성 요소로 이루어진 튜플인 &lt;code class=&quot;language-text&quot;&gt;(Int, Int, Bool)&lt;/code&gt;을 살펴보자. 이 튜플 또한 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;의 곱집합이 될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아마도 이미 눈치챘겠지만 우리가 찾아낸 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;의 곱집합 후보 중 첫 번째 후보는 곱의 Int 차원만을 다루고 있어 너무 작다고 느껴지고, 두 번째 후보는 Int 차원을 중복시켜놓았으니 너무 크다고 느껴진다.&lt;/p&gt;
&lt;p&gt;이제 보편적 구성(Universal Construction)의 랭킹 개념이 등장할 차례이다. 이제 우리는 패턴에 일치되어 뽑힌 두 결과 후보를 비교해볼 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;우선 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt;보다 “더 나은 경우”를 설명하고 싶은 상황이라고 가정하고, 하나의 후보 대상인 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;와 이 대상의 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;를 다른 후보 대상인 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt;와 이 대상의 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&apos;&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;q&apos;&lt;/code&gt;와 비교해보려고 한다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;로 향하는 임의의 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;이 존재한다면 경우 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;가 더 낫다고 말할 수 있겠지만, 그래도 이런 설명은 너무 빈약하다. 우리는 대상 뿐 아니라 이 대상이 가진 투영 사상들에 대해서도 어떤 것이 더 낫다고 설명할 수 있어야하기 때문이다. 즉, 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&apos;&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&apos;&lt;/code&gt; 또한 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;, 그리고 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;의 합성을 통해 구성될 수 있어야 한다는 의미이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 541px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/064dcc92871175f26dde24e634e3cce2/8af7b/6.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 81.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHeWVHkB//EABkQAQACAwAAAAAAAAAAAAAAAAEAEgIRIv/aAAgBAQABBQJdQy6jZaIE/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAARAAElH/2gAIAQEABj8CeCGq/8QAGxAAAwEAAwEAAAAAAAAAAAAAAREhABAxUUH/2gAIAQEAAT8h+jUMHtAcBHD2vFk02+4mKFv/2gAMAwEAAgADAAAAELPP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAAIDAQEAAAAAAAAAAAAAAREhADFBURD/2gAIAQEAAT8QAjK2KMVpCDbGJs578isZsOxyvMiA4LTTU6oxBUfR5n//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;6&quot; title=&quot;&quot; src=&quot;/static/064dcc92871175f26dde24e634e3cce2/8af7b/6.jpg&quot; srcset=&quot;/static/064dcc92871175f26dde24e634e3cce2/0913d/6.jpg 160w,
/static/064dcc92871175f26dde24e634e3cce2/cb69c/6.jpg 320w,
/static/064dcc92871175f26dde24e634e3cce2/8af7b/6.jpg 541w&quot; sizes=&quot;(max-width: 541px) 100vw, 541px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;이 방정식을 바라보는 다른 방법은 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;이 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&apos;&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&apos;&lt;/code&gt;를 인수분해한다고 보는 것이다. 이 방정식들의 변수들이 함수가 아니라 자연수, 그리고 함수의 합성을 의미하는 점(&lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt;)이 곱셉 연산 기호라고 가정해보자. 결국 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;은 &lt;code class=&quot;language-text&quot;&gt;p&apos;&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&apos;&lt;/code&gt;가 공유하는 공통 인수라는 사실을 알 수 있다.&lt;/p&gt;
&lt;p&gt;좀 더 직관적인 이해를 위해, &lt;code class=&quot;language-text&quot;&gt;fst&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;snd&lt;/code&gt; 라는 두 표준 투영 사상을 가진 &lt;code class=&quot;language-text&quot;&gt;(Int, Bool)&lt;/code&gt; 쌍이 앞서 알아봤던 두 개의 후보보다 더 나은 후보가 맞는지를 직접 보여주겠다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bff3233c699c3f1604778632826dfb07/cb69c/7.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 69.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHdgMsEH//EABoQAAICAwAAAAAAAAAAAAAAAAABAhEQEiH/2gAIAQEAAQUCbFzCiaCuv//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABcQAAMBAAAAAAAAAAAAAAAAAAAQIQH/2gAIAQEABj8Cd1U//8QAGxAAAgMAAwAAAAAAAAAAAAAAAREAIUEQMaH/2gAIAQEAAT8hQV7DHQtnTfBbuZahBECqyKDU/9oADAMBAAIAAwAAABCjD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABoQAQEAAwEBAAAAAAAAAAAAAAERADFBIRD/2gAIAQEAAT8QTSCVT4ZE4J0Pia2ENThjWUsTxgCQglO5/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;7&quot; title=&quot;&quot; src=&quot;/static/bff3233c699c3f1604778632826dfb07/cb69c/7.jpg&quot; srcset=&quot;/static/bff3233c699c3f1604778632826dfb07/0913d/7.jpg 160w,
/static/bff3233c699c3f1604778632826dfb07/cb69c/7.jpg 320w&quot; sizes=&quot;(max-width: 320px) 100vw, 320px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;첫 번째 후보를 위한 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;은 다음과 같이 정의될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 두 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;는 다음과 같이 재구성될 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;또한 두 번째 후보의 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt; 또한 아래와 같이 유일한 형태로 결정된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;(Int, Bool)&lt;/code&gt;이 다른 두 곱집합 후보보다 더 낫다는 사실을 보였다. 그럼 이제 반대 경우가 성립하지 않는 이유를 살펴보도록 하자. &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;fst&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;snd&lt;/code&gt;를 재구성할 수 있는 &lt;code class=&quot;language-text&quot;&gt;m’&lt;/code&gt;을 찾을 수 있을까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&apos;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&apos;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 곱집합 후보에서 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;는 항상 &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;를 반환했지만, 우리는 이미 두 번째 요소가 &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt;인 쌍 또한 존재할 수 있다는 사실을 알고 있다. 결국 이에 따라 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;를 통해 &lt;code class=&quot;language-text&quot;&gt;snd&lt;/code&gt;를 재구성할 수는 없다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;두 번째 예제는 조금 다르다. 두 번째 예제는 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt; 중 하나를 실행한 이후에도 충분한 정보들을 유지하고 있지만, 이번에는 &lt;code class=&quot;language-text&quot;&gt;fst&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;snd&lt;/code&gt;를 인수분해하는 방법이 너무 많다는 것이 문제가 된다.&lt;/p&gt;
&lt;p&gt;두 번째 후보의 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;는 모두 3개의 구성요소 중 두 번째 요소를 무시하기 때문에 &lt;code class=&quot;language-text&quot;&gt;m&apos;&lt;/code&gt; 에 어떤 값을 넣어도 전부 말이 된다. 즉 아래와 같은 예시들이 있을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 또는&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;m&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 기타 등등...&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;정리해보자면 어떤 두 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;를 가지는 타입 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;가 주어졌을 때 이들을 인수분해할 수 있는 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;은 유일하게 존재해야하는 후보가 가장 적합한 곱집합 후보라고 볼 수 있다. 사실 이 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;은 단순히 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;를 하나의 쌍으로 결합하는 녀석이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러면 결국 데카르트 곱 &lt;code class=&quot;language-text&quot;&gt;(a, b)&lt;/code&gt;가 가장 최적의 선택이 되며, 결국 이는 어떠한 두 집합의 곱을 선택하는 것과 동일하므로 이러한 보편적 구성이 집합 카테고리 위에서 제대로 작동한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;자 이제 집합에 대한 것은 모두 잊어버리고, 동일한 보편적 구성을 이용하여 임의의 카테고리에서 두 대상에 대한 곱을 정의해보도록 하자. 이러한 곱이 항상 존재한다고 말하기는 어렵지만, 만약 존재한다면 독특하게 유일한 동형성(Isomorphism)을 가지게 된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 두 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 곱은 “두 투영 사상을 갖춘 대상 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;“이며, 다른 “두 투영 사상을 갖춘 대상 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt;“에 대해 그 투영 사상들을 인수분해하는 유일한 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;이 존재하는 경우를 의미한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt; 두 후보로부터 인수분해 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;을 생성하는 고차함수는 &lt;code class=&quot;language-text&quot;&gt;factorizer&lt;/code&gt;라고 불린다. 앞서 살펴본 예시의 경우에는 아래와 같은 함수가 될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;56-합coproduct&quot; style=&quot;position:relative;&quot;&gt;5.6 합(Coproduct)&lt;a href=&quot;#56-%ED%95%A9coproduct&quot; aria-label=&quot;56 합coproduct permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;카테고리의 모든 구성 요소들과 마찬가지로 곱(Product)에도 대응되는 개념이 존재하는데, 이를 반대곱(Coproduct) 또는 합이라고 한다. 앞서 살펴보았던 곱의 패턴에서 화살표를 반대로 하면 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;에서부터 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;로 향하는 두 개의 삽입 사상을 가진 대상 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;를 만들어볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 616px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d472bf852bdba883d0bdeac5212604c2/4ae3a/8.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7WWnDDlf/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAERASITH/2gAIAQEAAQUCphC1xeKfFTXH/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgMBAQAAAAAAAAAAAAAAAREAECECYf/aAAgBAQAGPwI6xFyjkDo+1//EABsQAQEBAAIDAAAAAAAAAAAAAAERABAxIVGB/9oACAEBAAE/IT4Svea3R9usECqHnVUY4mxWrx//2gAMAwEAAgADAAAAEMsP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHhABAAICAQUAAAAAAAAAAAAAAREhAFEQMUFhcZH/2gAIAQEAAT8Qb0EehuXvkgQGbFouL38wYggrtjzgQSBTExl5UggB64//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;8&quot; title=&quot;&quot; src=&quot;/static/d472bf852bdba883d0bdeac5212604c2/4ae3a/8.jpg&quot; srcset=&quot;/static/d472bf852bdba883d0bdeac5212604c2/0913d/8.jpg 160w,
/static/d472bf852bdba883d0bdeac5212604c2/cb69c/8.jpg 320w,
/static/d472bf852bdba883d0bdeac5212604c2/4ae3a/8.jpg 616w&quot; sizes=&quot;(max-width: 616px) 100vw, 616px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;이는 단지 곱의 패턴에서 화살표를 반대로 뒤집은 것 뿐이므로 랭킹 또한 역전된 형태를 띈다. 대상 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;가 삽입 사상 &lt;code class=&quot;language-text&quot;&gt;i’&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;j’&lt;/code&gt;를 갖춘 대상 &lt;code class=&quot;language-text&quot;&gt;c’&lt;/code&gt;보다 더 낫다고 이야기하려면, 삽입 사상을 인수분해하는 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;이 존재해야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;i&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;j&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;j&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 575px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/64afd72f0aa385b61631a29cde698ded/8c797/9.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 83.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAEDAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB9uaYxq6VYFB//8QAGRABAAMBAQAAAAAAAAAAAAAAAQACERIg/9oACAEBAAEFAnR7ldxNlB8//8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGxAAAQQDAAAAAAAAAAAAAAAAAAEQEiEgMWH/2gAIAQEABj8C4UXtllj/AP/EABsQAAIDAAMAAAAAAAAAAAAAAAABESExIJGh/9oACAEBAAE/IWyy3hF5bjaKJISyUiY++P8A/9oADAMBAAIAAwAAABCIxwD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAfEAACAgIBBQAAAAAAAAAAAAABESExAFFxIEFhgcH/2gAIAQEAAT8QhW0hlrzj6JUFFy64vBrbEotTg0Owv3lcDQhBbkl/On//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;9&quot; title=&quot;&quot; src=&quot;/static/64afd72f0aa385b61631a29cde698ded/8c797/9.jpg&quot; srcset=&quot;/static/64afd72f0aa385b61631a29cde698ded/0913d/9.jpg 160w,
/static/64afd72f0aa385b61631a29cde698ded/cb69c/9.jpg 320w,
/static/64afd72f0aa385b61631a29cde698ded/8c797/9.jpg 575w&quot; sizes=&quot;(max-width: 575px) 100vw, 575px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;이렇게 찾아낸 가장 잘 들어맞는 대상, 다른 패턴으로 연결되는 유일한 사상을 가지고 있는 대상을 합이라고 하며, 만약 카테고리 내에 합이 존재한다면 이 합은 카테고리 내에서 특정한 두 대상의 결합을 나타내는 유일한 방법을 제공한다는 것을 의미한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 두 대상 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 합은 두 개의 삽입 사상을 가진 대상 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;로 정의된다. 만약 다른 대상 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt; 또한 두 삽입 사상을 갖추고 있다면, &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;c&apos;&lt;/code&gt;로 향하는 유일한 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;이 존재하며, 이는 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;가 가진 삽입 사상 &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;j&lt;/code&gt;를 인수분해한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;집합의 카테고리에서 합은 두 집합의 서로소 합집합(Disjoint Union)이다. 집합 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 집합 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 서로소 합집합의 원소는 모두 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;의 원소이거나 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;의 원소이다. 만약 두 집합이 겹치는 경우, 서로소 합집합에는 겹치는 부분의 두 복사본이 포함된다. 즉, 서로소 합집합의 원소는 원본을 나타내는 식별자로 일종의 태그가 지정된 것이라고 생각해볼 수 있다.&lt;/p&gt;
&lt;p&gt;프로그래머에게는 타입 관점에서 합을 이해하는 것이 더 쉽게 다가올 수 있다. 이는 두 타입의 태그가 지정된 유니온(Tagged Union)이다. C++은 유니온을 지원하지만, 이들은 태그가 없다. 이는 프로그램에서 어떻게든 어떤 유니온 멤버가 유효한지, 어떻게 추적할지 관리해야 한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;태그가 지정된 유니온을 생성하려면 먼저 Enum(tag)을 정의하고 유니온과 결합해야한다. 예를 들어 &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;char const *&lt;/code&gt;의 태그가 지정된 유니온은 아래와 같이 구현해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Contact&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isPhone&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isEmail &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; tag&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; phoneNum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; emailAddr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 두 삽입 사상은 생성자 또는 함수로 구현할 수 있다. 예를 들어 첫 번째 삽입 사상을 함수 &lt;code class=&quot;language-text&quot;&gt;PhoneNum&lt;/code&gt;으로 구현해본다면 아래와 같을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;Contact &lt;span class=&quot;token function&quot;&gt;PhoneNum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Contact c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isPhone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phoneNum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 정수를 &lt;code class=&quot;language-text&quot;&gt;Contact&lt;/code&gt;에 삽입하는 역할을 한다.&lt;/p&gt;
&lt;p&gt;이렇게 태그가 지정된 유니온은 때로 변형(Variant)라고도 불리며, &lt;code class=&quot;language-text&quot;&gt;boost:variant&lt;/code&gt; 클래스 템플릿에서 이러한 변형에 대한 기능을 제공받을 수 있다.&lt;/p&gt;
&lt;p&gt;Haskell에서는 수직바(&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;)로 데이터 생성자를 구분하여 어떤 데이터 형식이든 태그가 지정된 유니온으로 결합할 수 있다. 방금 C++로 만들어본 &lt;code class=&quot;language-text&quot;&gt;Contact&lt;/code&gt;는 Haskell에서 아래와 같은 선언으로 표현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Contact&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PhoneNum&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EmailAddr&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;PhoneNum&lt;/code&gt; 과 &lt;code class=&quot;language-text&quot;&gt;EmailAddr&lt;/code&gt;은 생성자(삽입 사상)와 패턴 매칭에 대한 태그로 사용된다. 아직 잘 이해가 되지 않겠지만 이는 나중에 더 알아보도록 하겠다.&lt;/p&gt;
&lt;p&gt;예를 들어 전화번호를 사용하여 연락처를 생성하는 방법은 아래와 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;helpdesk&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Contact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;helpdesk&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PhoneNum&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2222222&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에 기본적으로 내장된 곱의 표준 구현과 다르게 합의 표준 구현은 &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;라는 데이터 타입이며, 이는 표준 Prelude에 정의되어있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 두 타입을 나타내는 매개변수와 두 생성자를 가진 데이터 타입이다. &lt;code class=&quot;language-text&quot;&gt;Left&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 타입의 값을 나타내며 &lt;code class=&quot;language-text&quot;&gt;Right&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; 타입의 값을 나타낸다.&lt;/p&gt;
&lt;p&gt;우리가 곱에 대해서 &lt;code class=&quot;language-text&quot;&gt;factorizer&lt;/code&gt;라는 함수로 정의한 것과 마찬가지로, 합에 대해서도 함수를 정의해볼 수 있다. 후보 대상인 &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;와 두 후보 삽입 사상 &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;j&lt;/code&gt;가 주어진다면, &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt;를 사용하여 함수를 만들어볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;factorizer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;57-비대칭성asymmetry&quot; style=&quot;position:relative;&quot;&gt;5.7 비대칭성(Asymmetry)&lt;a href=&quot;#57-%EB%B9%84%EB%8C%80%EC%B9%AD%EC%84%B1asymmetry&quot; aria-label=&quot;57 비대칭성asymmetry permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이렇게 쌍대성을 가진 두 개의 집합을 살펴보았다. 종결 대상의 정의는 초기 대상의 정의에서 화살표의 방향을 반대로 하여 얻을 수 있으며, 이와 유사하게 합의 정의는 곱의 정의를 뒤집음으로써 만들어볼 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 집합의 카테고리에서 초기 대상은 최종 대상과는 매우 다르며, 합 또한 곱과 다르다. 추후 우리는 곱셈처럼 작동하는 곱집합의 정의에서 종결 대상이 1의 역할을 하고, 덧셈처럼 작동하는 합집합의 정의에서는 초기 대상이 0의 역할을 하는 것을 살펴볼 것이다.&lt;/p&gt;
&lt;p&gt;특히 유한 집합의 경우 곱집합의 크기는 개별 집합의 크기를 곱한 것과 같으며, 합집합의 크기는 개별 집합의 크기를 더한 것과 같다. 이는 집합의 카테고리가 화살표의 반전에 대해서 대칭적으로 작동하지 않는다는 사실을 보여준다.&lt;/p&gt;
&lt;p&gt;여기서 주의해야 할 점은 공집합이 어떤 집합에 대해 고유한 사상(&lt;code class=&quot;language-text&quot;&gt;absured&lt;/code&gt; 함수)을 가질 수는 있지만, 이 사상에 대한 역사상은 존재하지 않는다는 것이다. 단일원소집합은 어떤 집합에서 자신에게로 향하는 고유한 사상을 가지고 있지만, 자신에게서 공집합을 제외한 다른 모든 집합으로 향하는 사상 또한 가지고 있다. 종결 대상에서부터 다른 곳으로 향하는 사상은 다른 집합의 원소를 선택하는 매우 중요한 역할을 하지만, 공집합에는 원소가 없기 때문에 선택할 수 있는 것이 없다.&lt;/p&gt;
&lt;p&gt;바로 이러한 단일원소집합과 곱집합의 관계가 합집합과의 차별점이다. Unit 타입 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt; 으로 표현되는 단일원소집합을 곱 패턴의 후보로 생각해보자. 그럼 이제 단일원소집합은 자신으로부터 구성 요소 집합으로 향하는 투영 사상 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt;를 가지게 된다.&lt;/p&gt;
&lt;p&gt;결국 이 두 사상들이 표현하고 있는 행위는 곱집합의 원소를 구성하는 구성요소 중 하나를 선택하는 것이다. 또한 곱집합은 보편적 구성을 따르기 때문에 우리가 정한 후보인 단일원소집합으로부터 곱집합으로 향하는 유일한 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;도 존재할 것이다. 이 사상은 곱집합에서 특정 원소, 즉 구체적인 하나의 쌍을 선택할 것이며, 이 사상으로 두 투영 사상을 인수분해할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이를 단일원소집합의 유일한 원소인 값 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;에 대입해보면 위의 식은 아래와 같이 변형될 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 &lt;code class=&quot;language-text&quot;&gt;m ()&lt;/code&gt;은 사상 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;에 의해 선택된 곱집합의 원소이므로 이 식들은 &lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;가 첫번째 집합에서 선택한 요소, 즉 &lt;code class=&quot;language-text&quot;&gt;p ()&lt;/code&gt;가 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;에 의해 선택된 쌍의 첫번째 구성요소와 동일하다는 것을 나타낸다. 마찬가지로 &lt;code class=&quot;language-text&quot;&gt;q ()&lt;/code&gt;는 두번째 구성요소와 동일할 것이다. 이는 곱집합의 원소가 각 구성 집합의 원소로 이루어진 쌍이라는 개념과 완전히 일치한다.&lt;/p&gt;
&lt;p&gt;하지만 합에 대해서는 이렇게 간단한 해석이 불가능하다. 물론 단일원소집합을 합의 후보로 삼아 원소를 추출하려고 해볼 수는 있겠지만, 여기에는 단일원소집합에서 다른 구성요소집합으로 향하는 두 투영 사상이 아니라 다른 구성요소집합에서 단일원소집합으로 향하는 두 삽입 사상이 필요하다. 하지만 이 삽입 사상들은 원본의 정보에 대해 아무것도 알려주지 않을 것이다. 이는 앞서 살펴본 삽입 사상의 &lt;code class=&quot;language-text&quot;&gt;factorizer&lt;/code&gt;의 구현을 보면 이 함수가 입력된 매개변수 중 하나를 무시하고 있다는 사실에서 알 수 있다. 마찬가지로 합집합에서 단일원소집합으로 향하는 유일한 사상도 아무런 정보를 주지 못한다.&lt;/p&gt;
&lt;p&gt;결국 집합의 카테고리는 초기 대상의 방향에서 바라볼 때와 종결 대상의 방향에서 바라볼 때 다르게 보일 수 있다는 것이다. 이것은 일반적으로 수학에서의 집합이 가지는 본질적인 특성이라기보다는 모든 집합이 대상으로 정의되는 카테고리 이론에서 사상으로 사용되는 함수의 특성이다.&lt;/p&gt;
&lt;p&gt;함수는 일반적으로 비대칭적이다. 함수는 정의역 집합의 모든 원소에 대해서 정의되어야 한다만, 공역 집합의 모든 원소에 대해 대응될 필요는 없다. 방금 우리는 이러한 함수의 특성 중 극단적인 몇 가지를 살펴본 것이다. 결국 단일원소집합을 정의역으로 가지는 함수들은 공역 집합에서 딱 하나의 원소만 선택하는 함수들이다.&lt;/p&gt;
&lt;p&gt;우리는 종종 정의역 집합의 크기가 공역 집합의 크기보다 훨씬 작을 때, 이러한 함수들이 정의역 집합을 공역 집합에 포함시키는 행위라고 생각한다. 예를 들어 우리는 단일원소집합을 정의역으로 가진 함수가 정의역 집합이 가진 단 하나의 원소를 공역 집합에 포함시키는 것이라고 생각할 수 있다. 필자는 이들을 포함 함수(Embedding Functions)라고 부르지만, 수학자들은 이와 반대 시각을 가진 개념을 통해 이름을 부여했다. 이렇게 정의역을 공역에 꽉 채워넣을 수 있는 함수들을 “전사 함수(Surjective Functions)” 또는 “위로의 함수(Onto Functions)”라고 한다.&lt;/p&gt;
&lt;p&gt;다른 비대칭성의 원인은 함수가 정의역 집합 있는 여러 원소들을 공역 집합에 있는 하나의 원소로도 매핑할 수 있다는 점이다. 즉 함수는 이러한 원소들을 축소할 수 있다고 보는 것이다. 이에 대한 극단적인 예시는 정의역 집합에 있는 모든 원소를 공역 집합의 단 하나의 원소로 매핑하는 함수들이다. 이전에 보았던 &lt;code class=&quot;language-text&quot;&gt;unit :: a -&gt; ()&lt;/code&gt;의 정의를 가진 다형적 유닛 함수(Polymorphic Unit Function)이 바로 이 역할을 한다. 이러한 축소 행위는 합성을 통해 더 강화될 수 있다. 두 개의 축소 함수를 합성하는 것은 각각의 개별 함수보다 더 많은 축소 행위를 만들어낼 수 있다. 수학자들은 이렇게 축소되지않는 함수에 대해서 특별한 이름을 붙혔는데, 이를 “단사 함수(Injective Functions)” 또는 “일대일 함수(One-to-one Functions)”라고 부른다.&lt;/p&gt;
&lt;p&gt;물론 이렇게 포함도 축소도 아닌 일부 함수들도 존재한다. 이들은 “전단사 함수(Bijection Functions)”라고 불린다. 이 함수들은 전사, 단사 함수와는 다르게 대칭적이며, 이에 따라 역함수도 존재할 수 있다. 집합의 카테고리에서는 동형사상(Isomorphism)이 전단사 함수와 동일한 개념이다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 4. 크라이슬리 카테고리]]></title><description><![CDATA[우리는 지금까지 타입과 순수 함수들을 카테고리로 모델링하는 방법을 살펴봤다. 앞서 필자는 카테고리 이론에서 사이드 이펙트나 순수하지 않은 함수를 모델링하는 방법이 있다고 이야기했었는데, 어떠한 실행과정을 추적하거나 로깅하는 함수를 예시로 들어 이 방법에 대해 한번 살펴보도록 하자.]]></description><link>https://evan-moon.github.io/2024/02/20/category-theory-for-programmers-4-kleisli-category/</link><guid isPermaLink="false">20240220-category-theory-for-programmers-4-kleisli-category</guid><pubDate>Tue, 20 Feb 2024 03:48:43 GMT</pubDate><content:encoded>&lt;p&gt;우리는 지금까지 타입과 순수 함수들을 카테고리로 모델링하는 방법을 살펴봤다. 앞서 필자는 카테고리 이론에서 사이드 이펙트나 순수하지 않은 함수를 모델링하는 방법이 있다고 이야기했었는데, 어떠한 실행과정을 추적하거나 로깅하는 함수를 예시로 들어 이 방법에 대해 한번 살펴보도록 하자.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;우리가 명령형 언어를 사용하여 무언가를 구현할 때는 일반적으로 전역 상태를 선언하고 변경해가며 구현하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;string logger&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
     logger &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Not so! &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 자신의 외부 세계에 선언되어있는 &lt;code class=&quot;language-text&quot;&gt;logger&lt;/code&gt;를 변경한다는 사이드이펙트를 가지고 있기 때문에 순수함수가 아니다.&lt;/p&gt;
&lt;p&gt;모던 프로그래밍의 세계에서는 가급적이면 변경 가능한 전역 상태를 사용하지 않기 위해 노력하는데, 다른 것은 둘째치고 동시성의 복잡성때문에라도 이러한 행위는 최대한 피해야 한다. 아마 독자 여러분도 이런 코드를 라이브러리에 넣고 싶지는 않을 것이라 생각한다.&lt;/p&gt;
&lt;p&gt;다행히도 이 함수는 순수함수로 변경될 수 있는 가능성이 있다. 그저 함수에게 &lt;code class=&quot;language-text&quot;&gt;logger&lt;/code&gt;를 명시적으로 전달하기만 하면 된다. 즉, 함수에 하나의 문자열 인수를 추가함으로써 함수의 출력과 로그가 포함된 문자열을 짝지어볼 수 있는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string logger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; logger &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Not so! &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 이 함수는 사이드 이펙트를 발생시키지 않기 때문에 순수하다. 동일한 인수가 주어졌을 때 항상 동일한 값의 쌍을 출력하며, 이러한 특성으로 인해 필요한 경우에는 메모이제이션 할 수도 있다. 그러나 메모이제이션을 할 경우 이전 값을 토대로 다음 값을 생성한다는 누산적인 로그의 특성으로 인해, 결국은 이 함수가 호출되기까지의 모든 이력을 메모이제이션해야 할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;It was the best of times. &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 또는&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;It was the worst of times. &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;여기서 작가는 누산적인 연산을 한다는 로그의 특성으로 인해 메모이제이션을 하나마나라는 이야기를 하고 있다. negate 함수는 “이전 로그”를 받아 “Not so! “라는 문자열을 이어붙히는 방식으로 새로운 로그 문자열을 생성하여 반환하는데, 이는 결국 negate 함수가 반환하는 로그 문자열이 negate 함수가 호출되기 이전의 로그 상태의 영향을 받는다는 의미이다.&lt;/p&gt;
&lt;p&gt;아무리 negate 함수가 참조 투명성을 보장하는 순수함수라도, 결국 함수의 호출 맥락이라는 것은 상황에 따라 달라질 수 있기 때문에 negate 함수가 반환하는 로그 문자열 또한 매번 달라질 가능성이 크다. 그로 인해 이를 메모이제이션하는 것은 큰 의미가 없어지는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이러한 설계는 라이브러리 함수로써 좋은 설계라고 볼 수도 없다. 함수 호출자는 이 함수가 반환하는 로그 문자열을 무시할 수 있으니 출력 형태에 대해서는 큰 문제가 없겠지만, 입력에 대해서는 다르다. 로그가 필요없는 상황에도 매번 호출자가 특정한 로그 문자열을 함수에게 직접 전달해줘야 하기 때문이다.&lt;/p&gt;
&lt;p&gt;그렇다면 관심사를 분리하는 방법을 통해 이 함수를 조금 더 편하게 호출할 수 있는 방법은 없을까? 결국 위 예시에서 negate 함수의 주 목적은 인수로 받은 하나의 Boolean 값을 다른 Boolean 값으로 변환하는 것이며, 로깅은 그저 보조적인 역할만 수행한다. 물론 이 로그에 기록되는 메세지가 함수의 목적에 특화되어 있기는 하지만, 결국 어떠한 메세지를 하나의 로그로 통합하는 작업 자체는 negate 함수의 주 목적과는 별개의 관심사이다. 즉, 우리는 로깅에 대한 관심사를 분리해야 한다.&lt;/p&gt;
&lt;p&gt;그렇다면 이런 방법으로 타협을 볼 수 있을 것 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Not so! &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 이 아이디어는 함수가 호출될 때마다 로그를 계속 쌓는다는 컨셉에서 출발한다. 이제 이 아이디어를 어떻게 구현할 수 있을지 알아보기 위해 약간 더 현실적인 예제를 보도록하자.&lt;/p&gt;
&lt;p&gt;여기 어떤 문자열을 받아 소문자를 대문자로 변경하는 함수가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;string &lt;span class=&quot;token function&quot;&gt;toUpper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    string result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;toupperp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;toupper&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// toupper is overloaded&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;back_inserter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toupperp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 두번째 함수는 인수로 받은 문자열을 공백을 기준으로 나누어 벡터를 반환한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toWords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;toWords&lt;/code&gt; 함수의 실제 동작은 &lt;code class=&quot;language-text&quot;&gt;words&lt;/code&gt; 함수에서 수행된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isspace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;back&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 &lt;code class=&quot;language-text&quot;&gt;toUpper&lt;/code&gt; 함수와 &lt;code class=&quot;language-text&quot;&gt;toWords&lt;/code&gt; 함수를 수정하여 문자열 메세지를 이 함수들의 반환값과 함께 묶어 표현하고 싶다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/01933c7eafd8f72afd7f176b92dbd607/f93b5/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 106.87500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAVABQDASIAAhEBAxEB/8QAGQABAAIDAAAAAAAAAAAAAAAAAAMFAQIE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAbblngSyC41CQH//xAAbEAACAgMBAAAAAAAAAAAAAAABAgMRABASIv/aAAgBAQABBQKVqwSt0DYkj9MrYBQYWOBr/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAgEFAQAAAAAAAAAAAAAAAREAAhASIWEy/9oACAEBAAY/Ava5A2LCqlDe3AMwYooOW//EAB4QAAICAgIDAAAAAAAAAAAAAAERACExQRBhcYGx/9oACAEBAAE/IVXg03CwWsFK4JwIPiKNuwIZaidfYIYagXH6iaV04//aAAwDAQACAAMAAAAQtA88/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHhABAQACAgIDAAAAAAAAAAAAAREAMSFBYXEQgaH/2gAIAQEAAT8QhUlUC8usmlWJB+3XnBhjVVL3iSBF0F6d/nnOM1+Lt9nzkRIJqYjQDusGIVogL7+P/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/01933c7eafd8f72afd7f176b92dbd607/f93b5/1.jpg&quot; srcset=&quot;/static/01933c7eafd8f72afd7f176b92dbd607/0913d/1.jpg 160w,
/static/01933c7eafd8f72afd7f176b92dbd607/f93b5/1.jpg 300w&quot; sizes=&quot;(max-width: 300px) 100vw, 300px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;우리는 이제 이 함수들의 반환값을 아름답게 꾸며볼 것이다. 가장 먼저 임의의 타입 A인 값이 첫 번째 요소이고 문자열이 두 번째 요소인 쌍을 캡슐화하는 템플릿 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt;를 정의함으로써 이 문제를 일반화하겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; Writer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt;를 사용하여 각 함수들을 꾸며줄 차례이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toUpper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    string result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;toupperp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;toupper&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;back_inserter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toupperp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;toUpper &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toWords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;toWords &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 이 두 함수를 조합하여 문자열을 대문자로 변환하고 공백을 기준으로 나눠주는 함수를 꾸며보자. 바로 이 과정에서 이 작업에 대한 로그를 생성할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toUpper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toWords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 처음의 목표를 달성했다. 각각의 로그를 합치는 것은 이제 더 이상 개별 함수들의 관심사가 아니다. 각 함수들은 자체적으로 자신과 관련된 메세지를 생성할 뿐이고, 이 개별 함수들의 외부에서 이러한 메세지들을 합쳐 더 큰 로그를 만들어낸다.&lt;/p&gt;
&lt;p&gt;이제 이러한 스타일로 작성된 거대한 프로그램을 한번 상상해보자. 아마 이러한 패턴을 계속해서 반복하게되면 오류가 발생하기 쉬운 악몽과도 같은 코드가 될 것이다. 하지만 우리는 프로그래머이기 때문에 이런 반복적인 코드를 추상화를 사용하여 우아하게 해결하는 일에 이미 익숙하다. 그러나 이것은 우리가 지금까지 알던 추상화와는 약간 다르다. 바로 함수의 합성이라는 개념 자체를 추상화해야하기 때문이다.&lt;/p&gt;
&lt;p&gt;결국 합성이라는 개념은 카테고리 이론의 본질이니, 코드를 더 작성하기 전에 일단 카테고리 이론의 관점에서 이 문제를 한번 분석해보자.&lt;/p&gt;
&lt;h2 id=&quot;41-writer-카테고리&quot; style=&quot;position:relative;&quot;&gt;4.1 Writer 카테고리&lt;a href=&quot;#41-writer-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%AC&quot; aria-label=&quot;41 writer 카테고리 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;함수들의 반환 타입을 꾸며 추가 기능을 끼워넣을 수 있다는 아이디어는 우리에게 큰 가치를 가져다준다. 이제 이에 대한 더 많은 예제를 한번 보도록 하자. 대상을 타입으로 가지고 사상은 우리가 꾸며주었던 함수로 가지는 일반적인 카테고리에서부터 시작해보는 것이 좋겠다.&lt;/p&gt;
&lt;p&gt;예를 들어 &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt; 타입에서 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt; 타입으로 향하는 &lt;code class=&quot;language-text&quot;&gt;isEven&lt;/code&gt; 함수를 꾸며본다고 생각해보자. 가장 먼저 카테고리의 사상을 우리가 앞서 꾸며보았던 함수로 다시 표현해볼 것이다. 여기서 중요한 점은 이 함수가 비록 &lt;code class=&quot;language-text&quot;&gt;pair&amp;lt;bool, string&gt;&lt;/code&gt; 타입을 반환한다고 해도 카테고리 내에서는 여전히 &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt; 대상과 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt; 대상 사이의 화살표로 간주된다는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isEven&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;isEven &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;카테고리 법칙에 의하면 우리는 이 사상을 다른 사상과 합성하여 대상 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;에서 다른 대상으로 향하는 사상을 만들 수 있어야 한다. 여기서는 앞서 정의했던 &lt;code class=&quot;language-text&quot;&gt;negate&lt;/code&gt; 함수와 합성하는 상황을 한번 보도록 하겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Not so! &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 &lt;code class=&quot;language-text&quot;&gt;isEven&lt;/code&gt; 함수와 &lt;code class=&quot;language-text&quot;&gt;negate&lt;/code&gt; 함수는 서로의 입력과 출력 타입이 일치하지 않기 때문에 이 두 개의 사상을 일반적인 함수와 같은 방식으로 합성할 수는 없다. 이 두 사상의 합성은 아래와 같이 표현해줘야 할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isOdd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isEven&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;negate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 카테고리에서 두 개의 사상을 합성하는 과정은 다음과 같다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;첫 번째 사상에 해당하는 함수를 실행시킨다. 위 예시에서는 &lt;code class=&quot;language-text&quot;&gt;isEven(n)&lt;/code&gt;에 해당한다.&lt;/li&gt;
&lt;li&gt;첫 번째 함수가 반환한 값의 쌍에서 첫 번째 요소를 추출하고, 이 요소를 두 번째 사상에 해당하는 함수에 전달한다. 위 예시에서는 &lt;code class=&quot;language-text&quot;&gt;negate(p1.first)&lt;/code&gt;에 해당한다.&lt;/li&gt;
&lt;li&gt;첫 번째 사상과 두 번째 사상이 반환한 로그 문자열, 즉 각 함수가 반환한 쌍에서 두 번째 요소를 추출하여 직접 연결해준다.&lt;/li&gt;
&lt;li&gt;위 과정을 통해 얻어낸 값과 연결한 로그 문자열을 사용하여 새로운 쌍을 만들어 반환한다. 위 예시에서는 &lt;code class=&quot;language-text&quot;&gt;make_pair(p2.first, p1.second + p2.second)&lt;/code&gt;에 해당한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;만약 이 과정을 C++의 고차함수로 추상화하려면 이 카테고리가 가진 세 개의 대상을 타입 변수로 표현한 템플릿을 사용해야한다. 그리고 결과값과 로그 문자열 쌍을 반환하는 두 개의 함수를 가져와 합성하고, 마지막으로 새로운 쌍을 만드는 함수를 반환하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Writer&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Writer&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; m1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                               function&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Writer&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;B&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; m2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;m1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; m2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;m1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;m2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기까지 왔으면 이제 거의 끝났다. 이제 이 템플릿을 사용하여 원래 우리가 합성하려고 했던 &lt;code class=&quot;language-text&quot;&gt;toUpper&lt;/code&gt; 함수와 &lt;code class=&quot;language-text&quot;&gt;toWords&lt;/code&gt; 함수의 합성을 구현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toUpper&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toWords&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 아직도 &lt;code class=&quot;language-text&quot;&gt;compose&lt;/code&gt; 템플릿에 타입을 전달하는 과정이 번거로워 보인다. 이는 C++14 호환 컴파일러에서 지원하는 반환 타입 추론 기능을 지원하는 람다 함수를 사용함으로써 해결해볼 수 있다. (아래 코드의 작성자는 Eric Niebler이다.)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; compose &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; m1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; m2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;m1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; m2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;m1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;m2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; p2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 타입 추론을 지원하도록 정의된 &lt;code class=&quot;language-text&quot;&gt;compose&lt;/code&gt; 함수를 사용하여 함수를 더 간단하게 합성해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toUpper&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toWords&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;아직 끝난 것이 아니다. 우리는 지금까지 카테고리 내 사상의 합성만 정의한 것이고 아직 항등 사상에 대한 것은 정의하지 않았다. 이 항등 사상은 일반적인 항등 함수와는 약간 다르다. 이들은 타입 A로부터 다시 타입 A로 돌아가는 사상이기 때문에 아래와 같은 타입 선언을 가질 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 항등 사상은 합성에 대한 항등원처럼 작동해야한다. 우리가 정의해놓은 로직의 합성 과정에 의하면 이 항등 사상은 자신이 인수로 받은 값을 변경하지도 않고, 로그에는 빈 문자열만 기록하는 방식으로 정의해야 할 것 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Writer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 정의한 카테고리는 카테고리가 지켜야하는 모든 조건들을 만족하고 있다. 특히 이 카테고리의 합성은 명확하게 결합법칙을 만족하고 있다. 각 함수들이 반환하는 값의 쌍 중 첫 번째 요소만 보면 일반적인 함수의 합성으로 바라볼 수 있으며, 이 연산은 결합법칙을 만족한다. 또한 두 번째 요소인 로그 문자열에 대한 연산은 그저 문자열의 연결일 뿐이니 이 또한 결합법칙을 만족한다.&lt;/p&gt;
&lt;p&gt;여기서 영리한 독자라면 우리가 이 구조를 문자열 모노이드 뿐 아니라 어떤 모노이드에던 일반화해서 적용할 수 있다는 사실을 알아차렸을 것이다. &lt;code class=&quot;language-text&quot;&gt;compose&lt;/code&gt; 함수에서 &lt;code class=&quot;language-text&quot;&gt;+&lt;/code&gt; 연산자 대신 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;를, 그리고 &lt;code class=&quot;language-text&quot;&gt;identity&lt;/code&gt; 함수에서는 &lt;code class=&quot;language-text&quot;&gt;&quot;&quot;&lt;/code&gt;라는 값 대신에 &lt;code class=&quot;language-text&quot;&gt;mempty&lt;/code&gt;를 사용하기만 하면 된다.&lt;/p&gt;
&lt;p&gt;반드시 문자열을 다룰 때에만 한해서 로깅을 한다는 법은 없다. 좋은 라이브러리 작성자는 라이브러리가 동작하는 데 필요한 최소한의 제약 조건을 식별할 수 있어야 한다. 우리가 만든 로깅 라이브러리의 유일한 요구 사항은 그저 로그라는 개념이 모노이드적인 특성을 가져야 한다는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;42-하스켈의-writer&quot; style=&quot;position:relative;&quot;&gt;4.2 하스켈의 Writer&lt;a href=&quot;#42-%ED%95%98%EC%8A%A4%EC%BC%88%EC%9D%98-writer&quot; aria-label=&quot;42 하스켈의 writer permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 구현했던 것들을 Haskell에서는 조금 더 간결하게 작성할 수 있고 컴파일러로부터 더 많은 도움을 받을 수 있기도 하다.&lt;/p&gt;
&lt;p&gt;일단 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 타입을 정의하는 것부터 시작해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서는 단순히 타입 별칭(Type Alias)을 정의하고 있으며, 이것은 C++의 &lt;code class=&quot;language-text&quot;&gt;typedef&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;using&lt;/code&gt;과 동일한 기능이다. &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 타입은 타입 변수 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;를 받아 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 타입과 &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt; 타입의 쌍을 반환한다. 이 문법은 쌍을 의미하는 괄호 안에 두 개의 요소가 존재하고, 이 요소들이 쉼표로 부분되는 최소한의 형태로만 이루어져있다.&lt;/p&gt;
&lt;p&gt;이 카테고리에서의 사상은 임의의 타입에서 다른 타입을 매개변수로 가지는 &lt;code class=&quot;language-text&quot;&gt;Writer&lt;/code&gt; 타입으로 나아가는 함수라고 볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 “fish”라고도 불리는 재미있는 중위 연산자(Infix Operator)를 사용하여 합성을 정의할 차례이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;=&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 연산자는 두 개의 인수를 받아 합성하는 함수이며, 이 인수들은 합성의 대상이 되는 함수들이고 최종적으로는 합성된 함수를 반환한다. 첫 번째 인수는 &lt;code class=&quot;language-text&quot;&gt;(a -&gt; Writer b)&lt;/code&gt; 타입, 두 번째 인수는 &lt;code class=&quot;language-text&quot;&gt;(b -&gt; Writer c)&lt;/code&gt; 타입이며, 최종 반환 결과는 &lt;code class=&quot;language-text&quot;&gt;(a -&gt; Writer c)&lt;/code&gt; 타입을 가진다.&lt;/p&gt;
&lt;p&gt;아래 예시는 &lt;code class=&quot;language-text&quot;&gt;m1&lt;/code&gt; 이라는 인수와 &lt;code class=&quot;language-text&quot;&gt;m2&lt;/code&gt;라는 인수를 받았을 때 이 중위 연산자가 어떻게 작동하는지를 보여준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;m1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m2&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;연산의 결과는 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;라는 하나의 인수를 받는 람다 함수이다. 람다 함수는 역슬래시(&lt;code class=&quot;language-text&quot;&gt;\&lt;/code&gt;)로 표현할 수 있다. 기억하기 어렵다면 다리를 하나 잃은 그리스 문자 λ(Lambda)라고 생각하자.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;let&lt;/code&gt; 표현을 사용하면 함수 내의 지역변수를 선언할 수 있다. 여기서 &lt;code class=&quot;language-text&quot;&gt;m1&lt;/code&gt; 함수의 호출 결과는 &lt;code class=&quot;language-text&quot;&gt;(y, s1)&lt;/code&gt; 변수에 담기고, 이 변수에서 가져온 &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt; 인자를 사용하여 호출된 &lt;code class=&quot;language-text&quot;&gt;m2&lt;/code&gt; 함수의 호출 결과는 &lt;code class=&quot;language-text&quot;&gt;(z, s2)&lt;/code&gt; 변수에 담긴다.&lt;/p&gt;
&lt;p&gt;이처럼 Haskell에서는 C++에서 &lt;code class=&quot;language-text&quot;&gt;p1.first&lt;/code&gt; 같이 접근자를 사용했던 것과는 다르게, &lt;code class=&quot;language-text&quot;&gt;(y, s1) = m1 x&lt;/code&gt; 처럼 패턴 매칭하여 쌍을 분해하는 방법을 주로 사용한다. 이 외에도 두 언어의 기능 간에는 이렇게 직관적으로 대응해볼 수 있는 관계가 꽤 존재한다.&lt;/p&gt;
&lt;p&gt;위 함수의 &lt;code class=&quot;language-text&quot;&gt;let&lt;/code&gt; 표현식에서 선언된 변수들은 함수 동작의 구현을 의미하는 &lt;code class=&quot;language-text&quot;&gt;in&lt;/code&gt;절에서 접근할 수 있다. 즉 &lt;code class=&quot;language-text&quot;&gt;in&lt;/code&gt;절 내부에서 접근한 변수들은 &lt;code class=&quot;language-text&quot;&gt;let&lt;/code&gt; 표현식 내부에서 선언된 값들이며, 최종적으로 첫 번째 요소는 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt; 이고, 두 번째 요소는 두 문자열의 연결인 &lt;code class=&quot;language-text&quot;&gt;s1 ++ s2&lt;/code&gt;로 구성된 쌍을 만들어내고 이쓴 것이다.&lt;/p&gt;
&lt;p&gt;이런 합성 외에도 우리의 카테고리 내부에 존재해야하는 항등 사상도 정의를 해야하겠지만 이건 조금 이따 보도록 하겠다. 일단 항등사상은 &lt;code class=&quot;language-text&quot;&gt;return&lt;/code&gt; 이라고 네이밍하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;자 이제 원래 합성하려고 했던 대상인 &lt;code class=&quot;language-text&quot;&gt;upCase&lt;/code&gt; 와 &lt;code class=&quot;language-text&quot;&gt;toWords&lt;/code&gt; 함수의 Haskell 버전을 추가하면 거의 다 완성된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;upCase&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;upCase&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toUpper&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;upCase &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;toWords&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;toWords&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;toWords &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; 함수는 C++의 &lt;code class=&quot;language-text&quot;&gt;transform&lt;/code&gt;에 해당한다. 이 함수는 문자열 &lt;code class=&quot;language-text&quot;&gt;s&lt;/code&gt; 에 &lt;code class=&quot;language-text&quot;&gt;toUpper&lt;/code&gt; 함수를 적용한다. 그리고 &lt;code class=&quot;language-text&quot;&gt;words&lt;/code&gt; 함수는 표준 Prelude 라이브러리에 이미 정의되어있다.&lt;/p&gt;
&lt;p&gt;최종적으로 이 두 함수의 합성은 앞서 정의했던 fish 연산자를 사용하여 간단하게 표현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;process&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;process&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;upCase&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;toWords&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;43-크라이슬리-카테고리kleisli-categories&quot; style=&quot;position:relative;&quot;&gt;4.3 크라이슬리 카테고리(Kleisli Categories)&lt;a href=&quot;#43-%ED%81%AC%EB%9D%BC%EC%9D%B4%EC%8A%AC%EB%A6%AC-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%ACkleisli-categories&quot; aria-label=&quot;43 크라이슬리 카테고리kleisli categories permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사실 이러한 카테고리는 필자가 직접 고안해낸 것이 아니다. 이는 모나드라는 개념에서 기반한 크라이슬리 카테고리(Kleisli Category)의 한 예시이다. 아직 우리가 모나드에 대해 자세히 논의하기에는 조금 이르긴 하지만, 모나드가 어떤 역할을 하는지에 대해서 간략하게 살펴봤다고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;크라이슬리 카테고리는 프로그래밍 언어의 타입들을 대상으로 가진다. 그리고 타입 A에서 타입 B로 나아가는 사상은 타입 A에서 특정 “장식(Embellishment)”를 적용하여 B로 나아가는 함수라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;모든 크라이슬리 카테고리는 이러한 사상들을 고유한 방법으로 합성하는 방법을 정의하고, 이러한 합성에 대한 항등 사상 또한 정의할 수 있다. (추후 이 애매한 “장식”이라는 용어가 카테고리의 엔도펑터(Endofunctor)라는 개념을 의미한다는 사실을 설명하겠다.)&lt;/p&gt;
&lt;p&gt;이 챕터에서 함수들의 실행 과정을 추적하고 로깅하기 위해 만들었던 Writer 모나드는 순수함수들의 연산 결과에 이펙트를 포함하기 위한 일반적인 매커니즘의 예시이기도 하다.&lt;/p&gt;
&lt;p&gt;우리는 이전 챕터에서 프로그래밍 언어에서 bottom을 제외한 일반 타입들과 함수들을 집합으로 구성된 카테고리로 모델링하는 방법에 대해서 알아봤다. 그리고 이번에는 이 모델을 기반으로 함수들의 합성이라는 행위가 단지 한 함수의 출력을 다른 함수의 입력으로 전달하는 것뿐 아니라 조금 더 다양한 기능을 포함할 수 있는 카테고리로 발전시켜보았다.&lt;/p&gt;
&lt;p&gt;이제 우리는 함수의 합성을 가지고 놀 때 조금 더 자유로운 아이디어를 표현해볼 수 있게 되었다. 바로 우리가 앞서 알아본 개념들이 지금까지 명령형 언어들이 사이드이펙트를 사용하여 구현해왔던 프로그램에도 표시적 의미론(Denotational Semantics)을 적용할 수 있는 자유를 선물해준 것이다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 3. 다양한 카테고리들]]></title><description><![CDATA[우리는 다양한 예시들을 연구해보면서 카테고리에 대한 진정한 이해에 한발짝 더 다가갈 수 있다. 카테고리는 매우 다양한 형태와 크기를 가지고 있기 때문에 종종 전혀 예상하지 못 했던 곳에서 나타나기도 한다. 일단 가장 간단한 것부터 한번 시작해보도록 하자.]]></description><link>https://evan-moon.github.io/2024/02/13/category-theory-for-programmers-3-categories-great-and-small/</link><guid isPermaLink="false">20240213-category-theory-for-programmers-3-categories-great-and-small</guid><pubDate>Tue, 13 Feb 2024 09:09:06 GMT</pubDate><content:encoded>&lt;p&gt;우리는 다양한 예시들을 연구해보면서 카테고리에 대한 진정한 이해에 한발짝 더 다가갈 수 있다. 카테고리는 매우 다양한 형태와 크기를 가지고 있기 때문에 종종 전혀 예상하지 못 했던 곳에서 나타나기도 한다. 일단 가장 간단한 것부터 한번 시작해보도록 하자.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;31-대상이-없는-경우&quot; style=&quot;position:relative;&quot;&gt;3.1 대상이 없는 경우&lt;a href=&quot;#31-%EB%8C%80%EC%83%81%EC%9D%B4-%EC%97%86%EB%8A%94-%EA%B2%BD%EC%9A%B0&quot; aria-label=&quot;31 대상이 없는 경우 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;가장 간단한 카테고리는 어떠한 대상이나 사상을 전혀 가지고 있지 않는 카테고리이다. 이 카테고리만 따로 떼놓고 본다면 별로 쓸모가 없어보이겠지만 다른 카테고리와의 관계에서는 매우 중요한 의미를 가질 수도 있다. 예를 들면 모든 카테고리를 대상으로 가진 카테고리와 빈 카테고리의 관계 같은 것들이 있다. 상상하기 어렵겠지만 이런 카테고리도 분명 존재한다. 만약 여러분이 공집합의 존재 의의에 공감한다면 빈 카테고리도 나름의 의미가 있지 않을까?&lt;/p&gt;
&lt;h2 id=&quot;32-단순한-그래프&quot; style=&quot;position:relative;&quot;&gt;3.2 단순한 그래프&lt;a href=&quot;#32-%EB%8B%A8%EC%88%9C%ED%95%9C-%EA%B7%B8%EB%9E%98%ED%94%84&quot; aria-label=&quot;32 단순한 그래프 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;우리는 단순히 어떠한 대상을 화살표로 연결하는 것만으로도 카테고리를 만들어볼 수 있다. 한번 임의의 유향 그래프(Directed Graph)에 몇 개의 화살표를 추가하여 카테고리를 만드는 상상을 해보자. 먼저 그래프의 각 노드에 특정 대상으로부터 나와서 다시 자기 자신에게 돌아가는 항등 화살표를 추가한다. 그 다음 한 화살표의 종점 노드가 다른 화살표의 시작 노드와 일치하는 경우에는 이 두 화살표가 합성 가능하다는 사실을 의미하므로, 그 화살표들의 합성을 의미하는 새로운 화살표를 추가한다.&lt;/p&gt;
&lt;p&gt;항등 화살표를 제외하면 우리는 항상 새로운 화살표를 추가할 때마다 추가된 화살표와 다른 화살표들과의 합성 여부에 대한 것들을 고려해야 한다. 이러다보면 무한히 많은 화살표들이 생기겠지만 뭐 딱히 문제는 없다.&lt;/p&gt;
&lt;p&gt;즉 이러한 과정을 통해 우리는 모든 그래프의 노드들은 대상을, 그리고 간선은 합성 가능한 사상을 표현하는 일종의 카테고리를 만들었다고 볼 수 있다. (항등 사상의 경우에는 길이가 0인 특별한 간선이라고 볼 수 있다.)&lt;/p&gt;
&lt;p&gt;이렇게 미리 주어진 그래프에서부터 생성된 카테고리는 자유 카테고리(Free Category)라고 불린다. 즉, 미리 주어진 구조에 최소한의 항목만을 추가하여 원하는 법칙을 만족시킬 수 있는 일종의 자유 구성인 것이다. 여기서 우리가 원하는 법칙이란 결국 카테고리의 법칙일 것이다. 이와 관련된 자세한 내용은 추후 더 알아보도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;33-차수&quot; style=&quot;position:relative;&quot;&gt;3.3 차수&lt;a href=&quot;#33-%EC%B0%A8%EC%88%98&quot; aria-label=&quot;33 차수 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자 그러면 이제 완전히 다른 예시를 한번 살펴보자. 이번 카테고리는 대상들간의 사상이 “작거나 같음”으로 나타나는 관계를 가진 카테고리이다.&lt;/p&gt;
&lt;p&gt;먼저 이것이 정말 카테고리가 될 수 있는지부터 확인해보자. 항등 사상이 존재하는가? 모든 대상은 자기 자신보다 작거나 같으므로 답은 참이다. 사상의 합성은 존재하는가? 만약 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a≤b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7719em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b≤c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8304em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a≤c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7719em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;일테니 답은 참이다. 합성 간의 결합법칙은 적용되는가? 이도 참이다. 이와 같은 관계를 가진 집합은 원순서(Preorder)라고 하는데, 원순서 집합 또한 카테고리의 모든 조건을 만족시키므로 원순서 집합도 카테고리라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;그럼 여기에 몇 가지 조건을 추가하여 더 강한 관계를 만들어보자. 만약 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a≤b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7719em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b≤a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8304em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 같을 수 밖에 없는 경우도 있다. 이러한 관계는 부분순서(Partial Order)라고 한다.&lt;/p&gt;
&lt;p&gt;또한 우리는 어떠한 두 대상이 서로 상호 관계를 가진다는 조건도 부여할 수 있다. 이 경우에는 전순서(Linear Order 또는 Total Order)라는 개념을 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;자 그럼 이제 이 순서 집합들을 한번 카테고리로 표현해보도록 하자. 원순서 집합은 어떤 대상 a에서 다른 대상 b로 향하는 사상이 최대 1개만 존재하는 카테고리이다. 이러한 카테고리는 “Thin”하다고 표현하며, 원순서 집합은 Thin 카테고리라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;어떠한 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 가진 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 사상들의 집합은 Hom 집합(Hom-set)이라고 하며, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C(a,b)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;또는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Hom_c(a,b)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Ho&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라고 표기한다.&lt;/p&gt;
&lt;p&gt;즉, 원순서 집합에 속한 모든 Hom 집합은 공집합이거나 하나의 원소만을 가지는 단일원소집합이다. 이는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C(a,a)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 표현되는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 향하는 사상 집합인 항등사상 집합 또한 예외는 아니며, 이 집합은 어떤 원순서 집합 내에서도 단 하나의 원소, 즉 항등사상(identity) 하나만을 가지고 있다.&lt;/p&gt;
&lt;p&gt;이러한 원순서 내에서는 한 대상에서 시작한 여러 사상을 거쳐 동일한 대상으로 돌아오는 사이클이라는 개념이 성립할 수 있지만, 부분순서 내에서는 이러한 사이클이 성립될 수 없다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;원순서와 다르게 부분순서는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a≤b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7719em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b≤a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8304em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라면 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 같다는 반대칭관계를 만족해야한다. 대상이 a,b 밖에 없는 카테고리를 상상해보자. 사이클이라는 개념이 성립하려면 a→b로 향하는 사상과 b→a로 향하는 사상이 존재해야 한다. 원순서는 a→b로 향하는 사상과 b→a로 향하는 사상이 있다고 해서 이 두 대상을 같은 것이라고 정의하지 않아도 되지만, 부분순서는 반대칭관계를 만족해야하기 때문에 반드시 a=b가 되어버린다.&lt;/p&gt;
&lt;p&gt;즉, a와 b가 다른 대상이 될 수가 없으므로 사이클을 정의할 수가 없다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;정렬 문제와 같은 일상적인 문제를 해결할 때 퀵 정렬, 버블 정렬, 병합 정렬과 같은 정렬 알고리즘은 오직 전순서에서만 제대로 작동하며 부분순서에서는 위상 정렬 알고리즘을 사용해야 하기 때문에 어떠한 카테고리가 원순서인지 부분순서인지 또는 전순서인지를 알아내는 능력은 프로그래머에게 매우 중요하다고 할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;34-집합으로써의-모노이드&quot; style=&quot;position:relative;&quot;&gt;3.4 집합으로써의 모노이드&lt;a href=&quot;#34-%EC%A7%91%ED%95%A9%EC%9C%BC%EB%A1%9C%EC%8D%A8%EC%9D%98-%EB%AA%A8%EB%85%B8%EC%9D%B4%EB%93%9C&quot; aria-label=&quot;34 집합으로써의 모노이드 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;모노이드(Monoid)는 굉장히 간단하지만 놀라울 정도로 강력한 개념이다. 모노이드는 덧셈과 곱셈과 같은 기본적인 산술 연산의 기반이 되는 개념이며, 문자열, 리스트, Fold 연산이 가능한 구조, 동시성 프로그래밍에서의 Future, 함수형 반응형 프로그래밍에서의 이벤트 등 다양한 프로그래밍 기법에서도 빈번하게 사용되는 개념이다.&lt;/p&gt;
&lt;p&gt;전통적으로 모노이드는 이항연산을 가진 집합으로 정의된다. 이 이항연산은 결합법칙을 만족시켜야 하며, 이 연산에 대해서 항등원과 같은 역할을 하는 특별한 원소가 하나 있어야 한다. 예를 들어 0을 포함하는 자연수 집합(&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;N&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbb{N}_0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbb&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)은 덧셈에 대해 모노이드를 이룬다.&lt;/p&gt;
&lt;p&gt;결합법칙은 아래와 같은 특성을 의미한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(a + b) + c = a + (b + c)&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이건 다른 말로 하면 수를 더할 때 식 내에 있는 괄호를 생략해도 괜찮다는 의미이다. 그리고 덧셈에 대한 항등원은 0인데, 이 또한 결합법칙을 통해 간단하게 확인해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;0 + a = a
a + 0 = a&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 두 번째 식은 결국 첫 번째 식과 같은 의미이다. 덧셈은 &lt;code class=&quot;language-text&quot;&gt;a + b = b + a&lt;/code&gt; 와 같은 교환법칙도 만족하는 연산이기 때문이다. 하지만 교환법칙은 모노이드에서 반드시 만족시켜야 하는 대상은 아니다.&lt;/p&gt;
&lt;p&gt;예를 들어 문자열 연결 연산(Concatenation)의 경우 교환법칙을 만족하지 않지만 모노이드이다. 문자열 연결 연산의 항등원은 빈 문자열이고 이는 문자열의 어느 쪽에 가져다 붙여도 문자열을 변경하지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;Haskell에서는 모노이드에 대한 타입 클래스를 정의할 수 있다. 이는 &lt;code class=&quot;language-text&quot;&gt;mempty&lt;/code&gt;라고 불리는 항등원과 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;라고 불리는 이항연산을 정의한 타입이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;mempty&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;mappend&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;지금은 두 개의 인자를 받는 함수를 &lt;code class=&quot;language-text&quot;&gt;m-&gt;m-&gt;m&lt;/code&gt; 이라는 타입으로 표현한 것이 조금 어색하게 보일 수 있겠지만, 이건 나중에 커링(Currying)에 대해서 배우면 완벽하게 이해할 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 여러 화살표가 있는 타입 선언은 보통 두 가지 방식으로 해석해볼 수 있다. 첫째로는 오른쪽에 있는 타입이 반환 타입이 되는 다인수 함수로 해석할 수 있으며, 두 번째로는 가장 왼쪽에 있는 첫 번째 인수를 받아 함수를 반환하는 함수로도 해석해볼 수 있다. 후자의 해석은 &lt;code class=&quot;language-text&quot;&gt;m -&gt; (m -&gt; m)&lt;/code&gt; 처럼 괄호를 추가해서 강조해볼 수는 있지만, 사실 애초에 연산순서가 오른쪽에서 왼쪽으로 흘러가기 때문에 의미없는 괄호이기는 하다. 이러한 해석 방식에 대해서는 잠시 후 다시 이야기해보도록 하겠다.&lt;/p&gt;
&lt;p&gt;여기서 우리가 주의해야 할 점은 Haskell에서 &lt;code class=&quot;language-text&quot;&gt;mempty&lt;/code&gt;가 항등성을 가져야한다는 것과 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;가 결합법칙을 만족시켜야 한다는 사실을 명시적으로 표현할 수 있는 방법이 없다는 것이다. 이런 법칙들을 만족시키고 준수하는 것은 전적으로 프로그래머의 책임에 달려있다.&lt;/p&gt;
&lt;p&gt;Haskell의 클래스는 C++의 클래스처럼 강제적이지 않다. 그래서 새로운 타입을 정의할 때도 굳이 해당 클래스를 미리 지정할 필요가 없으며, 주어진 타입이 어떤 클래스의 인스턴스가 되는지에 대한 것은 나중에 정의해도 된다.&lt;/p&gt;
&lt;p&gt;예를 들어 &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;mempty&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;를 구현해서 모노이드가 되었다고 가정해보겠다. (사실 이건 &lt;a href=&quot;https://hackage.haskell.org/package/base-4.19.0.0/docs/Prelude.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Standard Prelude&lt;/a&gt;에 이미 구현되어있기는 하다.)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;mempty&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;mappend&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결국 String은 그저 문자들의 리스트일 뿐이므로, 위 예시에서는 리스트 연결 연산자인 &lt;code class=&quot;language-text&quot;&gt;(++)&lt;/code&gt;를 사용했다.&lt;/p&gt;
&lt;p&gt;여기서 Haskell의 문법에 대해서 하나 짚고 넘어가야 할 것 같다. Haskell에서 임의의 중위 연산자를 괄호로 감싸면 두 개의 인자를 받는 함수가 된다. 즉 두 문자열을 연결하기 위해 우리는 아래와 같이 문자열 사이에 ++ 연산자를 넣어주거나,&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;world!&quot;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;또는 ++ 연산자를 괄호로 감싸 &lt;code class=&quot;language-text&quot;&gt;(++)&lt;/code&gt;로 표현하여 함수로 만들고 두 개의 인자를 넘기는 방식으로 코드를 작성할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello &quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;world!&quot;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 함수의 인자들은 쉼표로 구분되지도 않고 괄호로 감싸지도 않았다는 사실을 기억하도록 하자. (이게 바로 Haskell을 배울 때 가장 익숙해지기 어려운 부분인 것 같다.)&lt;/p&gt;
&lt;p&gt;또한 Haskell에서는 함수가 서로 같다는 동등성을 표현할 수 있다는 점을 이야기하고 넘어가면 좋을 것 같다. 아래 예시를 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;mappend&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드는 함수가 생성한 값의 비교를 표현하는 것과는 개념적으로 다른 표현이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;mappend&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;s2&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 두 가지 예시 중 전자는 Hask 카테고리 또는 연산이 종료되지 않음을 의미하는 bottom을 제외한 집합에서의 사상의 동등성을 표현하고 있다고 볼 수 있다. 이러한 등식은 간결할 뿐 아니라 다른 카테고리에도 일반화될 수 있다.&lt;/p&gt;
&lt;p&gt;후자의 경우는 확장 동등성(Extensional Equality)라고 불리며, &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt; 함수와 &lt;code class=&quot;language-text&quot;&gt;(++)&lt;/code&gt; 함수가 인자로 동일한 두 개의 문자열을 입력받았을 때 이 함수들이 반환하는 출력 또한 동일하다는 것을 의미한다. 인수의 값은 점(Point)이라고 불리기도 하기 때문에 이 개념을 점별 동등성(Point-wise Equality)이라고 부르기도 한다. 인수를 지정하지 않은 함수들의 동등성은 Point-Free하다고 한다.&lt;/p&gt;
&lt;p&gt;참고로 Point-Free 스타일을 표현할 때 주로 함수의 합성(Composition)을 사용하는데, 이때 함수의 합성은 점(&lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt;)을 사용하여 표현하므로, 초보자에게는 조금 헷갈릴 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mappend = (++)&lt;/code&gt;가 표현하는 동등한 사상이라는 개념과 &lt;code class=&quot;language-text&quot;&gt;mappend s1 s1 = (++) s1 s2&lt;/code&gt; 가 표현하는 Extensional Equality의 개념이 조금 어려울 수 있다. 사실 잘 생각해보면 두 함수가 같은 인자를 받았을 때 같은 값을 반환한다는 것이 이 함수들이 정말로 “같은 함수”라는 것을 의미하는 것은 아니다.&lt;/p&gt;
&lt;p&gt;예를 들어 &lt;code class=&quot;language-text&quot;&gt;(a, b) ⇒ a + b&lt;/code&gt; 처럼 두 인자를 받아 두 값을 더해주는 함수와 &lt;code class=&quot;language-text&quot;&gt;(a, b) ⇒ a + b + 0&lt;/code&gt; 처럼 항등원을 한번 더 더하는 함수는 같은 인자를 받았을 때 항상 같은 값을 반환할테지만, 엄연히 두 함수의 구현은 다르므로 “다른 함수”라고 보는 것이다.&lt;/p&gt;
&lt;p&gt;즉, “같은 함수”라는 개념은 단지 같은 인자를 받았을 때 같은 값을 반환하는 것만으로는 만족할 수 있는 개념이 아니기 때문에 이 두 가지 개념을 엄밀하게 구분하는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C++에서 모노이드를 가장 비슷하게 흉내낼 수 있는 방법은 현재 표준 제안 단계인 &lt;code class=&quot;language-text&quot;&gt;concepts&lt;/code&gt; 키워드를 사용하는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  T mempty &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  T &lt;span class=&quot;token function&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; T&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;concept&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; Monoid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;M m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; mempty&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;M&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; M&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; M&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 정의는 마찬가지로 표준 제안 단계인 Value Template 기능을 사용하며, 다형적인 값을 받아들일 수 있도록 선언하여 모든 타입을 커버할 수 있도록 작성하였다.&lt;/p&gt;
&lt;p&gt;그리고 &lt;code class=&quot;language-text&quot;&gt;delete&lt;/code&gt; 키워드는 기본값이 정의되어 있지 않다는 것을 의미하며, 이는 각 케이스 별로 모두 명시해줘야 한다. 즉 위 예시에서 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;의 경우는 기본값이 정의되지 않은 것이다.&lt;/p&gt;
&lt;p&gt;concept으로 정의된 Monoid는 주어진 임의의 타입 &lt;code class=&quot;language-text&quot;&gt;M&lt;/code&gt;에 대해서 &lt;code class=&quot;language-text&quot;&gt;mempty&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;가 적절하게 정의되었는지를 검사하는 구문이기 때문에 bool을 반환하도록 작성되어있다.&lt;/p&gt;
&lt;p&gt;이러한 Monoid concept은 아래와 같이 적절한 특수화와 오버로딩을 통해 인스턴스로 구현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string mempty&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string &lt;span class=&quot;token function&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s1 &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; s2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;35-카테고리로써의-모노이드&quot; style=&quot;position:relative;&quot;&gt;3.5 카테고리로써의 모노이드&lt;a href=&quot;#35-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%AC%EB%A1%9C%EC%8D%A8%EC%9D%98-%EB%AA%A8%EB%85%B8%EC%9D%B4%EB%93%9C&quot; aria-label=&quot;35 카테고리로써의 모노이드 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자 지금까지 우리에게 익숙한 원소를 가진 집합의 관점에서 모노이드를 정의해보았다. 그러나 이 책은 카테고리 이론에 대한 이야기를 하고 있기 때문에, 이제부터는 집합과 원소에서 벗어나 대상과 사상에 대해 이야기를 해보려고 한다.&lt;/p&gt;
&lt;p&gt;자 일단 관점을 조금 바꿔서, 이항연산을 적용한다는 것을 어떤 대상에서 다른 대상으로 “이동”하는 것으로 생각해보자.&lt;/p&gt;
&lt;p&gt;예를 들어 모든 자연수에 5를 더하는 연산을 생각해보자. 이 연산은 0을 5로, 1을 6으로, 2를 7로 매핑할 것이다. 이런 개념은 일종의 자연수 집합에 정의된 함수와 동일하다. 역시 함수와 집합으로 생각하니 편하고 좋은 것 같다.&lt;/p&gt;
&lt;p&gt;어떤 수 n에 대해서 다시 n을 더하는 “Adder”라는 함수가 있다고 생각해보자. 이 Adder는 어떤 방식으로 합성될까? 5를 더하는 함수와 7을 더하는 함수를 합성하면 12를 더하는 함수가 될 것이다. 즉, Adder들간의 합성은 덧셈의 규칙을 그대로 유지한다고 볼 수 있다. 그렇다면 덧셈이라는 개념을 함수의 합성이라고 생각해도 문제가 없을 것이다.&lt;/p&gt;
&lt;p&gt;그리고 항등원인 0을 다루는 Adder도 존재할 수 있다. 0을 더한다는 행위는 아무것도 바꾸지 않는다는 의미이니 결국 자연수 집합에서의 항등함수라고 봐도 좋을 것 같다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 503px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0c6fe1eaa13884efac67be8a65a2ac54/ebfc4/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 127.49999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAECBAUD/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgAB/9oADAMBAAIQAxAAAAHci+BrYhUKOkDQY8//xAAeEAEBAAAGAwAAAAAAAAAAAAABAgADEBESICEiMf/aAAgBAQABBQJr2K30fDWYYPlzyCRen//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/ASn/xAAXEQADAQAAAAAAAAAAAAAAAAABEBEC/9oACAECAQE/AbEc1f/EAB8QAAAFBAMAAAAAAAAAAAAAAAABECExAhESICJBgf/aAAgBAQAGPwLHsQfqXHGp1JpPX//EAB0QAQEAAgIDAQAAAAAAAAAAAAERADEQIUFRYXH/2gAIAQEAAT8hEPkLlyRnpLwyiHW3JoEOk3mj8zoSX7rIGggtwIQ4k4//2gAMAwEAAgADAAAAEH/KgP/EABcRAQEBAQAAAAAAAAAAAAAAAAEREDH/2gAIAQMBAT8QC8wgmf/EABcRAQEBAQAAAAAAAAAAAAAAAAEQMUH/2gAIAQIBAT8QRphsXk//xAAeEAEBAAEEAwEAAAAAAAAAAAABEQAhMUFxEFFhkf/aAAgBAQABPxAIr6nQNr+45wFvF0waXHzw18B9+ZrzAqkDxTbvHXeRjQH6FruYQpiXGDYYR7AQ8AAAAcHj/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/0c6fe1eaa13884efac67be8a65a2ac54/ebfc4/1.jpg&quot; srcset=&quot;/static/0c6fe1eaa13884efac67be8a65a2ac54/0913d/1.jpg 160w,
/static/0c6fe1eaa13884efac67be8a65a2ac54/cb69c/1.jpg 320w,
/static/0c6fe1eaa13884efac67be8a65a2ac54/ebfc4/1.jpg 503w&quot; sizes=&quot;(max-width: 503px) 100vw, 503px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;즉, 전통적인 덧셈의 규칙들 대신에 Adder 함수들을 합성하는 규칙을 사용한다고 해도 연산 과정에서 딱히 어떤 정보를 잃어버리는 일은 없다는 말이다. 함수의 합성은 결합법칙을 만족하기 때문에 Adder의 합성 또한 결합법칙을 만족할 것이니 말이다. 그리고 항등함수에 해당하는 0을 더하는 Adder까지 존재한다.&lt;/p&gt;
&lt;p&gt;여기서 눈치 빠른 독자분들이라면 정수를 Adder로 매핑하는 것이 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt; 의 두 번째 해석이었던 &lt;code class=&quot;language-text&quot;&gt;m-&gt;(m-&gt;m)&lt;/code&gt;의 타입 선언과 유사하다는 것을 알아차릴 수 있었을 것이다. 이는 &lt;code class=&quot;language-text&quot;&gt;mappend&lt;/code&gt;가 모노이드 집합의 한 원소를 해당 집합에 작용하는 함수로 매핑한다는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;자 이제 자연수 집합 같은 것들은 다 잊어버리고, 그냥 이 집합을 Adder라는 수많은 사상이 달린 하나의 대상이라고 생각해보자. 결국 모노이드는 단 하나의 대상을 가진 단일대상 카테고리이다. 모노이드라는 이름 또한 단일한 무언가를 의미하는 그리스어 mono에서 유래되었다. 모든 모노이드는 단 하나의 대상과 서로 적절하게 합성할 수 있는 여러 사상들로 이루어진 단일대상 카테고리라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;문자열 연결 연산은 굉장히 흥미로운 경우인데, 우리는 연결하려고 하는 문자열을 대상 문자열의 뒤쪽에 붙힐 것인지, 앞쪽에 붙힐 것인지 선택할 수 있기 때문이다. 이 두 가지 모델의 합성 테이블(Composition Table)은 마치 거울처럼 대칭적이다.&lt;/p&gt;
&lt;p&gt;이는 “foo” 뒤에 “bar”를 추가하여 “foobar”를 만드는 것과 “bar” 앞에 “foo”를 추가하여 “foobar”를 만드는 것이 결국 동일하다는 것을 통해 확인해볼 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 이제 “모노이드라는 단일대상 카테고리가 어떤 이유로 이항연산자를 가진 집합과 연결되는가”에 대한 질문이 나올 차례인 것 같다.&lt;/p&gt;
&lt;p&gt;우리는 단일대상 카테고리에서 사상의 집합이라는 하나의 집합을 뽑아낼 수 있다. 위의 예시와 연결해보자면 이 집합의 원소인 사상들은 Adder들일 것이다. 다시 말해 우리는 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 단일대상 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 Hom 집합인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M(m,m)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;을 얻게되는 것이다.&lt;/p&gt;
&lt;p&gt;이 집합에서의 이항연산은 쉽게 정의해볼 수 있는데, Hom 집합 내 두 원소 간의 모노이드 곱은 각 사상들의 합성에 해당하는 원소일 것이다. 만약 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M(m,m)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에서 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 해당하는 두 원소를 가지고 모노이드 곱 이항연산을 한다면 결과는 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g\circ f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라는 것이다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d3da6336c55d688c889b42faf7546c4f/c08c5/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 65.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB7caMqFf/xAAYEAEBAQEBAAAAAAAAAAAAAAABAhEAIf/aAAgBAQABBQJfavEdGdWRTv/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABcRAAMBAAAAAAAAAAAAAAAAAAIQEUH/2gAIAQIBAT8BK4v/xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAbEAADAAIDAAAAAAAAAAAAAAAAAREhMUFhcf/aAAgBAQABPyFy3wYRTukhilOtecl0xIof/9oADAMBAAIAAwAAABBs7//EABcRAAMBAAAAAAAAAAAAAAAAAAEQEUH/2gAIAQMBAT8QE1f/xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQIBAT8QCMWMX//EABsQAQEAAwEBAQAAAAAAAAAAAAERACExQVFh/9oACAEBAAE/ENIQDmo4gwhNn3mUUinMURBFF45cEdpGe5Hqz8mf/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/d3da6336c55d688c889b42faf7546c4f/c08c5/2.jpg&quot; srcset=&quot;/static/d3da6336c55d688c889b42faf7546c4f/0913d/2.jpg 160w,
/static/d3da6336c55d688c889b42faf7546c4f/cb69c/2.jpg 320w,
/static/d3da6336c55d688c889b42faf7546c4f/c08c5/2.jpg 640w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;결국 이 사상들의 출발 대상과 도착 대상은 모두 동일한 대상이기 때문에 이러한 합성 또한 항상 존재할 수 밖에 없다. 그리고 카테고리의 규칙에 따라 사상 간의 합성은 결합법칙을 만족하며, 항등 사상이 모노이드 곱 연산의 항등원이라고 볼 수 있다. 즉 우리는 항상 모노이드 카테고리에서 모노이드 집합을 만들어낼 수 있으며, 이 두 개념은 본질적으로 같은 것이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;다만 여기에는 수학자들이 지적할만한 작은 문제가 하나 있는데, 반드시 사상들이 집합을 이뤄야 할 필요는 없다는 것이다. 카테고리의 세계에서는 집합보다 더 거대한 개념들이 있다. 임의의 두 대상 간의 사상이 집합을 이루는 카테고리를 작은 카테고리(Locally Small Category)라고 한다. 물론 앞서 이야기했듯이 필자는 이러한 사소한 부분들은 무시하고 넘어갈 것이지만, 이런 개념이 있다는 것 정도만 알아두자는 차원에서 언급해보았다.&lt;/p&gt;
&lt;p&gt;카테고리 이론에서 흥미롭게 여겨지는 많은 개념들은 Hom 집합의 원소가 합성이 가능한 사상임과 동시에 어떤 집합의 원소로써의 성질도 가질 수 있다는 점에서부터 비롯된다. 즉, 카테고리 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이 가진 사상들의 합성은 사상들의 집합인 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M(m,m)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이 가진 원소(사상)들 간의 모노이드 곱이라고 해석할 수도 있다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 2. 타입과 함수]]></title><description><![CDATA[타입과 함수로 이루어진 카테고리는 프로그래밍에서 꽤나 중요한 역할을 한다. 자 이제 타입이라는 것이 무엇이며 왜 이런 개념이 필요한지에 대해 이야기를 해보자.]]></description><link>https://evan-moon.github.io/2024/02/06/category-theory-for-programmers-2-types-and-functions/</link><guid isPermaLink="false">20240206-category-theory-for-programmers-2-types-and-functions</guid><pubDate>Tue, 06 Feb 2024 02:12:42 GMT</pubDate><content:encoded>&lt;p&gt;타입과 함수로 이루어진 카테고리는 프로그래밍에서 꽤나 중요한 역할을 한다. 자 이제 타입이라는 것이 무엇이며 왜 이런 개념이 필요한지에 대해 이야기를 해보자.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;21-어떤-이들에게-타입이-필요한가&quot; style=&quot;position:relative;&quot;&gt;2.1 어떤 이들에게 타입이 필요한가?&lt;a href=&quot;#21-%EC%96%B4%EB%96%A4-%EC%9D%B4%EB%93%A4%EC%97%90%EA%B2%8C-%ED%83%80%EC%9E%85%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%9C%EA%B0%80&quot; aria-label=&quot;21 어떤 이들에게 타입이 필요한가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;정적타입과 동적타입, 그리고 강타입과 약타입의 각각의 장단점에 대해서는 약간의 논란이 존재한다. 한번 간단한 사고실험을 통해 이 선택들에 대해 한번 상상해보자. 여기 수백만 마리의 원숭이가 컴퓨터 키보드 앞에 앉아 행복한 기분을 느끼며 아무런 키나 랜덤하게 누르고, 프로그램을 작성하고, 컴파일하고, 실행시키고 있다.&lt;/p&gt;
&lt;p&gt;만약 원숭이들이 기계어를 사용하는 상황이라면 이들이 만든 어떠한 바이트들의 조합이든 모두 허용되고 실행될 수 있다. 그러나 원숭이들이 고급 언어를 사용한다면 컴파일러가 어휘 및 문법 오류를 잡아준다는 사실에 그저 감사하게 될 것이다. 비록 많은 원숭이들이 바나나를 받지 못하고 떠나게 되겠지만, 그나마 유지보수할 수 있는 프로그램을 만들어낼 수 있을테니 말이다.&lt;/p&gt;
&lt;p&gt;타입 체킹은 무의미하게 작성된 프로그램에 대한 하나의 방어막이라고 볼 수 있다. 더 나아가 타입의 불일치를 런타임에서만 잡아낼 수 있는 동적 타입 언어와 다르게, 강력하게 타입이 정적으로 체크되는 언어에서는 타입의 불일치가 컴파일 타임에 발견되기 때문에 굳이 실행해보지 않더라도 잘못된 프로그램들을 잡아낼 수 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b8ac7991e21256d5af389e375d200d2e/10435/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 116.25000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAXABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIEBQP/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHbhT4m0iKsAuA//8QAGxABAAIDAQEAAAAAAAAAAAAAAQIDABESEyL/2gAIAQEAAQUCnLkLTrL/ALm77HZZUr4uRNR//8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAwACAwEAAAAAAAAAAAAAAAERECECEkFR/9oACAEBAAY/AiPE0odly2vpSr3EP//EABwQAQADAAIDAAAAAAAAAAAAAAEAETEhURBhcf/aAAgBAQABPyEe5cIzhC5Tvg8hBlLsqFktVSr7RH9U99RiTdT/2gAMAwEAAgADAAAAELAIAP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8QH//EAB8QAAICAQQDAAAAAAAAAAAAAAERADFBIVHB4RBh0f/aAAgBAQABPxAKJDSYn1AHP1g9KB++FbRiAYI6O7hD89wDarXqDBBI1tBEjJisAcCAuJOyXxGqNjvP/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/b8ac7991e21256d5af389e375d200d2e/c08c5/1.jpg&quot; srcset=&quot;/static/b8ac7991e21256d5af389e375d200d2e/0913d/1.jpg 160w,
/static/b8ac7991e21256d5af389e375d200d2e/cb69c/1.jpg 320w,
/static/b8ac7991e21256d5af389e375d200d2e/c08c5/1.jpg 640w,
/static/b8ac7991e21256d5af389e375d200d2e/10435/1.jpg 944w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;우리에게는 이 원숭이들을 행복하게 만드는 것이 중요할까? 아니면 정확한 프로그램을 만드는 것이 중요할까?&lt;/p&gt;
&lt;p&gt;일반적으로 이러한 원숭이 사고실험의 목표는 바로 셰익스피어의 전집을 만들어내는 것이며, 이때 맞춤법 검사기와 문법 검사기를 사용할 수 있다면 성공 확률은 크게 증가한다. 만약 타입 검사기와 비슷한 것이 있다면 로미오를 인간이라고 표현해놓고 뜬금없이 그에게서 나뭇잎이 자란다고 하거나, 로미오가 블랙홀이 되어 강력한 중력장으로 광자를 사로잡거나 하는 상황을 방지함으로써 셰익스피어 전집의 정밀도를 높혀나갈 수 있을 것이다.&lt;/p&gt;
&lt;h2 id=&quot;22-합성과-관련된-타입&quot; style=&quot;position:relative;&quot;&gt;2.2 합성과 관련된 타입&lt;a href=&quot;#22-%ED%95%A9%EC%84%B1%EA%B3%BC-%EA%B4%80%EB%A0%A8%EB%90%9C-%ED%83%80%EC%9E%85&quot; aria-label=&quot;22 합성과 관련된 타입 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 이야기했듯이 카테고리 이론은 결국 화살표를 합성하는 것이다. 하지만 임의의 두 화살표를 아무렇게나 합성할 수 있는 것은 아니다. 한 화살표의 목표인 대상은 다음 화살표의 출발 대상과 동일해야 한다. 프로그래밍에서는 한 함수의 결과를 다른 함수로 전달하는 것과 동일하다고 볼 수 있다. 만약 합성하려고 하는 함수의 결과물을 다른 함수가 제대로 해석할 수 없는 경우 프로그램은 제대로 작동하지 않을 것이다. 즉, 합성이 제대로 되려면 양 끝단이 일치해야 한다는 것이며, 프로그래밍 언어가 제공하는 타입 시스템이 강력할수록 이러한 일치 여부를 잘 표현할 수 있고, 기계적으로 잘 검증할 수도 있다.&lt;/p&gt;
&lt;p&gt;내가 들었던 정적타입, 강타입 체킹에 대한 반대 의견 중 유일하게 일리가 있었던 것은 바로 타입은 맞지 않더라도 의미적으로는 올바른 일부 프로그램이 배제될 수도 있다는 것이었다. 하지만 실제로 이런 일은 극히 드물기도 하고, 모든 정적 타입, 강타입 언어는 타입 시스템을 무시할 수 있는 방법을 제공해주기도 한다.&lt;/p&gt;
&lt;p&gt;심지어 Haskell에도 &lt;code class=&quot;language-text&quot;&gt;unsafeCoerce&lt;/code&gt; 라는 녀석이 존재하기는 하지만, 이러한 기능들은 매우 신중하게 사용되어야 한다. 프란츠 카프카의 소설인 “&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%B3%80%EC%8B%A0_(%EC%B9%B4%ED%94%84%EC%B9%B4)&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;변신&lt;/a&gt;”의 주인공인 Gregor Samsa는 어느 날 갑자기 거대한 벌레가 되어버리면서 타입 시스템을 깨뜨렸고, 결국 그 결과가 어땠는지는 우리 모두 잘 알고 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;소설 변신에서의 Gregor Samsa는 어느 날 갑자기 거대한 벌레가 되어버리며, 단지 모습 뿐만 아니라 그가 인간으로써 지켜왔던 모든 것들을 함께 잃어버리게 된다. 이후 가족들은 그를 챙기려는 모습을 보이기는 하지만, 결국 가족들에게 그는 인간이 아닌 벌레로 평가되어 버림받았으며, 최종적으로는 쓸쓸히 죽음을 맞이한다. 경제적 능력을 상실한 한 명의 인간이 가정이나 사회에서 버림받게 된다는 씁쓸한 메세지를 던지는 소설인데, 이 책의 작가는 unsafeCoerce 타입을 “타입 역할을 제대로 못 하는 타입”으로 바라보고 있기 때문에 이런 예시를 든 것은 아닐까? 하는 생각을 해본다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;흔히 들을 수 있는 또 다른 주장은 이러한 타입 처리들이 프로그래머에게 너무 많은 부담을 지운다는 것이다. 물론 C++에서 이터레이터 선언을 몇 번 해보고 난 뒤에는 이러한 마음에 어느 정도 공감할 수 있었다. 그러나 사실 컴파일러가 문맥을 통해 대부분의 타입을 추론할 수 있는 타입 추론 기술이 존재하기 때문에, C++에서는 변수를 auto로 선언하더라도 이 변수의 타입이 무엇인지 컴파일러가 알아서 결정할 수 있다.&lt;/p&gt;
&lt;p&gt;Haskell을 사용하는 대부분의 경우, 타입 선언은 선택 사항이다. 하지만 프로그래머들은 직접 타입 선언을 하는 경우가 많은데, 이러한 선언들이 코드의 의미에 대한 많은 정보를 알려주기도 하고 컴파일 오류를 이해하기 쉽게 만들어주기도 하기 때문이다. 사실 Haskell을 사용하여 프로젝트를 시작하는 경우에는 타입부터 설계하는 것이 일반적이다. 설계 이후에는 타입 선언들로부터 점진적으로 프로그램을 구현하게 된다.&lt;/p&gt;
&lt;p&gt;종종 강력한 정적 타이핑은 코드를 테스트하지 않는 핑계로도 사용된다. 간혹 Haskell 프로그래머들이 “컴파일된다면 이건 제대로 된 프로그램이다”라고 이야기하는 것을 들을 수 있다. 하지만 당연하게도 제대로 타이핑된 프로그램이라고 해서 반드시 제대로된 프로그램이라고 보장할 수는 없다.&lt;/p&gt;
&lt;p&gt;이런 경솔한 태도들은 여러 연구들에서 생각보다 Haskell이 코드 품질 측면에서 강력한 성과를 내지 못한다는 사실과도 이어진다. 상업적인 환경에서는 반드시 최고의 품질을 만들어 내야한다기보다는 일정한 품질 수준만 만족시키는 것이 나을 수도 있다. 이런 전략 선택의 팩터는 소프트웨어 개발의 경제적인 측면, 그리고 최종 사용자의 품질 허용 수준과 밀접한 관련이 있으며, 사실 프로그래밍 언어나 기술적 방법론과는 거의 관련이 없다.&lt;/p&gt;
&lt;p&gt;이런 환경에서 가장 우선시 되어야 하는 품질 기준은 얼마나 많은 프로젝트가 일정이 밀렸는지, 그리고 원하는 기능을 제대로 만족시키지 못한 상태로 사용자에게 전달되는지를 측정하는 것이다.&lt;/p&gt;
&lt;p&gt;또한 유닛 테스트가 강타입 시스템을 대체할 수 있다는 주장도 있다. 한번 강타입 시스템을 가진 언어에서 특정 함수가 가진 인수의 타입을 변경하는 일반적인 리팩토링 작업을 생각해보자.&lt;/p&gt;
&lt;p&gt;약타입 시스템 언어에서는 이제 이 함수가 다른 타입의 데이터를 기대한다는 사실이 호출부에 전달이 되지 않을 수도 있겠지만, 강타입 시스템 언어에서는 해당 함수의 선언을 수정하고 이후 파생된 빌드 오류들을 수정하는 것만으로도 충분할 것이다.&lt;/p&gt;
&lt;p&gt;하지만 결국 테스트라는 것은 확률적인 작업이기 때문에 증명이라는 개념을 대체하기에는 역부족이며, 유닛 테스트로 몇몇 구현의 불일치를 잡아내는 정도일 것이다.&lt;/p&gt;
&lt;h2 id=&quot;23-타입이란-무엇인가&quot; style=&quot;position:relative;&quot;&gt;2.3 타입이란 무엇인가?&lt;a href=&quot;#23-%ED%83%80%EC%9E%85%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80&quot; aria-label=&quot;23 타입이란 무엇인가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;타입을 가장 간단하게 설명하는 말은 바로 집합이다. &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt; 타입은 True와 False 2개의 원소로 이루어진 집합이며, &lt;code class=&quot;language-text&quot;&gt;Char&lt;/code&gt; 타입은 a나 ą와 같은 모든 유니코드 문자를 원소로 가진 집합이다.&lt;/p&gt;
&lt;p&gt;집합은 유한할 수도 있고 무한할 수도 있다. &lt;code class=&quot;language-text&quot;&gt;Char&lt;/code&gt;의 리스트와 동일한 의미인 &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt; 타입의 경우가 바로 무한집합의 예이다.&lt;/p&gt;
&lt;p&gt;한번 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;라는 변수를 &lt;code class=&quot;language-text&quot;&gt;Integer&lt;/code&gt; 타입으로 선언해보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Integer&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리는 이제 이 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;라는 값이 정수 집합에 들어있는 하나의 원소라고 이야기할 수 있다. Haskell에서 &lt;code class=&quot;language-text&quot;&gt;Integer&lt;/code&gt; 타입은 &lt;a href=&quot;https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;임의 정밀도 산술&lt;/a&gt;을 사용하기 때문에 무한한 집합이다. C++의 &lt;code class=&quot;language-text&quot;&gt;int&lt;/code&gt;와 같이 원시 타입에 해당하는 유한집합 &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;도 존재한다.&lt;/p&gt;
&lt;p&gt;물론 타입과 집합을 완전히 동일시 하기에는 재귀적인 정의를 포함하는 다형성 함수나 모든 집합을 원소로 가지는 집합을 정의할 수 없다는 등의 몇 가지 문제가 있기는 하지만, 앞서 이야기한대로 너무 엄격한 수학적인 정의를 이야기하지는 않겠다. 여기서 중요한 것은 “Set”이라고 불리는 집합들의 카테고리가 존재하며 우리가 앞으로 이 개념을 다룰 것이라는 점이다. 이 Set 카테고리에서 대상은 집합이고 사상(화살표)는 함수이다.&lt;/p&gt;
&lt;p&gt;Set은 매우 특별한 카테고리이다. 왜냐하면 우리는 이미 이 카테고리의 대상인 집합에 대해서 잘 알고 있으니 이로부터 많은 직관을 얻을 수 있기 때문이다. 예를 들어 우리는 이미 공집합이라는 것이 어떠한 원소도 가지고 있지 않다는 사실을 알고 있다. 또한 특별한 하나의 원소를 가진 집합도 알고 있으며, 함수라는 것이 어떤 한 집합의 원소를 다른 집합의 원소와 매핑(Mapping)해주는 개념이라는 것도 알고 있다.&lt;/p&gt;
&lt;p&gt;또한 함수가 두 개의 원소를 하나의 원소로 매핑할 수는 있지만, 반대로 하나의 원소를 두 개의 원소로 매핑할 수는 없다는 것도 알고 있다. 그리고 우리는 항등 함수가 집합의 각 원소를 자기 자신에게 매핑한다는 것을 알고 있다. 이제 우리의 목표는 이렇게 디테일한 개념들은 점점 잊어버리고 순수한 카테고리 이론의 용어, 즉 대상과 화살표만으로 이런 개념들을 추상화해서 이해하는 것이다.&lt;/p&gt;
&lt;p&gt;이상적인 상황에서 우리는 Haskell의 타입을 집합으로, Haskell의 함수는 집합 간의 수학적인 함수로 정의해볼 수 있을 것이다. 하지만 한 가지 문제가 있다. 바로 수학적인 함수는 코드를 실행하는 것이 아니라, 단순히 답을 알고 있는 추상적 개념이라는 것이다. 하지만 Haskell의 함수는 직접 답을 계산해야한다. 물론 유한한 계산단계 내에서 답을 얻어낼 수만 있다면 계산이 얼마나 복잡하던 이 차이가 딱히 문제로 번지지는 않는다. (물론 너무 큰 수를 사용한다면 문제가 될 수도 있지만 말이다.)&lt;/p&gt;
&lt;p&gt;하지만 재귀와 같은 일부 계산은 영원히 종료되지 않을 수도 있다. 그러나 종료되는 함수와 종료되지 않는 함수를 구분하는 것은 &lt;a href=&quot;https://namu.wiki/w/%EC%A0%95%EC%A7%80%20%EB%AC%B8%EC%A0%9C&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;정지 문제&lt;/a&gt;라는 유명한 난제이기 때문에, Haskell 내에서 종료되지 않는 함수만 찾아내어 금지하는 것은 불가능하다. 그래서 컴퓨터 과학자들은 관점에 따라 훌륭한 아이디어 또는 Hack으로도 볼 수 있는 bottom이라는 한 가지 특별한 값을 제안했다.&lt;/p&gt;
&lt;p&gt;이 “값”은 종료되지 않는 연산을 표현하며, &lt;code class=&quot;language-text&quot;&gt;_|_&lt;/code&gt; 또는 유니코드 &lt;code class=&quot;language-text&quot;&gt;⊥&lt;/code&gt;로도 표현할 수 있다. 한번 예시를 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 함수는 True, False 또는 &lt;code class=&quot;language-text&quot;&gt;_|_&lt;/code&gt; 를 반환하며, 이것은 이 함수가 종료되지 않을 수도 있다는 사실을 의미한다.&lt;/p&gt;
&lt;p&gt;재미있는 사실은 bottom을 타입 시스템의 일부로 받아들이기만 하면, 프로그램에서 발생하는 모든 런타임 에러를 bottom으로 표현하고 명시적으로 함수가  bottom을 반환할 수 있다는 개념만으로도 엄청난 편의성이 생긴다는 것이다. 이는 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;를 사용한 표현에서 확인해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;undefined&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 표현에서 &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;는 bottom으로 평가되기 때문에 타입 체크를 통과한다. bottom은 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;을 포함한 모든 타입의 원소이기 때문이다. 심지어 아래와 같이 작성할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- (x는 생략 가능)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이게 가능한 이유는 bottom이 &lt;code class=&quot;language-text&quot;&gt;Bool -&gt; Bool&lt;/code&gt; 타입에도 해당하기 때문이다. 이처럼 bottom을 반환할 수 있는 함수를 부분 함수(Partial Function)이라고 하며, 반대로 모든 인수에 대해 반드시 유효한 결과를 반환하는 함수는 전체 함수(Total Function)이라고 한다.&lt;/p&gt;
&lt;p&gt;바로 이 bottom이라는 개념 때문에 Haskell의 타입과 함수로 이루어진 카테고리는 Set이 아닌 Hask라는 이름으로 불린다. 하지만 이렇게 이론적으로 계속 파고 들다보면 끝도 없이 복잡해지기도 하고 어차피 실용적인 측면에서 보면 종료되지 않는 함수와 bottom을 그냥 무시하고 Hask를 Set이라고 생각해도 무방하니 이 이야기는 이쯤에서 마무리지으려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;24-우리는-왜-수학적인-개념을-알아야-하는가&quot; style=&quot;position:relative;&quot;&gt;2.4 우리는 왜 수학적인 개념을 알아야 하는가?&lt;a href=&quot;#24-%EC%9A%B0%EB%A6%AC%EB%8A%94-%EC%99%9C-%EC%88%98%ED%95%99%EC%A0%81%EC%9D%B8-%EA%B0%9C%EB%85%90%EC%9D%84-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%98%EB%8A%94%EA%B0%80&quot; aria-label=&quot;24 우리는 왜 수학적인 개념을 알아야 하는가 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;아마 여러분은 프로그래머로서 프로그래밍 언어의 구문과 문법에 대해 깊은 이해도를 가지고 있을 것이다. 언어의 문법이나 구문과 같은 요소들은 보통 언어 명세의 가장 첫 부분에 형식적인 표기를 사용하여 설명된다. 그러나 언어의 의미론적인 부분은 설명하기가 훨씬 까다롭다. 언어의 의미에 대한 설명들은 훨씬 더 많은 페이지를 필요로 하고 형식적이기도 어려우며, 대부분의 경우에는 설명이 완벽하기도 어렵다. 이 때문에 언어에 대한 논의는 끝나지 않고 언어 표준에 대한 내용에 대해 각자의 해석을 통해 저술한 책들이 범람하고 있는 것이다.&lt;/p&gt;
&lt;p&gt;물론 언어의 의미론적인 측면을 설명하는 형식화된 몇몇 도구들이 존재하기는 하지만, 워낙 복잡하기 때문에 주로 단순화된 학술적인 언어에나 사용되는 편이며 현실의 거대한 프로그래밍 언어에서는 잘 사용되지 않는다. 이러한 도구 중 하나인 운용 의미론(Operational Semantics)은 프로그램 실행 매커니즘을 기술하는데, 이는 형식화된 가상 인터프리터를 정의하는 것이다. 산업용 언어인 C++와 같은 언어들의 경우에는 보통 “추상기계(Abtract Machine)”와 같은 비형식적인 운용 추론을 사용하여 설명한다.&lt;/p&gt;
&lt;p&gt;문제는 이러한 운용 의미론을 이용하여 프로그램에 대한 증명을 하는 것이 굉장히 어렵다는 것이다. 어떤 프로그램에 대한 특징을 보여주기 위해서는 반드시 가상 인터프리터를 사용하여 프로그램을 “실행”시켜봐야 한다.&lt;/p&gt;
&lt;p&gt;단지 프로그래머들이 어떤 문제에 대한 형식적인 증명을 수행하는 것에 대해 익숙하지 않기 때문에 어렵다고 하는 것은 아니다. 우리는 항상 우리가 올바른 프로그램을 작성하고 있다고 “생각”한다. 아무도 키보드 앞에 앉아서 “일단 대충 몇 줄 짜보고 무슨 일이 벌어지는지 봐야지”라고 말하지는 않는다는 것이다. 우리는 우리가 작성하는 코드들이 원하는 결과를 얻을 수 있도록 특정한 동작을 수행할 것이라고 기대하는 것이다. 그래서 작성한 코드가 우리의 예상과 다르게 동작하면 우리는 크게 놀라게 된다.&lt;/p&gt;
&lt;p&gt;즉, 우리는 우리가 작성하는 프로그램의 동작에 대한 일종의 이성적 추론을 하고 있으며, 이러한 추론은 우리의 머릿속의 인터프리터를 통해 코드를 실행시켜보며 수행하고 있다는 것이다. 하지만 우리가 모든 변수를 추적한다는 것은 불가능에 가깝다. 컴퓨터는 프로그램을 실행하는 것에 특화되어있는 녀석이지만 우리 인간은 그렇지 않으니 말이다! 만약 우리가 컴퓨터만큼 프로그램을 잘 실행시킬 수 있었다면 컴퓨터라는 개념 자체가 필요없었을테니 말이다.&lt;/p&gt;
&lt;p&gt;이런 문제를 해결하기 위해 표시적 의미론(Denotational Semantics)라고 불리는 대안이 있다. 이는 수학을 기반으로 하며, 표시적 의미론에서는 모든 프로그래밍 구성에 수학적 해석이 부여되기 때문에 프로그램의 속성을 증명하려면 그저 수학적 정리를 증명하기만 하면 된다. 이런 수학적인 증명이 어려울 것이라고 생각할 수는 있겠지만, 사실 우리 인간은 지난 수천년동안 수학적 기술들을 발전시켜왔기 때문에, 이미 우리가 활용할 수 있는 많은 지식들이 쌓여있다. 또한 우리가 프로그래밍에서 마주치는 문제들은 전문적인 수학자들이 증명해야하는 문제들에 비해 상대적으로 간단한 경우가 많다.&lt;/p&gt;
&lt;p&gt;표시적 의미론을 아주 잘 표현할 수 있는 Haskell에서의 팩토리얼 함수 정의를 한번 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;fact&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[1..n]&lt;/code&gt; 표현식은 1부터 n까지의 정수로 이루어진 리스트를 의미한다. 함수 &lt;code class=&quot;language-text&quot;&gt;product&lt;/code&gt;는 이 리스트의 모든 원소를 곱한다. 이런 표현들은 우리가 수학 교과서에서 볼 수 있는 팩토리얼의 정의와 굉장히 유사하다. 한번 C와 비교해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-c line-numbers&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;*=&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;설명이 더 필요할까?&lt;/p&gt;
&lt;p&gt;사실 팩토리얼 함수에는 이미 명백한 수학적 표현이 존재하기 때문에 살짝 비겁한 예시이기는 하다. 여기서 영리한 독자라면 “그럼 키보드에서 문자를 읽거나 네트워크를 통해 패킷을 보내는 행위들에 대한 수학적 모델은 뭔가요?”라고 물어볼 수도 있겠다. 나도 오랜 기간 고민해봤지만 이런 질문들은 자칫 난해한 설명을 하게 되기 쉬운 까다로운 질문이었다.&lt;/p&gt;
&lt;p&gt;물론 질문과 같이 중요한 작업들을 운용 의미론으로 다루기는 쉽지만 표시적 의미론으로 다루기에는 적합하지 않아보인다는 것은 인정한다. 이런 문제에 대한 돌파구는 바로 카테고리 이론에서 나왔다. Eugenio Moggi는 계산에서 파생된 효과(Computational Effect)를 모나드에 매핑할 수 있다는 사실을 발견했는데, 이는 표시적 의미론에 새로운 생명을 불어넣어 주었고 순수 함수형 프로그램을 더 유용하게 만들 뿐 아니라 전통적인 프로그래밍에도 새로운 시각을 제공해주었다. 추후 모나드에 대해서는 카테고리론적인 도구들에 좀 더 익숙해지고난 뒤 다시 설명하도록 하겠다.&lt;/p&gt;
&lt;p&gt;정리하자면 프로그래밍에서 수학적 모델이 가지는 중요한 장점 중 하나는 소프트웨어의 정확성에 대한 형식적인 증명을 수행할 수 있다는 것이다. 일상 속에서 비즈니스 소프트웨어를 작성할 때는 그렇게 중요하지 않을 수 있겠지만, 작은 실패 하나가 큰 대가로 돌아오는 프로그래밍 분야나 심지어 사람의 목숨이 위험해질 수 있는 분야도 있다. 만약 여러분이 의료 시스템을 위한 웹 어플리케이션을 작성한다면 Haskell 표준 라이브러리가 제공하는 알고리즘과 함수들이 프로그램의 정확성을 보장해준다는 사실에 감사하게 될 수도 있다.&lt;/p&gt;
&lt;h2 id=&quot;25-순수함수와-순수하지않은-함수&quot; style=&quot;position:relative;&quot;&gt;2.5 순수함수와 순수하지않은 함수&lt;a href=&quot;#25-%EC%88%9C%EC%88%98%ED%95%A8%EC%88%98%EC%99%80-%EC%88%9C%EC%88%98%ED%95%98%EC%A7%80%EC%95%8A%EC%9D%80-%ED%95%A8%EC%88%98&quot; aria-label=&quot;25 순수함수와 순수하지않은 함수 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;우리가 C++ 또는 다른 명령형 언어에서 함수라고 부르는 것들은 수학자들이 함수라고 부르는 것과는 약간 다른 개념이다. 수학적 함수는 그저 어떠한 값들 간의 사상(Mapping)일 뿐이기 때문이다.&lt;/p&gt;
&lt;p&gt;물론 프로그래밍 언어를 사용하여 수학적인 함수를 구현하는 것도 가능하다. 이러한 함수는 주어진 입력 값을 받아 출력 값을 계산한다. 어떠한 수의 제곱을 구하는 함수는 받아들인 입력 값을 그 입력 값과 다시 곱하여 계산하고 반환할 것이다. 이 함수는 동일한 입력 값을 받아 호출될 때마다 항상 같은 출력 값을 보장한다. 어떠한 수의 제곱이라는 것은 달의 위상처럼 매번 변하는 개념이 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;또한 어떠한 수의 제곱을 계산하는 일이 강아지에게 맛있는 간식을 주는 것과 같은 사이드이펙트를 가지면 안된다. 이런 “함수”는 수학적 함수로 모델링하기가 쉽지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;이처럼 프로그래밍 언어에서 동일한 입력 값이 주어질 때 항상 동일한 결과를 생성하고 함수 외부세계에 영향을 끼치는 사이드이펙트가 없는 함수를 순수 함수라고 한다. Haskell과 같은 순수 함수형 언어에서는 모든 함수가 순수하기 때문에, 명령형 언어에 비해 표시적 의미론이나 카테고리 이론을 사용하여 모델링하는 것이 상대적으로 더 쉽다. 물론 다른 언어들을 사용하더라도 순수한 부분을 제한하거나 사이드이펙트를 별도로 다룰 수 있도록 만드는 것이 가능하다. 따라서 수학적 함수만 사용한다는 제약이 우리에게 어떠한 불이익을 가져다주는 일은 없을 것이며, 추후 모나드가 어떤 방식으로 순수 함수만을 사용하여 모든 종류의 효과들을 모델링할 수 있도록 만들어주는지도 알아볼 것이다.&lt;/p&gt;
&lt;h2 id=&quot;26-타입에-대한-예시&quot; style=&quot;position:relative;&quot;&gt;2.6 타입에 대한 예시&lt;a href=&quot;#26-%ED%83%80%EC%9E%85%EC%97%90-%EB%8C%80%ED%95%9C-%EC%98%88%EC%8B%9C&quot; aria-label=&quot;26 타입에 대한 예시 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;타입이 사실은 집합이라는 사실을 깨닫고 나면, 이제 우리는 약간 독특한 타입에 대해서도 한번 생각해볼 수 있다. 예를 들어 공집합에 해당하는 타입은 무엇일까? Haskell에서는 이러한 타입을 Void라고 부르기는 하지만, C++에서의 void와는 다른 개념이다.&lt;/p&gt;
&lt;p&gt;이 타입은 어떠한 값도 가지고 있지 않는 타입이다. Void를 인자로 받는 함수를 정의할 수는 있겠지만 이를 호출할 수는 없을 것이다. 왜냐하면 이런 함수를 호출하기 위해서는 Void 타입의 값을 인자로 넣어줘야 하는데, 이 타입의 값이 존재하지 않기 때문이다. 이 함수는 어떤 타입이든 반환할 수 있기 때문에 반환할 수 있는 것들에 대한 제약은 전혀 없겠지만, 결국 호출할 수 없기 때문에 뭔가가 반환되는 일도 벌어지지 않을 것이다. 즉, 이 함수는 반환 타입에 대한 다형성을 가진 함수라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;Haskell 개발자들은 이런 함수를 &lt;code class=&quot;language-text&quot;&gt;absurd&lt;/code&gt;라고 부른다. 여기서 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;는 어떤 타입이든지 될 수 있는 타입 변수라는 것을 기억하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;absurd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수의 이름은 그냥 지어진 것이 아니다. Curry-Howard 동형성이라는 논리학적인 측면에서 타입과 함수를 더 깊게 해석해볼 수 있다. Void 타입은 거짓을 나타내고, absurd 함수의 타입은 “거짓인 가정에서 시작된 모든 명제는 참이다”라는 명제에 해당한다. 이는 라틴어 속담 “ex falso sequitur quodlibet(모든 것은 거짓으로부터 나온다)”과 같은 말이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이는 형식논리학의 개념인데, P→Q(만약 P라면 Q이다)라는 명제가 있는 경우, P가 거짓이라 할 지라도 Q가 참이라면 전체 명제는 참으로 평가받는 것을 이야기하는 것이다. 만약 P가 “하늘이 하얀색이다”, Q가 “태양은 뜨겁다”라면 하늘이 하얀색이든 아니든 항상 태양은 뜨거우므로 P→Q(하늘이 하얀색이면 태양은 뜨겁다)도 참이 된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;다음으로는 단일원소 집합에 해당하는 타입이다. 이 타입은 단 하나의 값만을 가질 수 있으며, 이 값은 그저 “존재”한다. 처음에는 이 말이 잘 이해가 안 갈 수도 있지만, C++의 void가 바로 이러한 타입이다. void 타입의 인자를 받고 void 타입을 반환하는 함수를 한번 생각해보면, 이 함수는 어떤 상황이든 항상 호출될 수 있다. 만약 이 함수가 순수함수라면 이 함수는 항상 같은 값을 반환할 것이다.&lt;/p&gt;
&lt;p&gt;아래 예시를 한번 살펴보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f44&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;44&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수가 “아무 인자도 받지 않는 함수”로 보일 수도 있지만, 앞서 살펴본 것처럼 “아무 인자도 받지 않는 함수”는 호출될 수 없다. 왜냐하면 “아무것도 존재하지 않는다”라는 것을 나타내는 값이 없기 때문이다. 그렇다면 이 함수는 무엇을 인자로 받고 있는걸까? 사실 개념적으로 보면 이 함수는 단 하나의 원소만 존재할 수 있는 더미 값을 받는다고 볼 수 있기 때문에 우리가 직접 이 값을 명시해줄 필요는 없다. 그러나 Haskell에서는 이러한 더미 값을 빈 괄호쌍인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt; 으로 표현한다.&lt;/p&gt;
&lt;p&gt;이것이 우연인지 아닌지는 모르겠지만 C++과 Haskell에서 void를 인자로 받는 함수를 호출하는 방법은 같은 모양으로 보인다. 또한 Haskell은 간결함을 사랑하기 때문에 기호 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt; 가 그 값의 타입, 생성자, 그리고 이로 인해 생성되는 유일한 값을 표현하는데에도 사용된다.&lt;/p&gt;
&lt;p&gt;즉, 위의 C++함수는 Haskell에서는 아래와 같이 표현된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f44&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Integer&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f44&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;44&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 줄은 &lt;code class=&quot;language-text&quot;&gt;f44&lt;/code&gt; 함수가 unit이라고 발음하는 타입 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;을 받아 &lt;code class=&quot;language-text&quot;&gt;Integer&lt;/code&gt; 타입을 반환한다고 선언하고 있다. 두 번째 줄은 &lt;code class=&quot;language-text&quot;&gt;f44&lt;/code&gt; 함수가 unit의 유일한 생성자인 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;를 패턴 매칭하여 숫자 &lt;code class=&quot;language-text&quot;&gt;44&lt;/code&gt;를 생성한다는 것을 정의한다. 이 함수를 호출하기 위해서는 unit의 값 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;를 인자로 제공하면 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f44&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;unit을 인자로 받는 모든 함수는 반환 타입에 해당하는 원소 하나를 뽑는 것과 동일하다고 생각할 수 있다. (이 예시에서는 정수 44를 뽑았다.)&lt;/p&gt;
&lt;p&gt;사실 &lt;code class=&quot;language-text&quot;&gt;f44&lt;/code&gt;는 숫자 &lt;code class=&quot;language-text&quot;&gt;44&lt;/code&gt;의 또 다른 표현이라고 볼 수도 있다. 이는 집합의 특정한 원소를 명시적으로 표현하는 것이 아니라 이를 함수(화살표)로 표현하는 것으로 대체하는 방법의 예시이기도 하다. unit에서 임의의 타입 A로 나아가는 함수(unit을 인자로 받아 A를 반환하는 함수)는 집합 A의 원소들과 일대일 대응 관계에 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 void 타입을 반환하는 함수, Haskell에서는 unit 타입을 반환하는 함수는 어떨까? 보통 C++에서 이런 함수는 사이드이펙트를 표현하기 위해 사용되지만, 우리는 이미 이런 함수들이 수학적인 의미에서 진짜 함수가 아니라는 것을 알고 있다. 즉, unit을 반환하는 순수 함수는 아무 일도 하지 않고, 그냥 인자를 버리기만 하는 것이다.&lt;/p&gt;
&lt;p&gt;수학적으로 집합 A에서 단일원소 집합으로 향하는 함수는 집합 A의 모든 원소를 공역에 해당하는 단일원소 집합에 들어있는 원소 하나에 매핑한다. 따라서 모든 A의 원소에 대해 이러한 일을 하는 함수는 단 하나만이 존재할 수 있다.&lt;/p&gt;
&lt;p&gt;아래 예시를 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;fInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;fInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 임의의 정수를 인자로 입력받으면 반드시 unit을 반환한다. 앞서 언급했듯이 Haskell은 간결함을 추구하기 때문에 와일드카드 패턴인 언더스코어(&lt;code class=&quot;language-text&quot;&gt;_&lt;/code&gt;)를 사용하여 버려지는 인자를 표현할 수 있으며, 이 표현을 사용하면 인자의 이름을 지정할 필요도 없다.&lt;/p&gt;
&lt;p&gt;즉, 위의 예시는 아래와 같이 다시 표현해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;fInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;fInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 인자로 넘겨받는 값 뿐 아니라 인자의 타입에도 의존하고 있지 않다는 점에 주목하자.&lt;/p&gt;
&lt;p&gt;이처럼 임의의 타입에 대해서 항상 같은 형태로 구현될 수 있는 함수를 매개변수 다형성(Parametrically Polymorphic)을 가진 함수라고 한다. 구체적인 타입을 정하는 대신 타입 변수를 사용하여 하나의 방정식으로 다양한 함수들을 구현할 수 있다. 이렇게 임의의 타입을 받아 unit을 반환하도록 만들어져 다형성을 갖춘 함수를 뭐라고 부르면 좋을까?&lt;/p&gt;
&lt;p&gt;공교롭게도 이런 함수도 똑같이 unit이라고 부른다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C++에서는 이 함수를 아래와 같이 작성해볼 수 있을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다음으로 살펴볼 타입의 유형은 두 개의 원소를 가진 집합이다. C++에서는 이를 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt;이라고 부르며, Haskell에서도 이와 비슷하게 &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;이라고 부른다. 이 두 개념 간의 차이점은 C++의 bool은 built-in 타입인 반면에, Haskell에서는 아래와 같이 정의할 수 있다는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 정의는 Bool 타입이 &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt; 중 하나임을 의미한다. 원칙적으로는 C++에서도 Enum을 사용하여 bool 타입을 정의할 수 있어야 한다.&lt;/p&gt;
&lt;p&gt;하지만 C++의 Enum은 내부적으로 정수를 나타낸다. C++11의 “Enum Class”를 사용할 수도 있겠지만, 이 경우 해당 타입의 값을 사용할 때 &lt;code class=&quot;language-text&quot;&gt;bool::false&lt;/code&gt; 처럼 항상 클래스 이름을 붙혀주어야 한다. 또한 &lt;code class=&quot;language-text&quot;&gt;bool&lt;/code&gt; Enum을 사용하는 모든 파일들에 적절한 헤더를 포함시켜줘야 한다.&lt;/p&gt;
&lt;p&gt;Bool 타입을 인자로 받는 순수 함수는 대상 타입 내에서 &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt; 두 값을 선택한다.&lt;/p&gt;
&lt;p&gt;Bool을 반환하는 함수들은 predicates라고 불리는데, 예를 들어 Haskell 라이브러리인 &lt;code class=&quot;language-text&quot;&gt;Data.char&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;isAlpha&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isDigit&lt;/code&gt; 같은 predicates들로 가득 차있다. C++에도 이와 비슷한 라이브러리가 존재하며, 역시 &lt;code class=&quot;language-text&quot;&gt;isalpha&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isdigit&lt;/code&gt; 같은 함수들도 있지만 이 녀석들은 bool 타입이 아닌 int 타입을 반환한다. 실제 predicates는 &lt;code class=&quot;language-text&quot;&gt;std::ctype&lt;/code&gt; 에 정의되어있으며, &lt;code class=&quot;language-text&quot;&gt;ctype::is(alpha, c)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ctype::is(digit, c)&lt;/code&gt;와 같은 형태를 가지고 있다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 1. 카테고리: 합성의 본질]]></title><description><![CDATA[카테고리는 놀라울 정도로 단순한 개념이다. 카테고리는 대상과 그 사이를 이어주는 화살표로 구성되기 때문에 그림으로 나타내기도 매우 쉽다. 대상은 원이나 점으로 그리면 되고, 화살표는 그냥 화살표로 그리면 된다. (쉬운 이해를 위해 객체를 돼지 모양으로 그리고 화살표는 폭죽으로 그릴 것이다.)]]></description><link>https://evan-moon.github.io/2024/01/30/category-theory-for-programmers-1-category/</link><guid isPermaLink="false">20240130-category-theory-for-programmers-1-category</guid><pubDate>Tue, 30 Jan 2024 12:47:36 GMT</pubDate><content:encoded>&lt;p&gt;카테고리는 놀라울 정도로 단순한 개념이다. 카테고리는 대상과 그 사이를 이어주는 화살표로 구성되기 때문에 그림으로 나타내기도 매우 쉽다. 대상은 원이나 점으로 그리면 되고, 화살표는 그냥 화살표로 그리면 된다. (쉬운 이해를 위해 객체를 돼지 모양으로 그리고 화살표는 폭죽으로 그릴 것이다.)&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;하지만 카테고리의 본질은 합성(Composition)이다. 취향에 따라서 합성의 본질은 카테고리라고 말할 수도 있겠다. 만약 카테고리 내에 대상 A에서 다른 대상 B로 향하는 화살표와 대상 B에서 다른 대상 C로 향하는 화살표가 존재한다면, 반드시 대상 A에서 대상 C로 향하는 화살표, 즉 A→B와 B→C의 합성이 존재해야한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d0f06f731f3390dda0d7113c6f3aeaab/8e43b/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 43.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAGQAAAQUAAAAAAAAAAAAAAAAAAAECAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB1VsgwkD/xAAYEAEAAwEAAAAAAAAAAAAAAAACAAESEP/aAAgBAQABBQKrcLtEaz3/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAcEAABAwUAAAAAAAAAAAAAAAABAAIxESAiQXH/2gAIAQEABj8CcXxpVAPFlNn/xAAYEAEBAQEBAAAAAAAAAAAAAAABEQAgUf/aAAgBAQABPyE0DGQFpiQQHjj/2gAMAwEAAgADAAAAELAP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAQACAwEAAAAAAAAAAAAAAREAISAxQZH/2gAIAQEAAT8QhzVk9PLN42UCU2/TWM6RsHXD/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/d0f06f731f3390dda0d7113c6f3aeaab/c08c5/1.jpg&quot; srcset=&quot;/static/d0f06f731f3390dda0d7113c6f3aeaab/0913d/1.jpg 160w,
/static/d0f06f731f3390dda0d7113c6f3aeaab/cb69c/1.jpg 320w,
/static/d0f06f731f3390dda0d7113c6f3aeaab/c08c5/1.jpg 640w,
/static/d0f06f731f3390dda0d7113c6f3aeaab/6a068/1.jpg 960w,
/static/d0f06f731f3390dda0d7113c6f3aeaab/eea4a/1.jpg 1280w,
/static/d0f06f731f3390dda0d7113c6f3aeaab/8e43b/1.jpg 1845w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;하나의 카테고리에서 A에서 B로 이어지는 화살표와 B에서 C로 이어지는 화살표가 있다면,&lt;br&gt;반드시 A에서 C로 직접 이어지는 화살표, 즉 A→B 화살표와 A→C 화살표의 합성도 존재해야 한다.&lt;br&gt;나중에 다시 설명하겠지만 이 다이어그램은 항등 사상이 빠져있기 때문에 완벽한 카테고리는 아니다.&lt;/small&gt;
&lt;/center&gt;
&lt;h2 id=&quot;11-함수로써의-화살표&quot; style=&quot;position:relative;&quot;&gt;1.1 함수로써의 화살표&lt;a href=&quot;#11-%ED%95%A8%EC%88%98%EB%A1%9C%EC%8D%A8%EC%9D%98-%ED%99%94%EC%82%B4%ED%91%9C&quot; aria-label=&quot;11 함수로써의 화살표 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;벌써부터 너무 추상적이라 잘 이해가 안 가는가? 자 그럼 이제 조금 더 구체적인 이야기를 해보자. 화살표를 사상(Morphisms)이라고 불리는 함수라고 한번 생각해보는 것이다.&lt;/p&gt;
&lt;p&gt;자 여기 두 개의 함수 f와 g가 있다. 함수 f는 A 타입의 인자를 받아 B 타입의 값을 반환하며, 함수 g는 B 타입의 인자를 받아 C 타입의 값을 반환한다. 그럼 이제 우리는 함수 f의 결과를 함수 g에 전달하여 이 두 개의 함수를 합성할 수 있다. 우리는 결국 A 타입의 인자를 받아 C 타입의 값을 반환하는 새로운 함수를 정의한 것이다.&lt;/p&gt;
&lt;p&gt;수학에서는 이러한 함수들의 합성을 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g\circ f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 같이 함수 사이에 작은 원을 그려 표현하며, 합성된 함수의 실행 순서는 오른쪽에서 왼쪽으로 흘러간다. 아마 Unix의 파이프 표기법이나 F#의 Shevron(&lt;code class=&quot;language-text&quot;&gt;&gt;&gt;&lt;/code&gt;)에 익숙한 일부 프로그래머들에게는 이게 조금 헷갈릴 수도 있다. 이러한 표기법들은 모두 왼쪽에서 오른쪽으로 진행되기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-bash line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Unix의 파이프 표기법&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;lsof&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; Chrome&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 수학과 Haskell에서 함수 합성은 모두 오른쪽에서 왼쪽의 순서로 진행된다. 만약 &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;g\circ f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 “f 다음에 g”로 읽는다면 앞으로 나오는 설명들을 이해하는데 도움이 될 것이다.&lt;/p&gt;
&lt;p&gt;더 명확한 설명을 위해 C 코드를 예시로 들어보겠다. 여기 하나의 A타입의 인자를 받아 B타입의 값을 반환하는 함수 f가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-c line-numbers&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;B &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 B타입 인자를 받아 C타입의 값을 반환하는 또 다른 함수인 g도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-c line-numbers&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;C &lt;span class=&quot;token function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;B b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이들의 합성은 다음과 같이 나타낼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-c line-numbers&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;C &lt;span class=&quot;token function&quot;&gt;g_after_f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;A a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 이렇게 C로 작성된 코드를 통해서도 다시 한번 오른쪽에서 왼쪽으로 진행되며 합성되는 &lt;code class=&quot;language-text&quot;&gt;g(f(a));&lt;/code&gt;를 확인해볼 수 있다.&lt;/p&gt;
&lt;p&gt;C++ 표준 라이브러리에 두 개의 함수를 받아 합성함수를 반환하는 템플릿이 있다면 좋겠지만 그런 템플릿은 존재하지 않는다. 그러면 한번 Haskell로 한번 표현해보면 어떨까?&lt;/p&gt;
&lt;p&gt;여기 A를 인자로 받아 B를 반환하는 함수 f가 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기에 이어 B를 인자로 받아 C를 반환하는 함수 g를 선언하겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 이 두 함수의 합성 함수는 아래와 같이 나타낼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-c line-numbers&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;f&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 Haskell에서 함수의 합성에 대한 개념을 간단하게 표현하는 것을 보면, C++에서 직관적인 함수 개념을 표현하지 못하는 것이 당혹스럽기까지 하다. 심지어 Haskell은 유니코드 문자를 사용하여 아래와 같이 합성을 표현하는 기능까지 제공한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;◦&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;또한 아래와 같이 유니코드 이중 콜론과 화살표 문자도 사용할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; → &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서 이중 콜론은 “~의 타입을 가진다”라는 의미이며, 함수 타입은 두 개의 타입 사이에 화살표를 삽입하여 표현한다. 두 개의 함수를 합성하기 위해서는 그 사이에 &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; 이나 유니코드 &lt;code class=&quot;language-text&quot;&gt;◦&lt;/code&gt; 기호를 사용할 수 있다. 이것이 바로 내가 여러분에게 제공하는 첫 번째 Haskell 수업이다.&lt;/p&gt;
&lt;h2 id=&quot;12-합성의-속성&quot; style=&quot;position:relative;&quot;&gt;1.2 합성의 속성&lt;a href=&quot;#12-%ED%95%A9%EC%84%B1%EC%9D%98-%EC%86%8D%EC%84%B1&quot; aria-label=&quot;12 합성의 속성 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;어떤 카테고리든 상관없이, 합성이라는 개념이 만족시켜야하는 매우 중요한 두 가지 특성이 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-합성에는-결합법칙이-성립해야-한다&quot; style=&quot;position:relative;&quot;&gt;1. 합성에는 결합법칙이 성립해야 한다.&lt;a href=&quot;#1-%ED%95%A9%EC%84%B1%EC%97%90%EB%8A%94-%EA%B2%B0%ED%95%A9%EB%B2%95%EC%B9%99%EC%9D%B4-%EC%84%B1%EB%A6%BD%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;1 합성에는 결합법칙이 성립해야 한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;만약 세 개의 사상인 f, g, h가 있고 이들이 합성될 수 있다면, 괄호 여부, 위치와 상관없이 항상 같은 결과를 반환해야 한다. 수학 표기법에서는 다음과 같이 표현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;h◦(g◦f) = (h◦g)◦f = h◦g◦f&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Haskell에서의 의사(Pseudo) 코드는 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;D&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 함수에 대해서는 비교 연산 정의가 없기 때문에 Pseudo 코드라고 이야기 했다.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- 함수의 결합법칙은 꽤나 당연하고 명확해보이지만, 다른 카테고리에서는 이렇게 명확한 정의가 안 될수도 있다.&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-모든-대상-a에는-항등의-개념을-가진-화살표가-존재해야-한다&quot; style=&quot;position:relative;&quot;&gt;2. 모든 대상 A에는 항등의 개념을 가진 화살표가 존재해야 한다.&lt;a href=&quot;#2-%EB%AA%A8%EB%93%A0-%EB%8C%80%EC%83%81-a%EC%97%90%EB%8A%94-%ED%95%AD%EB%93%B1%EC%9D%98-%EA%B0%9C%EB%85%90%EC%9D%84-%EA%B0%80%EC%A7%84-%ED%99%94%EC%82%B4%ED%91%9C%EA%B0%80-%EC%A1%B4%EC%9E%AC%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;2 모든 대상 a에는 항등의 개념을 가진 화살표가 존재해야 한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이 화살표는 해당 대상에서 나와 다시 해당 대상으로 되돌아가는 루프라고 볼 수 있으며, 항등 화살표가 되기 위해서는 이 화살표를 대상 A에서 시작하거나, 또는 대상 A에서 끝나는 어떤 화살표와 합성하더라도 항상 같은 화살표가 나와야 한다. 대상 A에 대한 항등 화살표는 idA(항등사상. identity on A.)이라고 불린다. 만약 f가 A에서 B로 나아가는 경우 수학 표기로는 아래와 같이 표현할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;mathematica&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-mathematica line-numbers&quot;&gt;&lt;code class=&quot;language-mathematica&quot;&gt;f◦idA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; f
idB◦f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; f&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;p&gt;이를 함수로 다룰 때, 항등 화살표는 받은 인자를 그대로 반환하는 항등 함수로 구현된다. 이러한 특성은 모든 타입에 대해 동일하기 때문에 이 함수는 보편적인 다형성(Universally polymorphic)을 가지고 있다고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;C++에서는 아래와 같은 Template으로 정의해볼 수 있겠다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-cpp line-numbers&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; T &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;T x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 C++에서는 인자의 타입 뿐만 아니라 By reference, By const, By value 등 인자를 전달하는 방식도 함께 고려해야하기 떄문에 실제로는 이렇게 간단하지 않다.&lt;/p&gt;
&lt;p&gt;Haskell에서는 Prelude라고 불리는 표준 라이브러리에 항등함수의 정의가 선언되어있고, 그 정의는 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 Haskell에서는 타입을 타입 변수로 대체하기만 하면 되기 때문에 다형성을 만족시키는 함수를 정의하기가 매우 쉬운 편이다. 위 예시에서 주의해야 할 점이 하나 있는데, Haskell에서 구체적인 타입의 이름은 항상 대문자로 시작하고 타입 변수의 이름은 소문자로 시작한다는 것이다. 즉, 위 예시의 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;는 타입 변수이며 모든 타입을 의미한다.&lt;/p&gt;
&lt;p&gt;Haskell의 함수 정의는 함수 이름 다음에 Formal Paramter가 따라오도록 작성한다. (위 예시에서의 Formal Paramter는 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; 하나이다.) Haskell 초보자들에게 이러한 간결함은 익숙하지 않을 수도 있지만 금방 이 표현이 말이 된다는 것은 이해할 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;함수형 프로그래밍에서 함수를 정의하는 것과 호출하는 것은 빠질 수 없는 필수요소이므로 관련된 문법을 최소한으로 줄인 것이다. 인수 목록에는 괄호가 없을 뿐만 아니라 인수들 간의 쉼표 조차도 없다. (추후 여러 인수를 가진 다인수 함수를 정의할 때 쉼표가 나올 것이다.)&lt;/p&gt;
&lt;p&gt;함수의 본문은 항상 표현식(Expression)이며, 문(Statement)은 존재하지 않는다. 함수의 결과는 바로 이 표현식이며 위 예시에서는 &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;일 것이다. 이게 바로 나의 두 번째 Haskell 레슨이다.&lt;/p&gt;
&lt;p&gt;앞서 언급했던 항등사상에 대한 조건은 Haskell 의사 코드로 다음과 같이 작성해볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-haskell line-numbers&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이쯤 되면 아마 “왜 아무런 기능도 없는 항등 함수 같은 개념이 필요한지”에 대한 질문이 나올 수 있다. 하지만 잘 생각해보자. 그러면 우리는 왜 0이라는 숫자에 관심을 가질까? 0은 아무것도 없음을 나타내는 기호이지 않은가? 심지어 고대 로마인들은 0이 없는 수 체계를 가졌지만 그들은 훌륭한 도로와 수로를 건설할 수 있었으며, 그 중 일부는 오늘날까지도 남아있다.&lt;/p&gt;
&lt;p&gt;사실 0이나 id와 같은 중립적인 값들은 기호로 이루어진 변수들을 다룰 때 매우 유용하다. 그래서 로마인들은 대수학을 잘 하는 편이 아니었지만, 이미 0이라는 개념에 익숙했던 아랍과 페르시아인들은 대수학을 잘 했다. 어쨌든 항등함수는 고차함수(Higher Ordered Function)의 인수로 사용하거나 반환값으로 사용할 때 매우 편리하며, 이러한 고차함수들은 함수를 일종의 기호로써 바라보고 조작하는 것을 가능하게 해준다. 즉, 함수를 사용한 대수학이 가능해지는 것이다.&lt;/p&gt;
&lt;p&gt;요약해보자면, 하나의 카테고리는 대상과 화살표(사상)으로 이루어져 있다. 이러한 화살표들은 합성이 가능하며, 이 합성에는 결합법칙이 성립되어야 한다. 모든 대상들은 항등화살표(항등사상)을 가지고 있으며 이는 합성에 대한 항등원 역할을 한다.&lt;/p&gt;
&lt;h2 id=&quot;13-합성은-프로그래밍의-본질이다&quot; style=&quot;position:relative;&quot;&gt;1.3 합성은 프로그래밍의 본질이다.&lt;a href=&quot;#13-%ED%95%A9%EC%84%B1%EC%9D%80-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98-%EB%B3%B8%EC%A7%88%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;13 합성은 프로그래밍의 본질이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;함수형 프로그래머들은 상당히 독특한 방식으로 문제에 접근한다. 이들은 가장 먼저 철학적인 질문을 던지며 접근을 시작하는데, 예를 들어 인터렉티브 프로그램을 만들어야 한다면 가장 먼저 “상호작용(Interactive)란 무엇인가?”라는 질문을 던지는 식이다.&lt;/p&gt;
&lt;p&gt;콘웨이의 생명 게임(Conway’s Game of Life)을 구현할 때는 아마 인생의 의미에 대해 생각할지도 모르겠다. 그렇다면 이러한 맥락에 따라 나는 이런 질문을 던져보고자 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“프로그래밍이란 무엇인가?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;가장 기본적인 수준에서 이야기해보자면 프로그래밍은 결국 컴퓨터에게 어떠한 행위를 하기 위한 명령을 내리는 것이다. “메모리 주소 x가 가리키는 내용을 EAX 레지스터에 더해라”처럼 말이다.&lt;/p&gt;
&lt;p&gt;그러나 우리가 어셈블리어로 프로그래밍을 할 때조차도 우리가 컴퓨터에게 내리는 명령들은 이것보다는 좀 더 많은 의미를 가지고 있다. 우리는 매우 크고 복잡한 문제를 풀기 위해 컴퓨터를 사용하며, 애초에 그 정도 수준의 문제가 아니었다면 컴퓨터를 사용하지도 않았을 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 우리는 문제들을 어떻게 해결하는가? 우선 우리는 큰 하나의 문제를 작은 여러 개의 문제들로 쪼갠다. 그래도 여전히 이 문제가 너무 크다면 이를 다시 더 작은 문제들로 쪼개고, 계속 이 과정을 계속 반복하며, 최종적으로 우리는 이러한 작은 문제들을 해결할 수 있는 코드를 작성한다.&lt;/p&gt;
&lt;p&gt;그리고 바로 이때 프로그래밍의 본질이 나타난다. 바로 작은 문제들을 해결하는 코드 조각들을 합성하여 더 큰 문제에 대한 해결책을 만들어낸다는 것이다. 만약 문제를 쪼갤 수만 있고 이들을 다시 합칠 수 없다면 애초에 문제를 분할해서 해결한다는 의미도 없었을 것이다.&lt;/p&gt;
&lt;p&gt;이러한 계층적인 분해와 재조립 과정은 컴퓨터가 우리에게 강제한 사고방식이 아니며, 이는 결국 인간의 사고력에 대한 한계를 반영한 것이다. 우리의 뇌는 한 번에 처리할 수 있는 개념의 수가 제한적이다. 심리학에서 많이 인용되는 논문 중 하나인 “&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;The Magical Number Seven, Plus or Minus Two&lt;/a&gt;”에서는 우리가 한 번에 7±2개의 정보 청크(Chunk)만을 기억할 수 있다고 이야기하고 있다.&lt;/p&gt;
&lt;p&gt;물론 인간의 단기기억 능력에 대한 개념들과 주장들은 시간이 지남에 따라 조금씩 변하기는 하지만, 인간의 단기기억 능력이 제한적이라는 사실 하나만큼은 변하지 않는다. 결국 우리는 너무 많은 객체들이 버무려져있는 스파게티 코드를 처리할 수 없다는 것이다.&lt;/p&gt;
&lt;p&gt;우리는 단지 잘 설계된 프로그램이 멋있어 보이기 때문에 설계를 하는 것이 아니라, 제대로 설계를 하지 않으며 우리의 뇌가 코드를 효율적으로 읽기 어렵기 때문에 하는 것이다. 우리는 종종 어떤 코드를 보고 우아하다거나 아름답다고 이야기하지만, 이런 표현들은 결국 우리의 제한된 두뇌를 사용하여 이 코드를 이해하기가 쉽다는 것을 의미한다. 즉, 우아한 코드는 우리의 뇌가 처리할 수 있는 적절한 크기, 그리고 적절한 개수의 청크들을 만들어내는 것이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;그렇다면 프로그램을 구성하는 데에 있어 적합한 청크는 무엇일까? 일단 청크의 면적은 청크의 부피보다 느리게 증가해야 한다. (나는 이 비유를 좋아하는데, 기하학적 대상의 면적이 길이의 제곱에 비례하여 증가한다는 직관 때문이다. 길이의 세제곱에 비례해서 증가하는 부피보다는 느린 속도로 증가한다.)&lt;/p&gt;
&lt;p&gt;여기서 면적이라는 것은 우리가 하나의 청크를 합성하는 데에 필요한 정보이며, 부피는 우리가 청크를 구현하는 데에 필요한 정보이다. 즉, 하나의 청크를 구현하고 나면 그 구현의 세부 정보는 모두 잊어버리고 다른 청크와의 상호작용에만 집중할 수 있도록 하자는 것이다.&lt;/p&gt;
&lt;p&gt;객체지향 프로그래밍에서의 면적은 클래스 선언이나 추상 인터페이스이지만, 함수형 프로그래밍에서는 함수의 선언이라고 볼 수 있다. (조금 단순화해서 설명했지만, 결국 이게 핵심이다.)&lt;/p&gt;
&lt;p&gt;카테고리 이론은 각 대상의 내부를 살피는 것을 적극적으로 막기 때문에 극단적인 예시라고 볼 수도 있다. 카테고리 이론에서의 대상은 굉장히 추상적인 객체이다.&lt;/p&gt;
&lt;p&gt;어떤 대상에 대해서 알 수 있는 것은 그저 다른 대상과의 관계, 즉 화살표를 사용하여 어떤 식으로 연결되어있는지 뿐이다. 이는 인터넷 검색 엔진이 서로 연결되어있는 링크를 분석하여 각 웹사이트들의 순위를 매기는 방식과 동일하다. 객체지향 프로그래밍에서의 이상적인 객체는 추상적인 인터페이스(면적에 대한 특성만 가지고 부피가 없는 녀석)를 통해서만 볼 수 있으며, 메소드는 카테고리 내 화살표의 역할을 수행한다. 만약 객체를 다른 객체와 합성하기 위해 객체의 구현을 까봐야 하는 순간 이 프로그래밍 패러다임의 장점은 사라지게 된다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[[번역] 프로그래머를 위한 카테고리 이론 - 0. 서문]]></title><description><![CDATA[얼마 전부터 나는 프로그래머를 대상으로 하는 카테고리 이론에 대한 책을 작성하려는 아이디어를 떠올렸다. 즉 이 책은 컴퓨터 과학자가 아닌 프로그래머, 그리고 과학자보다는 엔지니어들을 대상으로 하는 책이다.]]></description><link>https://evan-moon.github.io/2024/01/30/category-theory-for-programmers-0-preface/</link><guid isPermaLink="false">20240130-category-theory-for-programmers-0-preface</guid><pubDate>Tue, 30 Jan 2024 11:45:32 GMT</pubDate><content:encoded>&lt;p&gt;얼마 전부터 나는 프로그래머를 대상으로 하는 카테고리 이론에 대한 책을 작성하려는 아이디어를 떠올렸다. 즉 이 책은 컴퓨터 과학자가 아닌 프로그래머, 그리고 과학자보다는 엔지니어들을 대상으로 하는 책이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;분명 과학과 엔지니어링 사이에는 큰 간극이 존재한다. 게다가 나는 그 간극의 양쪽 끝에서 일해보기도 했기 때문에 다른 사람들에게는 이런 아이디어가 미친 생각처럼 보일 수도 있을 것이다. 하지만 나는 항상 이 이론을 제대로 설명하고 싶다는 강한 의지를 가지고 있었다.&lt;/p&gt;
&lt;p&gt;나는 단순한 설명의 달인인 물리학자 리처드 파인만을 굉장히 존경해왔다. 물론 내가 파인만처럼 잘 설명할 수는 없겠지만 그래도 한번 최선을 다 해볼 것이다.&lt;/p&gt;
&lt;p&gt;우선 카테고리 이론을 학습하려는 독자들에게 동기를 부여하기 위해 이 서문을 작성함으로써, 이 서문이 앞으로 활발한 토론과 피드백을 구할 수 있는 초석이 되기를 바란다.&lt;/p&gt;
&lt;p&gt;우선 다음 몇 문단을 통해 이 책이 여러분을 위해 작성된 것이며 당신이 “남는 시간”을 투자하는 것만으로도 가장 추상적인 수학 분야 중 하나를 배우는 것에 대해 전혀 거부감을 가질 필요가 없다는 것을 보여주려고 한다. 나의 이러한 낙관론은 관찰 끝에 나온 몇 가지 사실들에 기반을 두고 있다.&lt;/p&gt;
&lt;p&gt;첫째, 카테고리 이론은 매우 유용한 프로그래밍 아이디어들의 보물 창고이다. 이미 오래전부터 Haskell 프로그래머들은 이 아이디어들을 사용해왔고, 이제는 슬슬 이 아이디어들이 다른 언어로도 퍼지고 있기는 하지만, 이 과정은 느려도 너무 느리다. 우리는 이 전파 속도를 가속시켜야 한다.&lt;/p&gt;
&lt;p&gt;둘째, 수학에는 많은 분야가 있으며, 이 분야들은 모두 각기 다른 대상에 대한 연구를 하고 있다. 물론 여러분이 미적분학이나 대수학 같은 것들에 대한 알레르기가 있을 수는 있겠지만, 그렇다고 해서 카테고리 이론을 즐길 수 없는 것은 아니다.&lt;/p&gt;
&lt;p&gt;사실 카테고리 이론은 어떤 구체적인 계산과 같은 내용이 아닌 추상적인 구조에 대한 이야기를 하고 있기 때문에 특히 프로그래머의 사고방식과 잘 맞는 수학 분야이다. 카테고리 이론은 프로그램을 합성 가능하도록(composable) 만들 수 있는 구조에 대해서 다룬다.&lt;/p&gt;
&lt;p&gt;합성이라는 것은 카테고리 이론을 이루는 가장 근본적인 개념이며, 프로그래밍의 본질이기도 하다. 옛날옛적 몇몇 위대한 엔지니어가 서브루틴이라는 개념을 도입하기 이전부터 우리는 이미 합성이라는 행위를 하고 있었다.&lt;/p&gt;
&lt;p&gt;예전 구조적 프로그래밍의 원칙은 코드 블록이라는 개념을 합성할 수 있도록 만들어줌으로써 프로그래밍에 대한 혁신을 불러왔다. 그리고 이후 OOP(객체지향 프로그래밍)가 등장했으며, 이 또한 객체들을 합성하는 방법에 대한 이야기를 하고 있다.&lt;/p&gt;
&lt;p&gt;하지만 FP(함수형 프로그래밍)는 이를 넘어 함수와 대수적인 데이터 구조들을 합성할 수 있게 해주고, 심지어 동시성(concurrency) 또한 합성할 수 있도록 해준다. 이는 지금까지의 다른 프로그래밍 패러다임으로는 거의 불가능한 일이다.&lt;/p&gt;
&lt;p&gt;마지막으로 나는 수학을 프로그래머들에게 보다 재미있게 전달할 수 있는 비밀 무기를 하나 가지고 있다.&lt;/p&gt;
&lt;p&gt;만약 당신이 전문적인 수학자라면 모든 가정을 명확하게 정의하고 모든 주장을 정확하게 설명할 수 있어야 하며, 여기서 파생된 증명들은 엄격하게 구성할 수 있어야 한다. 하지만 오히려 이러한 수학의 특징들로 인해 일반인들이 수학과 관련된 논문이나 책을 이해하기란 결코 쉽지 않은 것이 현실이다.&lt;/p&gt;
&lt;p&gt;나는 물리학자 출신이며, 물리학은 이러한 수학의 틀을 벗어난 직관적 사고를 통해 놀라운 발전을 이루어냈다는 말을 먼저 하고 싶다. 수학자들은 위대한 물리학자 P.A.M 디랙이 미분 방정식을 풀기 위해 즉흥적으로 만들어낸 디랙-델타 함수를 보고 비웃었지만, 결국 디랙의 아이디어가 구체적인 형식을 갖춘 뒤 분포 이론이라는 완전히 새로운 미적분 분야로 정립된 이후에 그들은 더 이상 웃지 못했다.&lt;/p&gt;
&lt;p&gt;물론 Hand-waving하게 설명을 할 때는 잘못된 설명을 할 가능성이 있으므로, 이 책에서 나는 직관적인 설명이나 개념 뒤에는 사실 탄탄한 수학적 이론이 함께 존재한다는 것을 이야기해줄 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hand wave는 “상대방이 이해하기 쉽도록 어려운 것을 간단하게 풀어서 설명한다”는 관용 표현이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 이 글은 프로그래머들을 위한 카테고리 이론에 대한 이야기를 하고 있으니, 나는 앞으로 설명할 모든 주요 개념을 컴퓨터 코드와 함께 설명할 것이다.&lt;/p&gt;
&lt;p&gt;아마 여러분도 알고 있겠지만 함수형 언어는 명령형 언어에 비해 수학에 더 가까우며, 더 강력하게 추상화를 할 수 있는 힘을 가져다준다. 그래서 자연스럽게 “카테고리 이론을 이해하려면 Haskell을 배워야해”라고 말하고 싶은 유혹에 빠지게 된다.&lt;/p&gt;
&lt;p&gt;하지만 오히려 이런 생각들이 마치 함수형 프로그래밍 이외의 분야에서는 카테고리 이론이 적용될 수 없다는 오해를 불러일으킬 수도 있기 때문에 나는 가급적이면 많은 C++ 예제를 함께 제공해보려고 한다.&lt;/p&gt;
&lt;p&gt;물론 몇 가지 난해한 문법들을 극복해야할 수도 있고, 장황한 패턴들도 존재할 수 있으며, 높은 레벨의 추상화 대신 복사 붙여넣기를 해야할 수도 있겠지만, 뭐 그게 원래 C++ 프로그래머들이 하는 일이 아닌가?&lt;/p&gt;
&lt;p&gt;하지만 한 가지 알아둬야 할 점은 여러분이 Haskell 프로그래머가 될 필요까지는 없어도 C++로 구현할 아이디어들을 스케치하고 문서화하기 위해서는 결국은 Haskell이 필요하기 때문에 여전히 Haskell이 중요하기는 하다는 것이다.&lt;/p&gt;
&lt;p&gt;사실 이것이 내가 Haskell을 시작했던 이유이다. Haskell의 간결한 문법과 강력한 타입 시스템은 내가 C++의 템플릿, 데이터 구조 그리고 알고리즘을 이해하고 구현하는데에 큰 도움이 된다고 생각한다. 하지만 여러분이 이미 Haskell을 알고 있다고 기대하기는 어렵기 때문에 이런 것들에 대해서는 천천히 소개하고 진행하며 설명해나가려고 한다.&lt;/p&gt;
&lt;p&gt;만약 여러분이 경력직 개발자라면 “지금까지 나는 카테고리 이론이나 함수형 개념같은 것들을 몰라도 코딩하는데는 문제가 없었는데, 도대체 뭐가 변한걸까?”라는 생각이 들 수도 있다. 하지만 이미 여러분은 알게 모르게 기존의 명령형 언어들에 계속 해서 함수형 개념이 도입되고 있다는 사실을 느끼고 있을 것이다.&lt;/p&gt;
&lt;p&gt;객체 지향 프로그래밍의 최후의 보루로 여겨졌던 자바에도 C++의 람다(Lambda)와 같은 개념이 추가되었으며, C++의 람다는 변화하는 세상을 따라잡기 위해 몇 년에 한번씩 새로운 표준이 나올만큼 미친 속도로 발전하고 있다.&lt;/p&gt;
&lt;p&gt;이러한 모든 현상들은 급격한 변화, 흔히 물리학자들이 이야기하는 “상전이(Phase Transition)”를 준비하는 과정이다. 물을 계속 가열하면 결국 끓기 시작하는 것처럼 말이다. 우리는 이제 점점 더 뜨거워지는 물 속에서 계속 헤엄을 칠지, 혹은 다른 대안을 찾아보기를 시작해야할지 결정해야하는 개구리의 입장에 놓여있다.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a43196a41329474bae8b5d061ef59f6e/ad059/1.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 71.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/aAAwDAQACEAMQAAAB7KpCWoRT/8QAGhABAAIDAQAAAAAAAAAAAAAAAQACAxMiMf/aAAgBAQABBQIeq5BZYU1Q8//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAICAwAAAAAAAAAAAAAAAAAhAhEQMmH/2gAIAQEABj8Clwq8I2Yz/8QAHBAAAgICAwAAAAAAAAAAAAAAAREAITFBEFFh/9oACAEBAAE/Icoa7QjyA73woKHlx6LH1GFjM//aAAwDAQACAAMAAAAQ38//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAXEQADAQAAAAAAAAAAAAAAAAABECEx/9oACAECAQE/EKMX/8QAHBABAAICAwEAAAAAAAAAAAAAAQARIUEQMVGR/9oACAEBAAE/EFwom1B1AmSgCqvzh6jdg1HEhGQiOb89ISBbUKJ//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;1&quot; title=&quot;&quot; src=&quot;/static/a43196a41329474bae8b5d061ef59f6e/c08c5/1.jpg&quot; srcset=&quot;/static/a43196a41329474bae8b5d061ef59f6e/0913d/1.jpg 160w,
/static/a43196a41329474bae8b5d061ef59f6e/cb69c/1.jpg 320w,
/static/a43196a41329474bae8b5d061ef59f6e/c08c5/1.jpg 640w,
/static/a43196a41329474bae8b5d061ef59f6e/ad059/1.jpg 758w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;이러한 큰 변화를 주도하는 힘 중에 하나는 바로 멀티코어(multicore) 혁명이다. 기존의 주류 프로그래밍 패러다임이었던 객체지향 프로그래밍은 동시성과 병렬성 영역에서 아무런 이점을 제공하지 못 하며, 오히려 위험한 버그를 발생시킬 수 있는 설계를 하게 되기 쉽상이다. 결국 객체지향의 기본 컨셉은 불필요한 정보를 은닉하는 것인데, 이러한 특성이 공유(Share), 변이(Mutation)와 결합되면 결국 데이터 레이스(Data race)가 발생하게 된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 역주&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;데이터 레이스(Data Race)란 여러 개의 쓰레드나 프로세스가 하나의 자원에 접근하려고 할 때 발생하는 Race Condition을 의미한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 뮤텍스(Mutex)와 뮤텍스가 보호할 데이터를 결합하는 것은 좋은 아이디어이지만, 불행하게도 락(Lock)은 합성이 불가능하고 락을 은닉했다가는 데드락(Deadlock)이 발생할 가능성이 커져 디버깅을 더더욱 어렵게 만든다.&lt;/p&gt;
&lt;p&gt;하지만 꼭 이러한 동시성 이슈가 아니더라도, 점점 더 복잡해지는 소프트웨어 시스템이 명령형 패러다임의 확장성의 한계가 어디까지인지를 시험하고 있다. 간단히 이야기하자면 사이드이펙트의 관리가 점점 더 어려워지고 있다.&lt;/p&gt;
&lt;p&gt;사이드이펙트를 발생시키는 함수가 편리하기도 하고 작성하기도 쉽다는 사실은 인정한다. 원칙적으로 이러한 이펙트들은 함수의 이름이나 주석으로 표현될 수 있다. 예를 들어 SetPassword 나 WriteFile 같은 함수들은 명백하게 함수 외부의 상태들은 변경하고 사이드이펙트를 발생시키지만, 이미 우리는 이런 함수들을 다루는 것에 익숙하다.&lt;/p&gt;
&lt;p&gt;하지만 이렇게 사이드이펙트를 발생시키는 함수들을 다른 사이드이펙트를 발생시키는 함수와 합성하다보면 점점 문제가 복잡해진다. 사이드이펙트가 본질적으로 나쁘다는 이야기는 아니지만, 이런 이펙트들은 예측하기가 어렵기 때문에 큰 규모의 어플리케이션에서는 관리하기가 거의 불가능하다는 것이 문제이다. 즉, 모든 명령형 프로그래밍은 사이드이펙트를 피할 수 없지만, 사이드이펙트는 확장이 불가능하다는 것이다.&lt;/p&gt;
&lt;p&gt;하드웨어의 변화, 그리고 점점 더 복잡해지는 소프트웨어의 특성으로 인해 우리는 프로그래밍의 기반을 이루는 것이 무엇인가에 대해 다시 한번 생각해볼 필요가 생겼다.&lt;/p&gt;
&lt;p&gt;마치 유럽의 위대한 고딕 대성당을 짓던 건축가들처럼 우리는 재료와 구조에 대해 한계까지 기술을 연마해왔다. 현재까지도 미완성된 프랑스의 보베 대성당은 이러한 인간의 한계에 대한 투쟁을 잘 보여주는 사례이다. 보베 대성당은 이전에 지어진 그 어떤 성당보다 더 높고 경이로운 성당을 짓기 위해 건설되었지만 몇 차례의 붕괴 사고를 겪었다. 철제와 목재로 지지대를 만들어 계속 붕괴가 진행되는 것은 막았지만 여전히 많은 문제가 있다는 것은 분명하다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 360px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f68f06bd8feb123d3becedf20b45b561/158ba/2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 133.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAwH/xAAXAQEAAwAAAAAAAAAAAAAAAAABAAID/9oADAMBAAIQAxAAAAGRk2yeGxYk1lZaSEJ//8QAGhABAQEBAAMAAAAAAAAAAAAAARECAAMQMf/aAAgBAQABBQJtzI46C4PGN7CiukNw9P3/xAAWEQEBAQAAAAAAAAAAAAAAAAARABD/2gAIAQMBAT8BI3//xAAXEQADAQAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/AWbf/8QAHRAAAgEEAwAAAAAAAAAAAAAAABEBAhAgISIxMv/aAAgBAQAGPwJzImdnodXKLaNpY//EABsQAQACAwEBAAAAAAAAAAAAAAEAIRExQVFx/9oACAEBAAE/ITSsvPIFiNzB1GxtjyaEPJbWozTerikHwhAMIRsf/9oADAMBAAIAAwAAABCf0g7/xAAXEQADAQAAAAAAAAAAAAAAAAAAAREQ/9oACAEDAQE/EE8LFn//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/EGrzSH//xAAeEAEAAwACAwEBAAAAAAAAAAABABEhMUFRYXGB8P/aAAgBAQABPxA1GsX3aH7dxIPbctPMtBZlj5++4qcGuWEJu8wia8aR5Ha4zqHmUWt1/EPg8F3kLu0y4kFFH01G8W19neM//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2&quot; title=&quot;&quot; src=&quot;/static/f68f06bd8feb123d3becedf20b45b561/158ba/2.jpg&quot; srcset=&quot;/static/f68f06bd8feb123d3becedf20b45b561/0913d/2.jpg 160w,
/static/f68f06bd8feb123d3becedf20b45b561/cb69c/2.jpg 320w,
/static/f68f06bd8feb123d3becedf20b45b561/158ba/2.jpg 360w&quot; sizes=&quot;(max-width: 360px) 100vw, 360px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;임시 조치로 붕괴를 방지하고 있는 보베 대성당의 모습&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;현대적인 관점에서 보면 고딕 구조물이 재료 공학, 컴퓨터 모델링, 유한요소해석, 일반 수학과 물리학의 도움 없이도 성공적으로 완성되었다는 것은 기적에 가깝다. 나는 후대의 사람들도 우리가 복잡한 운영체제, 웹 서버, 그리고 인터넷 인프라를 구축하는 과정에서 사용해왔던 프로그래밍 기술들에 대해서 감탄해주길 바란다.&lt;/p&gt;
&lt;p&gt;아니, 그들은 감탄할 수 밖에 없을 것이다. 왜냐하면 우리는 매우 얄팍한 이론적 기초 위에서 이 모든 것들을 만들어왔기 때문이다. 하지만 우리는 결국 앞으로 더 나아가기 위해 이러한 기초들을 제대로 고쳐야 할 필요가 있다.&lt;/p&gt;
&lt;h2 id=&quot;원문-보기&quot; style=&quot;position:relative;&quot;&gt;원문 보기&lt;a href=&quot;#%EC%9B%90%EB%AC%B8-%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;원문 보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://unglueit-files.s3.amazonaws.com/ebf/e90890f0a6ea420c9825657d6f3a851d.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Category Theory for Programmers&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[Can I Ever Be Free from Others' Judgment?]]></title><description><![CDATA[Humans are said to be social animals who live within relationships. This is especially pronounced in East Asian cultures, where people tend to define themselves through their relationships with others, and commonly make the mistake of letting others’ perceptions and evaluations determine their self-worth. Having lived for over 30 years within the culture of South Korea, an East Asian country, I’m not immune to this tendency. No matter how much I try not to care about others’ judgments, I still find myself shaken by them from time to time.]]></description><link>https://evan-moon.github.io/2023/11/21/how-to-overcome-being-self-conscious/en/</link><guid isPermaLink="false">20231121-how-to-overcome-being-self-conscious-en</guid><pubDate>Tue, 21 Nov 2023 12:58:27 GMT</pubDate><content:encoded>&lt;p&gt;Humans are said to be social animals who live within relationships. This is especially pronounced in East Asian cultures, where people tend to define themselves through their relationships with others, and commonly make the mistake of letting others’ perceptions and evaluations determine their self-worth.&lt;/p&gt;
&lt;p&gt;Having lived for over 30 years within the culture of South Korea, an East Asian country, I’m not immune to this tendency. No matter how much I try not to care about others’ judgments, I still find myself shaken by them from time to time.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Of course, since we spend most of our lives belonging to some group or another, we can never be entirely free from such evaluations. Even freelancers face judgment from their industry, and self-employed people can’t escape reviews on platforms or evaluations within their local community networks.&lt;/p&gt;
&lt;p&gt;But if you let these evaluations dictate your life too much, you end up losing your true self. This is especially easy to fall into if you’re someone who wants to be loved by everyone, because others’ evaluations are inherently subjective, and pleasing everyone is very difficult. &lt;em&gt;(You’d probably need to be on the level of Admiral Yi Sun-sin to pull that off.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I believe that only by protecting the self-esteem and convictions of “me” as an autonomous subject can you establish your identity and advance toward self-actualization. If you let others’ subjective standards determine your worth, maintaining a mature sense of self becomes very difficult. Ultimately, my value is something my own reason determines.&lt;/p&gt;
&lt;p&gt;In this post, I want to talk about the struggles I’ve faced under others’ evaluations and the methods I’ve been working on to overcome them.&lt;/p&gt;
&lt;h2 id=&quot;the-burden-of-others-evaluations&quot; style=&quot;position:relative;&quot;&gt;The burden of others’ evaluations&lt;a href=&quot;#the-burden-of-others-evaluations&quot; aria-label=&quot;the burden of others evaluations permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let me start by talking about the situations where I found myself preoccupied with others’ evaluations. Some of these will resonate with many readers, while others may be unique to my circumstances — but I imagine everyone has grappled with concerns from others’ judgments at some point.&lt;/p&gt;
&lt;h3 id=&quot;broader-responsibility-means-more-diverse-evaluators&quot; style=&quot;position:relative;&quot;&gt;Broader responsibility means more diverse evaluators&lt;a href=&quot;#broader-responsibility-means-more-diverse-evaluators&quot; aria-label=&quot;broader responsibility means more diverse evaluators permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My recent career has been in a leadership role rather than as an IC (Individual Contributor). Being a leader means you set direction, build empathy, and mobilize people to solve problems no individual could tackle alone. But that expanded responsibility also means receiving evaluations from a far wider range of people than when I was an IC.&lt;/p&gt;
&lt;p&gt;A leader’s decisions affect many people across the organization, and the number of stakeholders you interact with is larger than what an IC encounters. While an IC is primarily evaluated by the colleagues they directly work with, a leader receives evaluations from people throughout the entire organization, proportional to the broader impact of their decisions.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e46810019d235256fffc4e442cf29a91/89557/dri.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.12500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAADD0lEQVR42m1TX0iaURS/1UxNS5dbzubGosBt1NgYtcEaDQY9BIte3BiLBXsQKdrDYsTYgzDoYZRr/aEIqaigB8PFbAjh1JaJYmnln7TMxL85NXSuCQny7dzwGz3swuW7597f+Z1zfud8aG5urgwhRFlfX3+0u7v7QS6XX56YmCghCKIAnVn9/f2M6elp9uzsLEMikZQB9q3NZnuK36xW68W1tbVKqVRK/+dwcHCgABLC4XC8wLZOp6OBWUi+j46OMklbrVbXJ5NJIhgMunAg8LX7fL6wQqGoRSTI6XS2wKVsY2ODJxKJKJBpEb4nM4VK+BDkOQQsHhoaonp9vs9AJIKngv39fReQB8Cn7mxVmJiRP58DcGsgEOiBMmn4YmlpqUGv129OTU1dwTaPxyvBONhUnL1KpaKOjY1V4NLaQAMpBnG53FNC0Igdj8e3s9ks4fV6G/MZluWzLTDL5YKTeExxHAp94iNE9/v95yHDWyMjI5XIZDI9BEHfe398b4g7HD0OufwSztTtdrdHo9GPIDwXEyqVynrArQmbm8vtev14Kp0mErEYYVEqn/mDwflcLkdAY18ig9H42q9SVWeSyQhuSioQUIA/HXQsce/sfPV4PCtCoZAOJfG3trbEmNxjMr3D2F+JRNa4MH/PHwq9iUQiLq1W+xhptNrxoF53P5NO/8kB6OToaBV8mK+6uiqhUVGXy5Xo6+vjguDMycnJm+U1NWVChIridvuTuNVajwNAlVWAEwwMDFxAKysrLYODg4K409Z+HIl8CRgMtU1NTVhslMlkrqZSqer8qDSazeag0WjkdnZ2Mje3txU7e3sSXI3dbo8dHh7+lslkDxCMidpisbR+W1y8q9FoViHJIjyg5NiQCzcFSDn4PDMzc+dnNEqEQiEH/ilAloVwOKwZHh6uQqAPUyAQlELrby8vL7eLxeIKIKPnu12INz7j2cOBent7WVAB22AwtIGujRwOp7S7u5va0dFBAywNMRiMCgqFUldcXHwD/K7B5qP/r9MBZ7FYbPiQWCzHdfIHwGP1F/WavDK/RBI6AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;dri&quot; title=&quot;&quot; src=&quot;/static/e46810019d235256fffc4e442cf29a91/6af66/dri.png&quot; srcset=&quot;/static/e46810019d235256fffc4e442cf29a91/69538/dri.png 160w,
/static/e46810019d235256fffc4e442cf29a91/72799/dri.png 320w,
/static/e46810019d235256fffc4e442cf29a91/6af66/dri.png 640w,
/static/e46810019d235256fffc4e442cf29a91/d9199/dri.png 960w,
/static/e46810019d235256fffc4e442cf29a91/21b4d/dri.png 1280w,
/static/e46810019d235256fffc4e442cf29a91/89557/dri.png 1928w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;A leader&apos;s decisions affect and are evaluated by more people across the organization, commensurate with their expanded responsibility.&lt;br&gt;Considering this burden, being a leader isn&apos;t always as glamorous as it seems.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;For this reason, I found myself exposed to evaluations from a much more diverse set of people than when I was an IC. It’s an environment where caring about those evaluations comes easily.&lt;/p&gt;
&lt;p&gt;What’s interesting is how subjective these evaluations tend to be. When a leader proposes direction A, some people might say “I think they’re doing a good job” while others might say “I don’t think that approach will work.”&lt;/p&gt;
&lt;p&gt;Of course, a leader is just another human, so their decisions are also driven by intuition shaped by personal views, values, experience, and available information. Even when quantitative data is available, data doesn’t speak for itself: interpreting it and making decisions still comes down to human intuition. A leader doesn’t always present &lt;em&gt;the&lt;/em&gt; right answer; they present what they &lt;em&gt;believe&lt;/em&gt; to be the right direction based on their own criteria.&lt;/p&gt;
&lt;p&gt;Likewise, evaluations of a leader’s decisions are conducted through each evaluator’s own subjective criteria. Different people can view the same phenomenon and arrive at different assessments. If an evaluator tends toward conformity or introversion, they might even anchor their evaluation on the majority opinion or the views of someone they trust.&lt;/p&gt;
&lt;p&gt;When the evaluation target is something quantitative — like OKR, NSM, or KPI achievement — you can make evaluations without much subjectivity. But when it comes to directions proposed before results are in, or missions that are hard to quantify like organizational culture, binary success/failure thinking doesn’t apply, and subjective factors inevitably become the basis of evaluation.&lt;/p&gt;
&lt;p&gt;In summary: a leader’s values realistically may not earn everyone’s empathy. And evaluations of those decisions and values are often influenced more by perceptions of the leader as a person (likability and trust capital) than by the decisions themselves. This is especially true when the organization lacks shared foundational values.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/91b1a1491e66a4045794d72dae0055b2/acb04/review.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 32.49999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAcuAqD//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAEFAn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAEDH/2gAIAQEABj8CKv/EABcQAQEBAQAAAAAAAAAAAAAAAAEAYRH/2gAIAQEAAT8hdbpF2//aAAwDAQACAAMAAAAQA8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAgIDAAAAAAAAAAAAAAABABEhUaHR8P/aAAgBAQABPxB0FJqhnsPcNcPmf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;review&quot; title=&quot;&quot; src=&quot;/static/91b1a1491e66a4045794d72dae0055b2/c08c5/review.jpg&quot; srcset=&quot;/static/91b1a1491e66a4045794d72dae0055b2/0913d/review.jpg 160w,
/static/91b1a1491e66a4045794d72dae0055b2/cb69c/review.jpg 320w,
/static/91b1a1491e66a4045794d72dae0055b2/c08c5/review.jpg 640w,
/static/91b1a1491e66a4045794d72dae0055b2/acb04/review.jpg 750w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;So sometimes in the course of work, you receive evaluations like this on anonymous platforms.&lt;br&gt;&quot;TS&quot; in the original referred to Toss, and I was the only developer in that organization who had come from Toss.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;For example, imagine a leader with the value that “underperformers should be let go and high performers should be compensated accordingly.” Some might evaluate this as “Isn’t that obvious in a capitalist market economy?” while others might say “We spend most of our day at work, that feels too cold.”&lt;/p&gt;
&lt;p&gt;Debating right and wrong on such values is largely pointless. There are no correct answers when it comes to ideology. Everyone simply advocates for the direction they believe in.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/88380e1d1c538b6f85ed9691d2d203c3/db7b4/politics.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 50.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACA//EABYBAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABGhGM6Nd4/8QAGRAAAwADAAAAAAAAAAAAAAAAAAECEBJB/9oACAEBAAEFAphM0gcyjjx//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8Bqv/EABgQAAIDAAAAAAAAAAAAAAAAAAAyASAx/9oACAEBAAY/AsFgWn//xAAcEAEAAQQDAAAAAAAAAAAAAAABABARIUFhcYH/2gAIAQEAAT8hbtcvM1CdxrOsJOPCn//aAAwDAQACAAMAAAAQD/8A/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EIkQ/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/EKVmf//EAB4QAQACAQQDAAAAAAAAAAAAAAEAESExQVGBcbHx/9oACAEBAAE/ELiAUsYO9NoE3Dt8gYa0JQ4HuY48QgABwHiUW4NX3P/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;politics&quot; title=&quot;&quot; src=&quot;/static/88380e1d1c538b6f85ed9691d2d203c3/db7b4/politics.jpg&quot; srcset=&quot;/static/88380e1d1c538b6f85ed9691d2d203c3/0913d/politics.jpg 160w,
/static/88380e1d1c538b6f85ed9691d2d203c3/cb69c/politics.jpg 320w,
/static/88380e1d1c538b6f85ed9691d2d203c3/db7b4/politics.jpg 559w&quot; sizes=&quot;(max-width: 559px) 100vw, 559px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;This is easy to understand if you think about the parliament of a multi-party democracy.&lt;br&gt;Among the various ideologies different parties champion, which one is correct?&lt;br&gt;There is no correct answer. Each party simply argues for what they believe is right, for their own interests or the nation&apos;s.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;But ultimately, the person in a leadership role must propose a specific direction they believe will create the greatest impact for the organization, based on their own values. Even in organizations that value diversity, without at least a foundational direction, you end up with chaos where everyone is just shouting what they individually believe is right.&lt;/p&gt;
&lt;p&gt;So a leader must strike the right balance between direction and diversity: proposing a mission that team members can empathize with, then welcoming diverse opinions on how to achieve it, maximizing collective intelligence.&lt;/p&gt;
&lt;p&gt;The direction I proposed was probably just one of many possible directions, and naturally, the many people within the organization each evaluated me according to their own subjective standards and values.&lt;/p&gt;
&lt;p&gt;With more people evaluating me and their expectations and assessments diverging, it was an environment where caring about those evaluations came far more easily than before.&lt;/p&gt;
&lt;h3 id=&quot;positive-evaluations-and-preconceptions-from-the-blog&quot; style=&quot;position:relative;&quot;&gt;Positive evaluations and preconceptions from the blog&lt;a href=&quot;#positive-evaluations-and-preconceptions-from-the-blog&quot; aria-label=&quot;positive evaluations and preconceptions from the blog permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When I first started this blog in 2017, I was just an ordinary developer who enjoyed writing as a hobby. That hasn’t changed in 2023 — I’m still an ordinary developer. But having written for so long, people occasionally recognize me in daily life, talk to me about my posts, or even tell me they’re a fan.&lt;/p&gt;
&lt;p&gt;Most people who know of my existence probably discovered me through my writing rather than through actually working or spending time with me.&lt;/p&gt;
&lt;p&gt;People who first encounter me through the blog tend to think I’m a very serious, thoughtful person. This is probably because the written medium and my writing style don’t reveal much emotion, and my posts tend to cover academic topics or my personal philosophy.&lt;/p&gt;
&lt;p&gt;That side is certainly part of me, but the person who exists in real life isn’t all seriousness. I’m actually closer to someone who just lives the way they want, rather than chasing the conventional values society prescribes: money, prestige, pedigree, credentials.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e29d08b6cd6fef0018fbd6525801f5ac/acb04/star.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 236.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAvABQDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAECAwQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQMA/9oADAMBAAIQAxAAAAHy6xbbVui8lZix1CLzQWN1kn//xAAbEAEAAgMBAQAAAAAAAAAAAAABABECAxAxEv/aAAgBAQABBQKq59Yc9XQEuHroSNQLXDaSk4mrrqCf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwFf/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAEQUQIREv/aAAgBAgEBPwE6whN3G1Z//8QAHxAAAQIGAwAAAAAAAAAAAAAAAQAQAhEhMTKRM6Gi/9oACAEBAAY/Artx9tIIVKs2QKspKsXp6GLT5jS//8QAIBABAAICAgEFAAAAAAAAAAAAAQARITEQUUFhcYGRsf/aAAgBAQABPyF2AfaW9zCejPbgEgLZUm2s6jfY/ILBYX5YwbhdgxLVIgDbGA8EKcku+vqWMuLxXDtXfKf/2gAMAwEAAgADAAAAEHA/PcAv/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERURD/2gAIAQMBAT8QIxEWcjw//8QAHREBAAIABwAAAAAAAAAAAAAAAQAxEBEhgZGh8P/aAAgBAgEBPxCoMaLyxqZKvWAxb20//8QAHhABAAMAAQUBAAAAAAAAAAAAAQARITFBUWFxkaH/2gAIAQEAAT8QfAM1dziLFKT3GpKIBX13g03j7jZTgZWzdFKAw9TmdXGgw6DxAYCgeA8srQFCiT5BcHhRpxKkbALa1m+YwUaPsMZNDtPJHgQHiCisrbBs/VcC0O8I6BdkP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;star&quot; title=&quot;&quot; src=&quot;/static/e29d08b6cd6fef0018fbd6525801f5ac/c08c5/star.jpg&quot; srcset=&quot;/static/e29d08b6cd6fef0018fbd6525801f5ac/0913d/star.jpg 160w,
/static/e29d08b6cd6fef0018fbd6525801f5ac/cb69c/star.jpg 320w,
/static/e29d08b6cd6fef0018fbd6525801f5ac/c08c5/star.jpg 640w,
/static/e29d08b6cd6fef0018fbd6525801f5ac/acb04/star.jpg 750w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;I might come across as scholarly on the blog,&lt;br&gt;but I&apos;m just an ordinary guy in his 30s who enjoys gaming with friends in the evening.&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;These positive evaluations and preconceptions have undeniably been helpful in my life. They’ve led to good career opportunities: job offers, side projects, and more.&lt;/p&gt;
&lt;p&gt;But these evaluations don’t always bring only good things. In my case, the positive preconceptions actually caused me quite a bit of anguish.&lt;/p&gt;
&lt;p&gt;Throughout my career as a developer, I have never once thought of myself as an outstanding developer. I am absolutely not a perfect human being. I have plenty of shortcomings and many experiences of failure when I encountered problems beyond my capabilities.&lt;/p&gt;
&lt;p&gt;There are so many talented people around me that I still think of myself as just another average developer wandering around Gangnam or Pangyo.&lt;/p&gt;
&lt;p&gt;But when I step away from the internet and meet people in real life, I occasionally hear things like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I want to become a developer like you.”&lt;/p&gt;
&lt;p&gt;“Wow, it’s like meeting a celebrity.”&lt;/p&gt;
&lt;p&gt;“Someone at your level doesn’t have to worry about making a living, right?”&lt;/p&gt;
&lt;p&gt;“Can’t you just pick whichever company you want?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The people who say these things are readers who love and resonate with my writing and who are cheering me on, and for that, I’m truly grateful. Having someone empathize with your thoughts and values and root for you is a genuinely happy thing.&lt;/p&gt;
&lt;p&gt;But hearing these things, alongside gratitude, I also find myself thinking:&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 496px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b4ec7a5ca3af9bd5b634dc29a2234796/6a372/surprised.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwAEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAUEgOnZ4/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAAxESEyH/2gAIAQEAAQUC6NrXayHqRCfGY5n/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAACAwAAAAAAAAAAAAAAAAAAARARMf/aAAgBAQAGPwIq2zI2P//EABwQAQADAAIDAAAAAAAAAAAAAAEAESExQVFhsf/aAAgBAQABPyGpCl637jRWPsM3ksa+9yu1DeZ//9oADAMBAAIAAwAAABBYH//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxAxf//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAgEBPxAVf//EABoQAQADAQEBAAAAAAAAAAAAAAEAESFBMVH/2gAIAQEAAT8QCBJCi0uxSFmnK+oa9MC9VhaV4iVWau17M1032f/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;surprised&quot; title=&quot;&quot; src=&quot;/static/b4ec7a5ca3af9bd5b634dc29a2234796/6a372/surprised.jpg&quot; srcset=&quot;/static/b4ec7a5ca3af9bd5b634dc29a2234796/0913d/surprised.jpg 160w,
/static/b4ec7a5ca3af9bd5b634dc29a2234796/cb69c/surprised.jpg 320w,
/static/b4ec7a5ca3af9bd5b634dc29a2234796/6a372/surprised.jpg 496w&quot; sizes=&quot;(max-width: 496px) 100vw, 496px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Wait, I&apos;m not quite at that level...?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;In reality, I haven’t achieved financial freedom, I’m not a celebrity. I’m just an ordinary developer with lots of worries who happens to enjoy writing.&lt;/p&gt;
&lt;p&gt;But as I’ve mentioned multiple times, evaluation is conducted according to the evaluator’s subjective criteria. People who first encounter me through the blog naturally lack detailed information about who I really am or what I’m actually capable of, so they evaluate me based on the surface-level information available to them, like blog posts or code on GitHub.&lt;/p&gt;
&lt;p&gt;The problem from my perspective is that I have no way of knowing how inflated these evaluations are. Being human, when someone has expectations of me, I naturally want to live up to them and not disappoint. But if others’ evaluations are set far above my actual capabilities, satisfying them becomes difficult, and this psychology turns into pressure.&lt;/p&gt;
&lt;p&gt;For a while, whenever someone recognized me or offered positive evaluations, I’d find myself straightening up, watching my words and behavior, becoming hyper-conscious of others’ perceptions in order to live up to their evaluations. &lt;del&gt;&lt;em&gt;(In plain terms, it was basically celebrity syndrome.)&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;
&lt;h2 id=&quot;live-as-the-master-of-your-own-life&quot; style=&quot;position:relative;&quot;&gt;Live as the master of your own life&lt;a href=&quot;#live-as-the-master-of-your-own-life&quot; aria-label=&quot;live as the master of your own life permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Whether the evaluations are positive or negative, living a life focused on others’ judgments is stressful. Some people may derive fulfillment from others’ recognition, but fundamentally, other people’s hearts lie outside your sphere of control, and things don’t go the way you want more often than they do.&lt;/p&gt;
&lt;p&gt;Moreover, focusing too much on others’ evaluations can shake your own values and cause you to lose direction. In my case, pouring too much energy into these evaluations led me to act against convictions I had long believed in, and the resulting stress manifested physically.&lt;/p&gt;
&lt;p&gt;As you go through life and build your career, the number of people who remember you naturally grows through the work you’ve done. More people remembering you means more people who might evaluate you, and the more positive evaluations you receive, the easier it becomes to advance your interests within the vast organization that is society.&lt;/p&gt;
&lt;p&gt;But that doesn’t mean you should outsource the fundamental evaluation of who you are entirely to others. As I said, others’ evaluations fundamentally lie outside your sphere of control.&lt;/p&gt;
&lt;p&gt;I, too, found that the more I cared about these evaluations, the more I felt myself losing my center. I spent a long time thinking about how to break free. The first thing I did to reclaim that freedom was to classify what I can control and what I cannot, accept that distinction, and let go of my attachment to what I cannot control.&lt;/p&gt;
&lt;h3 id=&quot;clearly-distinguish-what-you-can-and-cannot-control&quot; style=&quot;position:relative;&quot;&gt;Clearly distinguish what you can and cannot control&lt;a href=&quot;#clearly-distinguish-what-you-can-and-cannot-control&quot; aria-label=&quot;clearly distinguish what you can and cannot control permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you look around carefully as you go through life, you’ll realize that the things you can truly control are fewer than you’d think. What you can control is mostly things where you are the subject: your thoughts, your emotions. Things involving other people beyond yourself are mostly in the uncontrollable domain.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/75882324a1834fcc0529ebf9f418eded/07a9c/out-of-control.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADrklEQVR42m1Vy44bVRB1gsQCFKRI8F9ILIKikdgEIfiJWWYNkZJVEKMoSlgwiDEIEQmYCbEzEzsittuP+P3qd7vbY/yM+97DqY5n5EnSUrna11V1T516OJXaegBcFm3b9ofj8fhaGIb3R6NRnTINgmBGafLsR8oO3z/a9nnrOfvBcZxPPc+r0AkMqi3LQr/fB8/h+z5OT081z+V7gxdd2/heEtkOdmkT7OZ0OsV8Pkc6nVYHBwfx3t6evn3nDo6OjnCQTuv9/f348PBQMbheLpdwXfdb+r93Hmx3dzdBRkQ3lVKgjkejQAki1/XgUttE6brUtpUgdT1P0GrarrXWINJb28BS5OMzSaPX66l2u62pMQoCBEzR80dw/DFsbwwvCHnuIQh8DIdDdLtdsY0nkwnPgi+SYPl8/gMeFIWrk5MTlclk8Tyf560R+v4cTS9Gw9NouApNN0bPmyeBy4Yh9sjlckqCk6pGsVi8miLcz2ezmaSgwjBCFBEFddNeoNRbwOjPqaeoDJeoDBbUr1C35rQZJ7biQ3Sx8BlF0Y0UP+5tyI0p8MjVMFgiU7TwMP0Y9376E7d/2MejbAU/P3pGOcHjFwMMglViK3yKrxSSsX6RgDVByFs03+EznYazRs16hZq5RHkwx3HZwVPDeo2Q8tJa0yaGS37DUCTSwiP9rRR77D/mjlqthlKxgFbPTDir00F4E50tmTh63rlwJmKxUC9rVRQKBZRKJQwGA50ioVMJ1mq1USkbaPdtOulzp7q9JkIbf+WaRL16K2Cr1UC1Wk3ENE0t/VeXZn4z5TM0UoxMcYjDfJvFmW0FXJO/1ymzsJoTJCk7wuEDKQrHLaaw9zz03BlqjkqchcOnhol//u2h0JmwjRRqtkLHXSSjKCK+UhSC+00Q7iwWyY+KNyGkBGyFlsv0POBZxcXfuQb+eFLGk8IATR9oOitmEiW24kPfeLVaScCvU/xyhVNSlZZh5ysKOp02TMtBz1+iuqm09GN1uEDXWyTVNYcDsed0dRXpkqXRrdfrnyTTwqDXhVROjcpms8hQ2q1WgsD1Q9j+JBF5F0pkJMvlMo6Pj2VaYq47sG2+urBpePCdDDrRrgldy63CT5CIdx7ojDcpBPlf019SvXthOfCRfXaZm+SWkCs7jxQoIdvfCnJWABHZlcI9fb43DOP9CwG3FySddujQFWMGlxW1jSo523TFkPLlOxfsm7uRt1+l8w0G+ZVOruy+DToq/3ei/4YUffyuv4D/AbN8BMBkHMxNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;out of control&quot; title=&quot;&quot; src=&quot;/static/75882324a1834fcc0529ebf9f418eded/6af66/out-of-control.png&quot; srcset=&quot;/static/75882324a1834fcc0529ebf9f418eded/69538/out-of-control.png 160w,
/static/75882324a1834fcc0529ebf9f418eded/72799/out-of-control.png 320w,
/static/75882324a1834fcc0529ebf9f418eded/6af66/out-of-control.png 640w,
/static/75882324a1834fcc0529ebf9f418eded/d9199/out-of-control.png 960w,
/static/75882324a1834fcc0529ebf9f418eded/21b4d/out-of-control.png 1280w,
/static/75882324a1834fcc0529ebf9f418eded/07a9c/out-of-control.png 1440w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;Proper self-awareness starts with recognizing where the boundaries of your control lie&lt;br&gt;and where the uncontrollable domain begins.&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;In other words, how others evaluate me is a concept beyond my sphere of control. Of course, taking action to persuade or build empathy with someone in order to change their mind falls within my control, but the outcome of that action remains outside it.&lt;/p&gt;
&lt;p&gt;At the outset, I said that people who want to be loved by everyone easily lose themselves. That’s because the desire to be loved by everyone tends to manifest as obsession with others’ evaluations — a concept that lies beyond one’s control.&lt;/p&gt;
&lt;p&gt;The people around us hold a diverse range of values and ideologies, and this is true of any organization. Even when looking at the same phenomenon, different people can have different evaluations and emotional responses.&lt;/p&gt;
&lt;p&gt;This reality is not something I can control. If I can’t control it, why obsess over it? No matter what I do, the people who will like me will like me, and those who won’t, won’t. Is there anything more self-destructive than desperately struggling to obtain something you can never have?&lt;/p&gt;
&lt;p&gt;The “focus on impact” in life is about concentrating on doing better in the areas I can control, and about pulling things from the uncontrollable domain into the controllable domain wherever possible. Devoting excessive attention to things I currently cannot control is essentially spending a limited resource (focus) on something meaningless.&lt;/p&gt;
&lt;p&gt;Recognizing and accepting these limitations connects to metacognition: being aware of what you know versus what you don’t, what you can do versus what you can’t. Awareness of your control boundaries is essentially recognizing the limits of the influence that “I” as a subject can exert on the world.&lt;/p&gt;
&lt;h3 id=&quot;in-the-end-it-is-your-mind-that-moves&quot; style=&quot;position:relative;&quot;&gt;In the end, it is your mind that moves&lt;a href=&quot;#in-the-end-it-is-your-mind-that-moves&quot; aria-label=&quot;in the end it is your mind that moves permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;One day, a banner was fluttering in the wind at a temple. Two monks began arguing about the sight. One monk said, “The banner is moving.” The other insisted, “The wind is moving.” The debate went back and forth with neither yielding.&lt;/p&gt;
&lt;p&gt;Then Huineng, the Sixth Patriarch, spoke: “Neither the wind nor the banner is moving. It is your minds that are moving.” The two monks were stunned into silence.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Gateless Gate&lt;/em&gt;, Case 29: Not the Wind, Not the Banner.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What was Huineng trying to say in this episode? The &lt;em&gt;Gateless Gate&lt;/em&gt; is a collection of koans that pose questions without providing answers, so the book won’t tell you.&lt;/p&gt;
&lt;p&gt;Reading this episode, my thought was: “Phenomena merely exist as they are; interpreting them is a subjective human judgment.”&lt;/p&gt;
&lt;p&gt;The Avatamsaka Sutra, a scripture of Mahayana Buddhism, speaks of the core concept &lt;em&gt;ilche yushimjo&lt;/em&gt; (一切唯心造), which literally means “all things are created solely by the mind.” I believe this is the key to living as the master of your own life.&lt;/p&gt;
&lt;p&gt;Generally, the situations where people suffer from others’ evaluations involve negative rather than positive judgments. So imagine a scenario where someone is spreading gossip about you behind your back.&lt;/p&gt;
&lt;p&gt;That gossip is almost certainly not 100% factual. Like most gossip, it’s probably a mixture of partial truth embellished with misunderstanding and subjective interpretation. Few people bother to verify the facts with the person involved — plain truth is far less entertaining than truth with added drama.&lt;/p&gt;
&lt;p&gt;If you learned about this gossip, you might be swept up in emotions — frustration, feeling wronged, anger, betrayal. But where did these emotions originate? From the environment or situation where someone is spreading gossip about you? From the person doing the spreading?&lt;/p&gt;
&lt;p&gt;No. Frustration, indignation, anger, betrayal: these emotions start within your own mind. These are your emotions, and as I discussed, your emotions lie squarely within your controllable domain. Regardless of what’s happening around you, it’s you who generates these emotions and makes yourself suffer.&lt;/p&gt;
&lt;p&gt;This is the meaning of ilche yushimjo — all things are created solely by the mind. Of course, you may need to make value judgments about whether the situation itself is right or wrong, and if wrong, establish action items to address it. But you must not forget that devising a strategy to solve the problem and executing it are separate matters from your emotions.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6271f4799e9572d8153bd8477492a94b/65f94/water.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 132.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAwACAQX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAH3TQzFqFJMh3Y//8QAGRAAAQUAAAAAAAAAAAAAAAAAIAAQESFB/9oACAEBAAEFAg1rUB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAVEAEBAAAAAAAAAAAAAAAAAAAgMf/aAAgBAQAGPwJ0/wD/xAAbEAEBAAIDAQAAAAAAAAAAAAABABEhEDFxgf/aAAgBAQABPyFl3iSZNGZ6sY7z+Xrhm//aAAwDAQACAAMAAAAQswMw/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHBABAAMBAAMBAAAAAAAAAAAAAQARMSFBUXGx/9oACAEBAAE/EDxhUWuUQbioV8S0Jwv8mp2j2QMBdN5+RV9bGYmp/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;water&quot; title=&quot;&quot; src=&quot;/static/6271f4799e9572d8153bd8477492a94b/65f94/water.jpg&quot; srcset=&quot;/static/6271f4799e9572d8153bd8477492a94b/0913d/water.jpg 160w,
/static/6271f4799e9572d8153bd8477492a94b/cb69c/water.jpg 320w,
/static/6271f4799e9572d8153bd8477492a94b/65f94/water.jpg 420w&quot; sizes=&quot;(max-width: 420px) 100vw, 420px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;The water in the glass simply sits there — how you choose to see it is a matter of the mind.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Ilche yushimjo might sound detached from reality. But I think it may be the most necessary message for modern people suffering under the weight of constant evaluation and comparison.&lt;/p&gt;
&lt;p&gt;Of course, learning that someone is spreading gossip about you or attacking you from behind anonymity is an emotionally difficult situation. But whether or not you’re suffering, unless you rationally analyze the root cause and take action to address it, the situation itself won’t improve.&lt;/p&gt;
&lt;p&gt;In other words, what matters is improving the unhealthy organizational state that allows gossip to spread — not the fact that you became the subject of it.&lt;/p&gt;
&lt;p&gt;So just approach it plainly: think about what caused the situation. If the cause is within your controllable domain, take swift action. If it’s not, focus only on whether you can pull it into the controllable domain.&lt;/p&gt;
&lt;p&gt;If you understand ilche yushimjo and can keep your emotions squarely within the controllable domain, you gain the ability to observe the phenomena around you with a more rational eye, focused on the essence of the problem.&lt;/p&gt;
&lt;p&gt;This isn’t about eliminating emotions. It’s about not letting your emotions depend on external variables like surrounding situations or environment. Regardless of your circumstances, your emotions are yours to control. You can be happy or unhappy regardless of what’s happening around you.&lt;/p&gt;
&lt;h3 id=&quot;remember-that-most-evaluations-are-two-sided&quot; style=&quot;position:relative;&quot;&gt;Remember that most evaluations are two-sided&lt;a href=&quot;#remember-that-most-evaluations-are-two-sided&quot; aria-label=&quot;remember that most evaluations are two sided permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you habitually pay attention to evaluations around you, it’s easy to focus more on negative evaluations than positive ones. Humans are wired to react sensitively to threats from negative information, a kind of negativity bias. &lt;em&gt;(They say newspapers and news programs sell negative stories better than positive ones, too.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you’re not yet skilled at emotional control, this can spiral into self-deprecating thoughts like “I’ll never make it” and drag you into a pit of despair. Once you fall into a cycle of giving yourself negative feedback, climbing out on your own isn’t easy.&lt;/p&gt;
&lt;p&gt;But in reality, evaluations of any specific person are mostly two-sided. That is, most people don’t evaluate you as purely bad or purely good — they see both strengths and shortcomings.&lt;/p&gt;
&lt;p&gt;This is only natural, when you think about it. Every human has both strengths and weaknesses, so you’re likely to receive positive evaluations on your strengths and critical ones on your weaknesses.&lt;/p&gt;
&lt;p&gt;Of course, biases like &lt;a href=&quot;https://en.wikipedia.org/wiki/Actor%E2%80%93observer_asymmetry&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;actor-observer bias&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Self-serving_bias&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;self-serving bias&lt;/a&gt; can lead people to judge others more harshly than themselves. But fundamentally, any rational adult will make a somewhat balanced evaluation of a specific person. &lt;em&gt;(If someone only has negative things to say about a particular person, they likely lack the ability to view phenomena from multiple perspectives — I’d recommend keeping your distance.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Internalizing the fact that most evaluations are two-sided and balanced does a great deal to protect your self-esteem. Of course, focusing only on positive information can blind you to reality, so striking the right balance is important. And this isn’t just a hypothetical — it’s the reality playing out around you right now.&lt;/p&gt;
&lt;p&gt;What matters is maintaining your own balanced perspective: reinforce what others evaluate positively about you, and improve what they evaluate negatively. There’s no need to let your mood worsen or improve because of these evaluations. As I’ve been saying, simply acknowledge the plain fact that an evaluation occurred, and take action items to reinforce or improve accordingly.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Like everyone else, I’ve faced countless evaluations throughout my life. This was true not just as a developer, but also during my younger days as a b-boy and sound engineer.&lt;/p&gt;
&lt;p&gt;No matter how little someone values relationships, we all inevitably interact with other humans within the vast network of society. And in that process, it’s only natural that others will form evaluations of us.&lt;/p&gt;
&lt;p&gt;But if you become too consumed by these evaluations, you risk losing your true self. Others’ evaluations and advice may sometimes warrant adjustments to your values or life direction, but the decision-making authority must belong solely to you. You must never delegate that authority to others.&lt;/p&gt;
&lt;p&gt;The words and evaluations we direct at others cost us nothing. Others can evaluate you, but they almost never bear responsibility for those evaluations.&lt;/p&gt;
&lt;p&gt;In other words, they’re not deliberating over their judgments with the same gravity as, say, deciding whether to buy a billion-won apartment.&lt;/p&gt;
&lt;p&gt;So I’d recommend not giving those evaluations too much weight. Ultimately, my value is determined by my own reason, and I believe any mature adult with sound values should do the same.&lt;/p&gt;
&lt;p&gt;As I’ve discussed, there are no correct answers when it comes to human thought and values. These ideas simply exist, and everyone’s judgment of them can differ.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Is working at a startup the right choice? Or a large corporation?”&lt;/p&gt;
&lt;p&gt;“Is trading work-life balance for high income the right choice? Or is protecting your time over money?”&lt;/p&gt;
&lt;p&gt;“Is equality of opportunity right? Or equality of outcome?”&lt;/p&gt;
&lt;p&gt;No one can provide correct answers to these ideological questions. You simply choose according to the values you believe in.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So stop trying to find the right answer or trying to be loved by everyone. Follow the convictions you believe in, walk the path you think is right, and maintain your own pace.&lt;/p&gt;
&lt;p&gt;Comparing yourself to others, getting emotionally invested in situations that won’t matter in hindsight, struggling for things you can’t have right now: the one making yourself suffer through all of this is yourself.&lt;/p&gt;
&lt;p&gt;If you take full control of yourself and observe the phenomena around you rationally, you might realize that you’ve been overcomplicating what are, in truth, rather simple problems.&lt;/p&gt;
&lt;p&gt;This concludes my post: Can I Ever Be Free from Others’ Judgment?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[나는 타인의 평가에서 자유로울 수 있을까]]></title><description><![CDATA[인간은 관계 속에서 살아가는 사회적 동물이라고 한다. 특히 사람들과의 관계 속에서 나 자신을 정의하는 특성이 강한 동양 문화권에서 살아가는 사람들은 타인의 시선과 평가를 의식하고 이에 따라 자신의 가치를 결정하는 실수를 흔히들 저지르고는 한다. 필자 또한 지난 30여년 간 대한민국이라는 동아시아 국가의 문화 속에서 살아온 한 명의 인간인 만큼 이러한 관념에서 자유로울 수 없어, 타인의 평가에 대해 신경을 쓰지 않으려고 해도 어쩔 수 없이 이에 흔들리는 상황을 경험하고는 한다.]]></description><link>https://evan-moon.github.io/2023/11/21/how-to-overcome-being-self-conscious/</link><guid isPermaLink="false">20231121-how-to-overcome-being-self-conscious</guid><pubDate>Tue, 21 Nov 2023 12:58:27 GMT</pubDate><content:encoded>&lt;p&gt;인간은 관계 속에서 살아가는 사회적 동물이라고 한다. 특히 사람들과의 관계 속에서 나 자신을 정의하는 특성이 강한 동양 문화권에서 살아가는 사람들은 타인의 시선과 평가를 의식하고 이에 따라 자신의 가치를 결정하는 실수를 흔히들 저지르고는 한다.&lt;/p&gt;
&lt;p&gt;필자 또한 지난 30여년 간 대한민국이라는 동아시아 국가의 문화 속에서 살아온 한 명의 인간인 만큼 이러한 관념에서 자유로울 수 없어, 타인의 평가에 대해 신경을 쓰지 않으려고 해도 어쩔 수 없이 이에 흔들리는 상황을 경험하고는 한다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;물론 우리는 대부분의 인생을 어떠한 집단 속에 속해서 살아가게 되니 이러한 평가에서 온전히 자유로울 수는 없을 것이다. 비단 필자와 같은 직장인이 아닌 프리랜서라고 해도 본인이 일하는 업계라는 집단의 평가를 받을 수 있으며, 자영업을 하는 사람이라고 해도 특정 플랫폼 내에서의 리뷰나 동네의 로컬 네트워크 내에서의 평가에서 자유로울 수 없다.&lt;/p&gt;
&lt;p&gt;그러나 너무 이러한 평가들에 휘둘려 살게되면 진정한 나 자신을 잃어버리게 되는 일이 발생한다. 특히 모두에게 사랑받고 싶다는 마음을 가진 사람이라면 더더욱 이런 상황에 휩쓸리기 쉬운데, 어차피 타인의 평가는 매우 주관적이라 모두의 입맛에 맞추기란 굉장히 어렵기 때문이다. &lt;small&gt;(모두에게 사랑받고 싶다면 이순신 장군 정도의 위인은 되어야 하지 않을까)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;필자는 온전히 “나”라는 주체의 자존감과 신념을 지켜내야만 자신의 자아정체성을 확립하고 자아실현의 단계까지 나아갈 수 있다고 믿는다. 만약 나의 가치를 타인의 주관적 잣대에 의존하게 된다면 성숙한 자아를 유지하기 쉽지 않을 것이다. 결국 내 가치는 내 이성이 결정하는 것이다.&lt;/p&gt;
&lt;p&gt;이번 포스팅에서는 필자가 타인의 평가 속에서 겪었던 어려움과 이를 이겨내려고 노력하고 있는 방법에 대해서 이야기해보려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;타인의-평가에-대한-부담&quot; style=&quot;position:relative;&quot;&gt;타인의 평가에 대한 부담&lt;a href=&quot;#%ED%83%80%EC%9D%B8%EC%9D%98-%ED%8F%89%EA%B0%80%EC%97%90-%EB%8C%80%ED%95%9C-%EB%B6%80%EB%8B%B4&quot; aria-label=&quot;타인의 평가에 대한 부담 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;먼저 필자가 타인의 평가를 신경썼던 경우들에 대한 이야기를 먼저 해보려고 한다. 이 중에서는 아마 독자 여러분이 공감하실만한 내용도, 필자만이 경험했던 특수한 상황도 있겠지만, 아마 누구나 한번 쯤은 타인의 평가에서부터 출발한 고민을 해보았으리라 생각한다.&lt;/p&gt;
&lt;h3 id=&quot;넓어진-책임만큼-다양한-이들의-평가를-받는-상황&quot; style=&quot;position:relative;&quot;&gt;넓어진 책임만큼 다양한 이들의 평가를 받는 상황&lt;a href=&quot;#%EB%84%93%EC%96%B4%EC%A7%84-%EC%B1%85%EC%9E%84%EB%A7%8C%ED%81%BC-%EB%8B%A4%EC%96%91%ED%95%9C-%EC%9D%B4%EB%93%A4%EC%9D%98-%ED%8F%89%EA%B0%80%EB%A5%BC-%EB%B0%9B%EB%8A%94-%EC%83%81%ED%99%A9&quot; aria-label=&quot;넓어진 책임만큼 다양한 이들의 평가를 받는 상황 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자의 최근 커리어는 IC(Individual Contributor)가 아닌 조직을 이끄는 리더의 역할이었다. 리더라는 역할은 다른 사람들에게 방향성을 제시하고 공감시켜 움직이게 만듦으로써 혼자서는 해결할 수 없었던 문제들을 해결할 수 있다는 장점도 있지만, 역설적으로 이렇게 넓어진 책임만큼 IC일 때에 비해 더 다양한 이들에게 다양한 시각의 평가를 받을 수 있는 역할이기도 하다.&lt;/p&gt;
&lt;p&gt;아무래도 리더의 의사결정들은 조직 내의 많은 사람들에게 영향을 주게 되기도 하고, 평소 접하는 이해관계자 자체가 IC에 비해서 많기도 하다. 즉, 리더는 의사결정의 영향력이 IC에 비해 큰 만큼 주로 직접적으로 함께 일하는 동료들의 평가를 받게되는 IC와 달리 조직 전체에 속해있는 사람들에게서 비롯된 다양한 평가를 받게 된다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e46810019d235256fffc4e442cf29a91/89557/dri.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.12500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAADD0lEQVR42m1TX0iaURS/1UxNS5dbzubGosBt1NgYtcEaDQY9BIte3BiLBXsQKdrDYsTYgzDoYZRr/aEIqaigB8PFbAjh1JaJYmnln7TMxL85NXSuCQny7dzwGz3swuW7597f+Z1zfud8aG5urgwhRFlfX3+0u7v7QS6XX56YmCghCKIAnVn9/f2M6elp9uzsLEMikZQB9q3NZnuK36xW68W1tbVKqVRK/+dwcHCgABLC4XC8wLZOp6OBWUi+j46OMklbrVbXJ5NJIhgMunAg8LX7fL6wQqGoRSTI6XS2wKVsY2ODJxKJKJBpEb4nM4VK+BDkOQQsHhoaonp9vs9AJIKngv39fReQB8Cn7mxVmJiRP58DcGsgEOiBMmn4YmlpqUGv129OTU1dwTaPxyvBONhUnL1KpaKOjY1V4NLaQAMpBnG53FNC0Igdj8e3s9ks4fV6G/MZluWzLTDL5YKTeExxHAp94iNE9/v95yHDWyMjI5XIZDI9BEHfe398b4g7HD0OufwSztTtdrdHo9GPIDwXEyqVynrArQmbm8vtev14Kp0mErEYYVEqn/mDwflcLkdAY18ig9H42q9SVWeSyQhuSioQUIA/HXQsce/sfPV4PCtCoZAOJfG3trbEmNxjMr3D2F+JRNa4MH/PHwq9iUQiLq1W+xhptNrxoF53P5NO/8kB6OToaBV8mK+6uiqhUVGXy5Xo6+vjguDMycnJm+U1NWVChIridvuTuNVajwNAlVWAEwwMDFxAKysrLYODg4K409Z+HIl8CRgMtU1NTVhslMlkrqZSqer8qDSazeag0WjkdnZ2Mje3txU7e3sSXI3dbo8dHh7+lslkDxCMidpisbR+W1y8q9FoViHJIjyg5NiQCzcFSDn4PDMzc+dnNEqEQiEH/ilAloVwOKwZHh6uQqAPUyAQlELrby8vL7eLxeIKIKPnu12INz7j2cOBent7WVAB22AwtIGujRwOp7S7u5va0dFBAywNMRiMCgqFUldcXHwD/K7B5qP/r9MBZ7FYbPiQWCzHdfIHwGP1F/WavDK/RBI6AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;dri&quot; title=&quot;&quot; src=&quot;/static/e46810019d235256fffc4e442cf29a91/6af66/dri.png&quot; srcset=&quot;/static/e46810019d235256fffc4e442cf29a91/69538/dri.png 160w,
/static/e46810019d235256fffc4e442cf29a91/72799/dri.png 320w,
/static/e46810019d235256fffc4e442cf29a91/6af66/dri.png 640w,
/static/e46810019d235256fffc4e442cf29a91/d9199/dri.png 960w,
/static/e46810019d235256fffc4e442cf29a91/21b4d/dri.png 1280w,
/static/e46810019d235256fffc4e442cf29a91/89557/dri.png 1928w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;리더의 의사결정은 IC에 비해 넓어진 책임만큼 조직 내의 더 많은 사람들에게 영향을 끼치고 평가를 받게 된다.&lt;br&gt;이런 부담을 생각해보면 리더를 한다는 게 좋기만 한 것도 아닌 것 같다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그런 이유로 인해 필자 또한 IC로 일할 때보다는 상대적으로 다양한 사람들에게 다양한 평가를 받는 환경에 노출되게 되었고, 아무래도 자연스럽게 이런 평가들에 대해 신경을 쓰게 되기 쉬운 환경에 노출되었다.&lt;/p&gt;
&lt;p&gt;여기서 재밌는 점은 이러한 평가들이 꽤나 주관적으로 이루어진다는 것이다. 리더가 A라는 방향성을 제시했을 때 이 방향성이나 가치관에 대하여 어떤 사람은 “잘 하고 있는 것 같다”라고 할 수도 있고 어떤 사람은 “저런 식으로 하면 안될 것 같다”라고 이야기할 수도 있다.&lt;/p&gt;
&lt;p&gt;물론 리더도 결국 한 명의 인간이니 리더의 의사결정들 또한 개인의 주관, 가치관, 경험, 인지한 정보 등에서 발현된 직관에 의해 진행된다. 정량적 데이터를 참고할 수 있는 상황이라면 좋겠지만 데이터 자체가 정답을 말해주는 것은 아니니 이를 해석해서 진행하는 의사결정은 결국 인간의 직관에서 비롯된다. 즉, 리더는 늘 정답을 제시하는 것이 아닌 본인의 기준에 따라 정답이라고 생각하는 방향을 제시한다는 것이다.&lt;/p&gt;
&lt;p&gt;마찬가지로 리더의 의사결정에 대한 평가들도 각 평가자의 주관에서 비롯된 기준에 의해 진행된다. 같은 현상을 보더라도 이 현상에 대한 평가는 이를 평가하는 인간 객체마다 각각 다를 수 있으며, 심지어 평가자의 중립성 또는 내향성이 강하다면 조직 내 다수의 의견이나 자신이 신뢰하는 다른 인간 객체의 의견에 편승하여 평가하는 경우도 있다.&lt;/p&gt;
&lt;p&gt;물론 평가 대상이 OKR, NSM, KPI와 같이 정량적인 목표 달성 여부라면 주관성이 포함되어있지 않은 평가를 할 수 있겠지만, 아직 결과가 나오지 않았을 때 목표를 달성하기 위해 제시된 방향성 또는 조직 문화와 같이 정량적 목표를 잡기 어려운 미션에 대해서는 성공/실패와 같은 이분법적 사고를 할 수가 없으니 결국 주관적인 요소들이 평가의 근거가 되기 쉬운 것이다.&lt;/p&gt;
&lt;p&gt;정리하자면 현실적으로 리더의 가치관은 모두의 공감을 받기 어려울 수도 있으며, 생각보다 이러한 의사결정이나 가치관에 대한 평가는 그것 자체보다는 오히려 리더라는 인간에 대한 평가, 즉 호감도나 신뢰 자산과 같은 요소들이 더 큰 영향을 끼치는 경우가 많다. 특히 조직 전체가 추구하는 공통적인 가치가 부재한 경우라면 더더욱 그렇다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/91b1a1491e66a4045794d72dae0055b2/acb04/review.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 32.49999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAcuAqD//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAEFAn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAEDH/2gAIAQEABj8CKv/EABcQAQEBAQAAAAAAAAAAAAAAAAEAYRH/2gAIAQEAAT8hdbpF2//aAAwDAQACAAMAAAAQA8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAgIDAAAAAAAAAAAAAAABABEhUaHR8P/aAAgBAQABPxB0FJqhnsPcNcPmf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;review&quot; title=&quot;&quot; src=&quot;/static/91b1a1491e66a4045794d72dae0055b2/c08c5/review.jpg&quot; srcset=&quot;/static/91b1a1491e66a4045794d72dae0055b2/0913d/review.jpg 160w,
/static/91b1a1491e66a4045794d72dae0055b2/cb69c/review.jpg 320w,
/static/91b1a1491e66a4045794d72dae0055b2/c08c5/review.jpg 640w,
/static/91b1a1491e66a4045794d72dae0055b2/acb04/review.jpg 750w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;그래서 일을 하다보면 익명 플랫폼 내에서 이런 평가를 받기도 한다.&lt;br&gt;&quot;ㅌㅅ&quot;의 원문은 토스였는데, 이 조직에 토스를 경험하고 온 개발자는 필자 뿐이었다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;예를 들어 “일을 못하는 사람은 회사에서 해고 당하고 일을 잘하는 사람은 그에 걸맞는 보상을 받아야 한다”라는 가치관을 가진 리더가 있다고 생각해보자. 누군가는 이 리더의 생각에 대해 “자본주의 시장경제체제에서 그건 당연한 것 아니야?”라고 평가할 수 있는 반면, 누군가는 “그래도 회사는 우리가 하루의 대부분을 보내는 곳인데, 너무 차가운 것 같아”라고 평가할 수도 있다.&lt;/p&gt;
&lt;p&gt;이러한 가치들에 대한 옳고 그름을 따지는 것은 사실 의미가 없다. 이러한 이데올로기에는 정답이 없기 때문이다. 그저 각자가 옳다고 믿는 방향성을 외칠 뿐이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/88380e1d1c538b6f85ed9691d2d203c3/db7b4/politics.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 50.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACA//EABYBAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABGhGM6Nd4/8QAGRAAAwADAAAAAAAAAAAAAAAAAAECEBJB/9oACAEBAAEFAphM0gcyjjx//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8Bqv/EABgQAAIDAAAAAAAAAAAAAAAAAAAyASAx/9oACAEBAAY/AsFgWn//xAAcEAEAAQQDAAAAAAAAAAAAAAABABARIUFhcYH/2gAIAQEAAT8hbtcvM1CdxrOsJOPCn//aAAwDAQACAAMAAAAQD/8A/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EIkQ/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/EKVmf//EAB4QAQACAQQDAAAAAAAAAAAAAAEAESExQVGBcbHx/9oACAEBAAE/ELiAUsYO9NoE3Dt8gYa0JQ4HuY48QgABwHiUW4NX3P/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;politics&quot; title=&quot;&quot; src=&quot;/static/88380e1d1c538b6f85ed9691d2d203c3/db7b4/politics.jpg&quot; srcset=&quot;/static/88380e1d1c538b6f85ed9691d2d203c3/0913d/politics.jpg 160w,
/static/88380e1d1c538b6f85ed9691d2d203c3/cb69c/politics.jpg 320w,
/static/88380e1d1c538b6f85ed9691d2d203c3/db7b4/politics.jpg 559w&quot; sizes=&quot;(max-width: 559px) 100vw, 559px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이는 다당제 민주주의 국가의 의회를 생각해보면 쉽게 이해할 수 있다.&lt;br&gt;여러 정당이 외치는 이념 중 어떤 것이 정답인가?&lt;br&gt;정답은 없다. 그저 각자의 이익을 위해 혹은 국가의 이익을 위해 옳다고 생각하는 방향을 주장할 뿐이다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;하지만 결국 리더라는 역할을 맡은 사람은 자신의 가치관에 의거하여 조직에 가장 큰 임팩트를 만들어낼 수 있다고 생각하는 특정한 방향성을 제시해야만 한다. 아무리 다양성을 중시하는 조직이라도 기초가 되는 방향성조차 없다면 그저 각자가 자신이 옳다고 생각하는 것들을 외치고만 있는 혼란스러운 상황이 되어버리기 쉽기 때문이다.&lt;/p&gt;
&lt;p&gt;그래서 리더는 팀원들을 공감시킬 수 있는 미션, 즉 최소한의 방향성을 제시하고 이를 공감시킨 후 미션을 달성하기 위한 다양한 의견을 받아들이는 등 집단지성을 극대화할 수 있는 방향성과 다양성 간의 적절한 밸런스를 잡아야 한다.&lt;/p&gt;
&lt;p&gt;아마 필자가 제시했던 방향성도 그저 이런 수많은 방향성 중 하나였을테니 당연히 이 방향성에 대해 조직 내부에 있는 수많은 인간 객체들은 각자 저마다의 주관적 기준과 가치관에 의거하여 필자에 대한 평가를 했을 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 필자를 평가하는 사람 자체도 많아지고 필자에 대한 각자의 기대치나 평가가 갈리는 환경에 노출되다보니 아무래도 예전에 비하면 이러한 평가들에 대해 신경을 쓰게 되기 쉬운 환경이었던 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;블로그로-인한-긍정적-평가와-선입견&quot; style=&quot;position:relative;&quot;&gt;블로그로 인한 긍정적 평가와 선입견&lt;a href=&quot;#%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EA%B8%8D%EC%A0%95%EC%A0%81-%ED%8F%89%EA%B0%80%EC%99%80-%EC%84%A0%EC%9E%85%EA%B2%AC&quot; aria-label=&quot;블로그로 인한 긍정적 평가와 선입견 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;2017년 필자가 이 블로그를 처음 시작했을 때, 필자는 그저 글 쓰는 행위를 취미로 즐기는 평범한 한 명의 개발자였다. 물론 2023년 현재도 평범한 개발자인 것은 변하지 않았지만, 아무래도 오랜 기간 글을 써온 만큼 일상생활 속에서도 필자를 알아봐주시고 필자가 작성한 글에 대한 이야기를 해주시거나 심지어 팬이라고 해주시는 분들도 생겼다.&lt;/p&gt;
&lt;p&gt;아마 필자의 존재를 알고 있는 사람들은 아무래도 실제로 필자와 함께 일해보거나 일상을 보내본 분들보다는 필자의 글을 통해서 필자를 알게 되는 분들이 많을 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 블로그를 통해 필자를 먼저 알게 되시는 분들은 필자가 굉장히 진중한 사람이라고 생각하시는 경우가 많았던 것 같다. 이는 아마 글이라는 매체와 필자의 필체 특성 상 감정이 크게 드러나지 않는 것, 그리고 필자가 작성하는 글의 주제들이 주로 학술적인 이야기나 필자의 철학에 대한 이야기를 많이 다루기 때문이라 생각한다.&lt;/p&gt;
&lt;p&gt;물론 그런 모습도 필자의 일부이긴 하겠지만 실제 현실에 존재하는 필자는 그렇게 진지하기만 한 사람도 아니거니와 오히려 돈, 명예, 학벌, 스펙과 같이 사회가 제시하는 공통적 가치보다는 그냥 자기 하고 싶은 대로 하면서 사는 사람에 가깝다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e29d08b6cd6fef0018fbd6525801f5ac/acb04/star.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 236.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAvABQDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAECAwQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQMA/9oADAMBAAIQAxAAAAHy6xbbVui8lZix1CLzQWN1kn//xAAbEAEAAgMBAQAAAAAAAAAAAAABABECAxAxEv/aAAgBAQABBQKq59Yc9XQEuHroSNQLXDaSk4mrrqCf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwFf/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAEQUQIREv/aAAgBAgEBPwE6whN3G1Z//8QAHxAAAQIGAwAAAAAAAAAAAAAAAQAQAhEhMTKRM6Gi/9oACAEBAAY/Artx9tIIVKs2QKspKsXp6GLT5jS//8QAIBABAAICAgEFAAAAAAAAAAAAAQARITEQUUFhcYGRsf/aAAgBAQABPyF2AfaW9zCejPbgEgLZUm2s6jfY/ILBYX5YwbhdgxLVIgDbGA8EKcku+vqWMuLxXDtXfKf/2gAMAwEAAgADAAAAEHA/PcAv/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERURD/2gAIAQMBAT8QIxEWcjw//8QAHREBAAIABwAAAAAAAAAAAAAAAQAxEBEhgZGh8P/aAAgBAgEBPxCoMaLyxqZKvWAxb20//8QAHhABAAMAAQUBAAAAAAAAAAAAAQARITFBUWFxkaH/2gAIAQEAAT8QfAM1dziLFKT3GpKIBX13g03j7jZTgZWzdFKAw9TmdXGgw6DxAYCgeA8srQFCiT5BcHhRpxKkbALa1m+YwUaPsMZNDtPJHgQHiCisrbBs/VcC0O8I6BdkP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;star&quot; title=&quot;&quot; src=&quot;/static/e29d08b6cd6fef0018fbd6525801f5ac/c08c5/star.jpg&quot; srcset=&quot;/static/e29d08b6cd6fef0018fbd6525801f5ac/0913d/star.jpg 160w,
/static/e29d08b6cd6fef0018fbd6525801f5ac/cb69c/star.jpg 320w,
/static/e29d08b6cd6fef0018fbd6525801f5ac/c08c5/star.jpg 640w,
/static/e29d08b6cd6fef0018fbd6525801f5ac/acb04/star.jpg 750w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;블로그에서는 좀 선비같아 보일 수 있지만&lt;br&gt;필자도 그냥 남들처럼 저녁에 친구랑 게임하는 것 좋아하는 평범한 30대 남자다.&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;물론 이러한 긍정적인 평가와 선입견들이 분명 필자의 인생에 큰 도움이 되는 것은 사실이며, 실제로 이러한 평가들로 인해 이직, 오퍼 등 커리어에 대한 좋은 기회나 부업에 대한 기회도 많이 제안받고 있다.&lt;/p&gt;
&lt;p&gt;하지만 이러한 평가가 항상 좋은 점만 가져다 주지는 않는다. 오히려 필자의 경우 이러한 긍정적 선입견들로 인해 꽤나 많은 고민들을 했었다.&lt;/p&gt;
&lt;p&gt;필자는 지금까지 개발자로 일을 해오며 스스로가 훌륭한 개발자라고 생각했던 적이 단 한 번도 없었다. 당연히 필자는 절대 완벽한 인간이 아니며 아직 부족한 점도 많고 실제로 필자의 역량으로는 해결하기 어려운 문제들을 만나 실패한 경험도 많다.&lt;/p&gt;
&lt;p&gt;또한 필자 주변을 보면 워낙 훌륭하신 분들이 많기도 해서 필자는 지금도 스스로를 그냥 강남이나 판교에 굴러다니는 평범한 개발자 정도의 수준이라고 생각한다.&lt;/p&gt;
&lt;p&gt;하지만 인터넷을 벗어나 일상 속에서 사람들을 만나다보면 간혹 이러한 이야기들을 듣게 된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“저도 동욱님 같은 개발자가 되고 싶어요.”&lt;/p&gt;
&lt;p&gt;“우와 연예인 보는 것 같아요.”&lt;/p&gt;
&lt;p&gt;“동욱님 정도면 먹고 살 걱정은 없지 않아요?”&lt;/p&gt;
&lt;p&gt;“동욱님은 회사도 원하는 곳으로 골라서 가실 수 있지 않아요?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 이러한 말씀을 해주신 분들은 필자의 글을 사랑해주시고 공감해주시는 독자님들이시고 필자를 응원해주시는 분들이니, 이는 너무나도 감사한 일이다. 누군가가 나의 생각과 가치관에 공감해주고 응원해준다는 것은 너무 행복한 일이라고 생각한다.&lt;/p&gt;
&lt;p&gt;하지만 이런 이야기들을 듣다보면 감사하다는 마음과 동시에 이런 생각이 들기도 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 496px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b4ec7a5ca3af9bd5b634dc29a2234796/6a372/surprised.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwAEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAUEgOnZ4/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAAxESEyH/2gAIAQEAAQUC6NrXayHqRCfGY5n/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAACAwAAAAAAAAAAAAAAAAAAARARMf/aAAgBAQAGPwIq2zI2P//EABwQAQADAAIDAAAAAAAAAAAAAAEAESExQVFhsf/aAAgBAQABPyGpCl637jRWPsM3ksa+9yu1DeZ//9oADAMBAAIAAwAAABBYH//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxAxf//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAgEBPxAVf//EABoQAQADAQEBAAAAAAAAAAAAAAEAESFBMVH/2gAIAQEAAT8QCBJCi0uxSFmnK+oa9MC9VhaV4iVWau17M1032f/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;surprised&quot; title=&quot;&quot; src=&quot;/static/b4ec7a5ca3af9bd5b634dc29a2234796/6a372/surprised.jpg&quot; srcset=&quot;/static/b4ec7a5ca3af9bd5b634dc29a2234796/0913d/surprised.jpg 160w,
/static/b4ec7a5ca3af9bd5b634dc29a2234796/cb69c/surprised.jpg 320w,
/static/b4ec7a5ca3af9bd5b634dc29a2234796/6a372/surprised.jpg 496w&quot; sizes=&quot;(max-width: 496px) 100vw, 496px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;엇 내가 그 정도는 아닌데...?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;현실의 필자는 무슨 경제적 자유를 이룬 사람도 아니고 연예인도 아닌 그저 이런저런 고민이 많고 글쓰기를 좋아하는 한 명의 평범한 개발자일 뿐이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 여러 번 이야기 했듯 평가라는 행위는 평가자의 주관적 기준에 의해 수행되며, 당연히 블로그를 통해 필자를 처음 접한 분들은 실제로 필자가 어떤 사람인지, 어떤 역량을 지녔는지에 대한 자세한 정보가 없으니 그저 블로그 포스팅이나 깃허브에 올려둔 코드와 같이 본인들이 접한 표면적인 정보를 토대로 필자를 평가하게 될 것이다.&lt;/p&gt;
&lt;p&gt;문제는 필자 입장에서는 이 평가가 도대체 어디까지 올려쳐진 상태인지 알기 어렵다는 것이다. 아무래도 필자도 사람인지라 누군가가 필자에게 기대를 한다면 이 기대에 부응하고 실망시키지 않고 싶다는 마음이 생기기 마련인데, 만약 필자의 실제 역량보다 타인의 평가가 매우 높게 형성된 상태라면 이를 만족시키기 쉽지 않을테니 이런 심리가 결국 부담으로 돌아오는 상황이 발생하는 것이다.&lt;/p&gt;
&lt;p&gt;그래서 한때 누군가가 필자를 알아보거나 긍정적인 평가를 해주시는 상황이라면, 이 평가들에 부응하기 위해 몸가짐을 바르게 하고&lt;small&gt;(…)&lt;/small&gt; 언행도 주의하는 등 타인의 시선을 많이 의식하는 상태가 되었었다. &lt;small&gt;&lt;del&gt;(쉽게 말해 그냥 연예인 병이다)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2 id=&quot;삶의-주인으로-살아라&quot; style=&quot;position:relative;&quot;&gt;삶의 주인으로 살아라&lt;a href=&quot;#%EC%82%B6%EC%9D%98-%EC%A3%BC%EC%9D%B8%EC%9C%BC%EB%A1%9C-%EC%82%B4%EC%95%84%EB%9D%BC&quot; aria-label=&quot;삶의 주인으로 살아라 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사실 긍정적인 평가든 부정적인 평가든 이렇게 타인의 평가에 집중해서 살아가는 삶은 스스로에게 꽤나 큰 스트레스가 된다. 물론 사람에 따라 타인의 인정으로부터 충족감을 얻는 경우가 있기도 하겠지만, 근본적으로 타인의 마음이란 내 통제 영역 밖에 있는 것이기 때문에 원하는 대로 되지 않는 경우가 더 많기 때문이다.&lt;/p&gt;
&lt;p&gt;게다가 타인의 평가에 너무 집중하다보면 나 자신의 가치관이 흔들리고 방향성을 잃게 되는 경우도 발생한다. 필자의 경우에도 이러한 평가에 과한 신경을 쏟다보니 지금까지 필자가 옳다고 믿어왔던 신념들에 반하는 행동을 하는 경험을 하게 되었고, 이로 인해 큰 스트레스를 받아 신체적인 영향까지 발생했었다.&lt;/p&gt;
&lt;p&gt;사실 사회 생활을 하다보면, 그리고 경력을 쌓아가면 쌓아갈수록 내가 해왔던 일들로 인해 자연스레 나를 기억하는 사람들이 많아지게 된다. 이렇게 나를 기억하는 사람들이 많아진다는 것은 나를 평가할 가능성이 있는 사람들이 많아진다는 것과 동일한 이야기이고, 이 과정 속에서 많은 이들에게 좋은 평가를 받을 수록 사회라는 거대한 조직 안에서 내 이익을 챙기기 수월해진다.&lt;/p&gt;
&lt;p&gt;하지만 그렇다고 해서 나라는 사람에 대한 근본적인 가치 평가를 온전히 다른 이들에게 맡겨선 안 된다. 앞서 이야기했듯이 근본적으로 타인의 평가란 내 통제 영역 밖에 있는 일이기 때문이다.&lt;/p&gt;
&lt;p&gt;필자 또한 이러한 평가를 신경쓰게 될수록 스스로가 중심을 잃어간다는 생각을 했었고, 이를 벗어나 자유로워 질 수 있는 방법에 대한 고민을 오랜 시간 해왔다. 이 자유를 되찾기 위해 필자가 가장 먼저 했던 것은 내가 통제할 수 있는 것과 통제할 수 없는 것이 무엇인지를 분류하고 이를 인정한 후, 통제할 수 없는 것에 대해서는 집착을 버리는 일이었다.&lt;/p&gt;
&lt;h3 id=&quot;통제할-수-있는-것과-통제할-수-없는-것을-명확히-구분하자&quot; style=&quot;position:relative;&quot;&gt;통제할 수 있는 것과 통제할 수 없는 것을 명확히 구분하자&lt;a href=&quot;#%ED%86%B5%EC%A0%9C%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B2%83%EA%B3%BC-%ED%86%B5%EC%A0%9C%ED%95%A0-%EC%88%98-%EC%97%86%EB%8A%94-%EA%B2%83%EC%9D%84-%EB%AA%85%ED%99%95%ED%9E%88-%EA%B5%AC%EB%B6%84%ED%95%98%EC%9E%90&quot; aria-label=&quot;통제할 수 있는 것과 통제할 수 없는 것을 명확히 구분하자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;세상을 살아가며 가만히 주위를 둘러보면 생각보다 내가 온전히 통제할 수 있는 것들이 그렇게 많지 않다는 사실을 깨달을 수 있다. 내가 통제 가능한 부분은 대부분 나의 생각, 나의 감정과 같이 내가 주체가 되는 것들이며, 나를 벗어난 타인과 관련된 것들은 대부분 통제가 불가능한 영역에 위치한다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/75882324a1834fcc0529ebf9f418eded/07a9c/out-of-control.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADrklEQVR42m1Vy44bVRB1gsQCFKRI8F9ILIKikdgEIfiJWWYNkZJVEKMoSlgwiDEIEQmYCbEzEzsittuP+P3qd7vbY/yM+97DqY5n5EnSUrna11V1T516OJXaegBcFm3b9ofj8fhaGIb3R6NRnTINgmBGafLsR8oO3z/a9nnrOfvBcZxPPc+r0AkMqi3LQr/fB8/h+z5OT081z+V7gxdd2/heEtkOdmkT7OZ0OsV8Pkc6nVYHBwfx3t6evn3nDo6OjnCQTuv9/f348PBQMbheLpdwXfdb+r93Hmx3dzdBRkQ3lVKgjkejQAki1/XgUttE6brUtpUgdT1P0GrarrXWINJb28BS5OMzSaPX66l2u62pMQoCBEzR80dw/DFsbwwvCHnuIQh8DIdDdLtdsY0nkwnPgi+SYPl8/gMeFIWrk5MTlclk8Tyf560R+v4cTS9Gw9NouApNN0bPmyeBy4Yh9sjlckqCk6pGsVi8miLcz2ezmaSgwjBCFBEFddNeoNRbwOjPqaeoDJeoDBbUr1C35rQZJ7biQ3Sx8BlF0Y0UP+5tyI0p8MjVMFgiU7TwMP0Y9376E7d/2MejbAU/P3pGOcHjFwMMglViK3yKrxSSsX6RgDVByFs03+EznYazRs16hZq5RHkwx3HZwVPDeo2Q8tJa0yaGS37DUCTSwiP9rRR77D/mjlqthlKxgFbPTDir00F4E50tmTh63rlwJmKxUC9rVRQKBZRKJQwGA50ioVMJ1mq1USkbaPdtOulzp7q9JkIbf+WaRL16K2Cr1UC1Wk3ENE0t/VeXZn4z5TM0UoxMcYjDfJvFmW0FXJO/1ymzsJoTJCk7wuEDKQrHLaaw9zz03BlqjkqchcOnhol//u2h0JmwjRRqtkLHXSSjKCK+UhSC+00Q7iwWyY+KNyGkBGyFlsv0POBZxcXfuQb+eFLGk8IATR9oOitmEiW24kPfeLVaScCvU/xyhVNSlZZh5ysKOp02TMtBz1+iuqm09GN1uEDXWyTVNYcDsed0dRXpkqXRrdfrnyTTwqDXhVROjcpms8hQ2q1WgsD1Q9j+JBF5F0pkJMvlMo6Pj2VaYq47sG2+urBpePCdDDrRrgldy63CT5CIdx7ojDcpBPlf019SvXthOfCRfXaZm+SWkCs7jxQoIdvfCnJWABHZlcI9fb43DOP9CwG3FySddujQFWMGlxW1jSo523TFkPLlOxfsm7uRt1+l8w0G+ZVOruy+DToq/3ei/4YUffyuv4D/AbN8BMBkHMxNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;out of control&quot; title=&quot;&quot; src=&quot;/static/75882324a1834fcc0529ebf9f418eded/6af66/out-of-control.png&quot; srcset=&quot;/static/75882324a1834fcc0529ebf9f418eded/69538/out-of-control.png 160w,
/static/75882324a1834fcc0529ebf9f418eded/72799/out-of-control.png 320w,
/static/75882324a1834fcc0529ebf9f418eded/6af66/out-of-control.png 640w,
/static/75882324a1834fcc0529ebf9f418eded/d9199/out-of-control.png 960w,
/static/75882324a1834fcc0529ebf9f418eded/21b4d/out-of-control.png 1280w,
/static/75882324a1834fcc0529ebf9f418eded/07a9c/out-of-control.png 1440w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;올바른 자기인식은 자신이 통제가 가능한 부분이 어디까지이고&lt;br&gt;통제가 불가능한 부분이 어디까지인지를 인식하는 것에서부터 시작한다&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;즉, 타인이 나에 대해서 평가하는 것은 나의 통제 영역을 벗어난 개념이다. 물론 타인의 마음을 돌리기 위해 그 사람을 설득하고 공감시키기 위한 행동을 하는 것은 통제 영역 안에 있지만, 그 행위에 대한 결과는 여전히 나의 통제 영역을 벗어나 있다.&lt;/p&gt;
&lt;p&gt;서두에서 필자는 모두에게 사랑받고 싶어하는 사람은 자기 자신을 잃게 되기 쉽다고 이야기했다. 이는 모두에게 사랑받고 싶다는 그 마음이 타인의 평가라는 나의 통제 영역을 벗어난 개념에 대해 집착하는 형태로 나타나기 쉽기 때문이다.&lt;/p&gt;
&lt;p&gt;우리 주변에는 굉장히 다양한 가치관과 이념을 가진 인간들이 함께 살아가고 있으며, 이는 어떤 조직이라고 해도 마찬가지이다. 결국 같은 현상을 보더라도 이에 대한 평가나 감정은 각각의 인간 객체마다 다를 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;이러한 현실은 내가 통제할 수 있는 것이 아니다. 어차피 내가 통제할 수 없는 것이라면 왜 거기에 집착하는가? 내가 어떤 행동을 하던 나를 좋아할 사람은 좋아하고 싫어할 사람은 싫어하기 마련이다. 내가 절대 가질 수 없는 것을 가지고자 발버둥치는 것만큼 스스로를 불행하게 만드는 일이 또 있을까?&lt;/p&gt;
&lt;p&gt;필자는 인생의 Focus on Impact가 내가 통제 가능한 영역을 더 잘 해내기 위해 집중하는 것, 그리고 통제 불가능한 영역에 존재하는 것들을 가급적이면 통제 가능한 영역으로 끌어들이는 것이라고 생각한다. 당장 내가 통제할 수 없는 것들에 지나친 관심을 쏟는 것은 집중력이라는 한정된 자원을 의미없는 곳에 지출하고 있는 것이나 마찬가지이다.&lt;/p&gt;
&lt;p&gt;이러한 한계를 인지하고 인정하는 행위는 결국 내가 아는 것이 무엇이고 모르는 것이 무엇인지, 할 수 있는 것이 무엇이고 하지 못 하는 것이 무엇인지 등을 스스로 인지하는 메타인지와도 연결된다. 통제 영역에 대한 인지 또한 “나”라는 주체가 세상에 행사할 수 있는 영향력이 어디까지인지에 대한 경계를 인지하는 것이기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;결국-움직이는-것은-그대의-마음이다&quot; style=&quot;position:relative;&quot;&gt;결국 움직이는 것은 그대의 마음이다&lt;a href=&quot;#%EA%B2%B0%EA%B5%AD-%EC%9B%80%EC%A7%81%EC%9D%B4%EB%8A%94-%EA%B2%83%EC%9D%80-%EA%B7%B8%EB%8C%80%EC%9D%98-%EB%A7%88%EC%9D%8C%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;결국 움직이는 것은 그대의 마음이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;어느 날 사찰 깃발이 바람에 나부끼고 있었다. 이 광경을 본 두 스님이 서로 논쟁을 했다. 한 스님은 “깃발이 움직이고 있다”라고 말하고, 다른 스님은 “바람이 움직인다”라고 주장했다. 서로의 주장만이 오갈 뿐 논쟁은 해결되지 않는다.&lt;/p&gt;
&lt;p&gt;이때 육조 혜능은 말했다. &lt;strong&gt;“바람이 움직이는 것도, 깃발이 움직이는 것도 아닙니다. 그대들의 마음이 움직이고 있을 뿐입니다.”&lt;/strong&gt; 두 스님은 소스라치게 놀랄 수 밖에 없었다.&lt;/p&gt;
&lt;p&gt;[무문관] 29칙. 비풍 비번.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 에피소드에서 혜능 스님은 어떤 것을 이야기하고 싶었던 것일까? 본래 무문관이란 질문만 던져놓고 답을 제시하지는 않는 화두집이니 이 책에서 이 질문에 대한 답을 알려주지는 않는다.&lt;/p&gt;
&lt;p&gt;필자는 이 에피소드를 읽고 “현상은 그저 존재할 뿐, 그 현상을 해석하는 것은 인간의 주관적인 판단이다”라는 생각을 했었다.&lt;/p&gt;
&lt;p&gt;대승 불교의 경전인 화엄경은 **일체유심조(一切唯心造)**라는 핵심 사상에 대해서 이야기한다. 이 말은 단어 그대로 “모든 것은 오직 마음이 지어낸다”라는 뜻이며, 필자는 내가 내 삶의 주인으로 살 수 있는 핵심 포인트가 바로 이 일체유심조라고 생각한다.&lt;/p&gt;
&lt;p&gt;일반적으로 사람들이 타인의 평가로 인해 힘들어하는 상황은 좋은 평가를 받는 상황보다는 좋지 못한 평가를 받는 상황인 경우가 많으니, 누군가가 뒤에서 여러분에 대한 가십을 퍼트리고 다니는 상황을 한번 생각해보자.&lt;/p&gt;
&lt;p&gt;아마도 그 가십은 100% 사실로만 이루어진 내용은 아닐 것이다. 게다가 여러 가십들이 그러하듯 약간의 사실과 그 사실에 대한 오해와 주관이 덧붙혀진 내용들일 가능성이 높다. 이런 이야기를 들었을 때 당사자에게 제대로 된 사실 관계를 확인하려고 하는 사람은 드물기도 하거니와 담백한 사실보다는 이런저런 거품이 붙어야 더 재미도 있기 때문이다.&lt;/p&gt;
&lt;p&gt;만약 여러분이 이 사실을 알게 되었다면 여러분은 답답함, 억울함, 분노, 배신감과 같은 여러가지 감정에 휩싸이게 될 수도 있다. 그렇다면 이 감정은 어디에서 비롯된 것일까? 누군가 뒤에서 나에 대한 가십을 퍼트리고 다닌다는 그 환경이나 상황에서 비롯된 것일까? 혹은 그 가십을 퍼트리고 다니는 인물에게서 비롯된 것일까?&lt;/p&gt;
&lt;p&gt;아니다. &lt;strong&gt;결국 답답함, 억울함, 분노, 배신감과 같은 감정은 내 마음에서부터 시작하는 것이다.&lt;/strong&gt; 이런 감정들은 결국 내 감정인 것이며, 앞서 이야기했듯이 내 감정은 내가 온전히 통제 가능한 영역 안에 있는 개념이다. 결국 현재 벌어지고 있는 상황과 관계없이 내가 스스로 이런 감정을 만들어내어 나를 힘들게 하는 것이다.&lt;/p&gt;
&lt;p&gt;이것이 바로 일체유심조(一切唯心造), 모든 것은 오직 마음이 지어낸다는 말의 의미이다. 물론 현재 벌어지고 있는 상황 자체가 옳거나 옳지 않다는 가치 판단, 그리고 옳지 않다면 바로 잡아야하는 액션 아이템의 수립이 필요할 수도 있다. 하지만 문제 상황을 해결하기 위한 전략을 수립하고 행동을 수행하는 것과 내 감정은 별개의 문제라는 사실을 잊지 말아야 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6271f4799e9572d8153bd8477492a94b/65f94/water.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 132.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAwACAQX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAH3TQzFqFJMh3Y//8QAGRAAAQUAAAAAAAAAAAAAAAAAIAAQESFB/9oACAEBAAEFAg1rUB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAVEAEBAAAAAAAAAAAAAAAAAAAgMf/aAAgBAQAGPwJ0/wD/xAAbEAEBAAIDAQAAAAAAAAAAAAABABEhEDFxgf/aAAgBAQABPyFl3iSZNGZ6sY7z+Xrhm//aAAwDAQACAAMAAAAQswMw/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHBABAAMBAAMBAAAAAAAAAAAAAQARMSFBUXGx/9oACAEBAAE/EDxhUWuUQbioV8S0Jwv8mp2j2QMBdN5+RV9bGYmp/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;water&quot; title=&quot;&quot; src=&quot;/static/6271f4799e9572d8153bd8477492a94b/65f94/water.jpg&quot; srcset=&quot;/static/6271f4799e9572d8153bd8477492a94b/0913d/water.jpg 160w,
/static/6271f4799e9572d8153bd8477492a94b/cb69c/water.jpg 320w,
/static/6271f4799e9572d8153bd8477492a94b/65f94/water.jpg 420w&quot; sizes=&quot;(max-width: 420px) 100vw, 420px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;컵에 들어있는 물은 그저 거기에 담겨있을 뿐, 이를 어떻게 바라볼 지는 사람의 마음에 달려있다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;일체유심조라는 말은 어찌 보면 꽤 현실과 동떨어진 이야기처럼 느껴진다. 하지만 필자는 이 말이 수많은 평가와 비교 속에서 고통받고 있는 현대인들에게 가장 필요한 말이 아닐지 생각한다.&lt;/p&gt;
&lt;p&gt;물론 누군가 나에 대한 가십을 퍼트리고 다닌다는 것이나 익명 뒤에 숨어서 비난을 하는 것이 감정적으로 힘들어지기 쉬운 상황인 것은 맞다. 하지만 내가 힘들어하든 힘들어하지않든 내가 이성적으로 이 현상의 원인에 대해서 고민하고 해결하기 위한 액션아이템을 수행하지 않는다면 상황 자체는 개선되지 않을 것이다.&lt;/p&gt;
&lt;p&gt;즉 조직 내에서 가십이 돌 정도로 건강하지 않은 조직의 현재 상태를 개선하는 것이 중요하지 내가 가십의 대상이 되었다는 그 상황 자체가 중요한 것은 아니라는 이야기이다.&lt;/p&gt;
&lt;p&gt;그렇다면 그냥 담백하게 그런 상황이 발생하게 된 원인에 대해서 고민하고, 만약 그 원인이 내 통제 가능한 영역 안에 있는 것이라면 빠른 액션아이템 수행을, 그리고 내가 통제할 수 없는 것이라면 통제 가능한 영역으로 끌어들일 수 있는지에 대해서만 고민하면 되는 것이다.&lt;/p&gt;
&lt;p&gt;이처럼 일체유심조를 이해하고 내 감정을 온전히 통제 가능한 영역에 둘 수 있다면 주변에서 발생하는 현상을 관찰할 때 조금 더 문제의 본질에 대해 이성적으로 바라볼 수 있는 시각을 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;이는 감정을 없애라는 것이 아니다. 주변에서 발생하는 상황이나 주어진 환경과 같은 외부 변수에 내 감정이 의존하게 만들지 말라는 것이다. 주변 환경이 어떻든 내 감정은 내가 컨트롤하는 것이다. 주변 환경이나 상황에 관계없이 행복할 수도 불행할 수도 있는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;대부분은-양면적인-평가를-한다는-사실을-기억하자&quot; style=&quot;position:relative;&quot;&gt;대부분은 양면적인 평가를 한다는 사실을 기억하자&lt;a href=&quot;#%EB%8C%80%EB%B6%80%EB%B6%84%EC%9D%80-%EC%96%91%EB%A9%B4%EC%A0%81%EC%9D%B8-%ED%8F%89%EA%B0%80%EB%A5%BC-%ED%95%9C%EB%8B%A4%EB%8A%94-%EC%82%AC%EC%8B%A4%EC%9D%84-%EA%B8%B0%EC%96%B5%ED%95%98%EC%9E%90&quot; aria-label=&quot;대부분은 양면적인 평가를 한다는 사실을 기억하자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;평소 주변의 평가에 대해 신경을 쓰다 보면 아무래도 좋은 평가보다는 좋지 않은 평가에 더 집중하게 되기 쉽다. 인간은 부정적인 정보가 가져다주는 위협에 대해 민감하게 반응하도록 설계되었기 때문에 일종의 부정성 편향을 가지고 있기 때문이다. &lt;small&gt;(신문이나 뉴스도 긍정적인 소식보다는 부정적인 소식이 더 잘 팔린다고 한다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이때 만약 감정 컨트롤까지 능숙하지 않다면 “나는 안 될 거야”와 같은 자조적인 가치 절하와 함께 절망의 구렁텅이로 빠져들 수도 있다. 게다가 내가 나에게 부정적인 피드백을 주는 구렁텅이로 한번 빠져들게 되면 스스로 헤어나오는 것이 쉽지 않을 수도 있다.&lt;/p&gt;
&lt;p&gt;하지만 사실 특정 인간에 대한 평가는 대부분 양면적이다. 즉 나에 대해 나쁘게만 평가하는 사람이나 좋게만 평가하는 사람보다는 대부분 좋은 점도 있고 부족한 점도 있다고 평가한다는 것이다.&lt;/p&gt;
&lt;p&gt;어찌보면 이는 당연한 사실인게, 인간이라면 누구나 다 강점과 약점이 존재하기 때문에 강점에 대해서는 좋은 평가를 받을 가능성이 높고 약점에 대해서는 좋지 못한 평가를 받을 가능성이 높다.&lt;/p&gt;
&lt;p&gt;물론 &lt;a href=&quot;https://namu.wiki/w/%ED%8E%B8%ED%96%A5#s-2.2.5&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;행위자-관찰자 편향&lt;/a&gt;이나 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EA%B8%B0_%EA%B3%A0%EC%96%91%EC%A0%81_%ED%8E%B8%EA%B2%AC&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;자기 고양 편향&lt;/a&gt;으로 인해 자신에 비해 타인에게 더 엄격한 평가를 하는 경우도 있기는 하지만, 기본적으로 이성적인 성인이라면 특정 인물에 대해서 어느 정도는 중립적인 평가를 하기 마련이다. &lt;small&gt;(특정 인물에 대해 좋지 않은 평가만 하는 사람이라면 특정 현상에 대해 다각적인 시각을 가지지 않은 사람일 가능성이 높으니 가급적 피하는 것을 추천한다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그리고 대부분의 평가는 양면적이며 중립적이라는 사실을 스스로 인지한다는 것은 나의 자존감을 지키는 데 큰 도움이 된다. 물론 반대로 너무 긍정적인 정보에만 집중하면 현실을 제대로 보지 못 할 수도 있으니 적절한 밸런스를 잡는 것이 중요할 것이다. 물론 이것은 단순한 가정이 아니라 실제로 여러분 주위에서 벌어지고 있는 현실이기도 하다.&lt;/p&gt;
&lt;p&gt;중요한 것은 나 또한 중립적인 시각을 가지고 타인이 나에 대해 긍정적 평가를 한 부분에 있어서는 강화를, 부정적 평가를 한 부분에 있어서는 개선을 하는 것이다. 굳이 이런 평가들로 인해 기분이 나빠질 필요도 좋아질 필요도 없다. 앞서 이야기했듯 그저 이런 평가가 발생했다는 담백한 사실을 인지하고 강화하거나 개선하기 위한 액션 아이템을 수행하면 되는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;누구나 그러하듯이 필자 또한 지금까지 삶을 살아오며 수많은 평가를 마주할 수 있었다. 이는 비단 개발자로 일을 할 때 뿐만이 아니라 어릴 적 비보이, 사운드 엔지니어로 활동했을 때도 동일했었다.&lt;/p&gt;
&lt;p&gt;아무리 관계를 중시하지 않는 인간이라고 해도 결국 사회라는 거대한 네트워크 내에서 알게 모르게 다른 인간들과 인터랙션을 하며 살아갈 수 밖에 없다. 그리고 이 과정 속에서 타인이 자연스레 나에 대한 평가를 한다는 사실 또한 너무나 당연한 현실일 것이다.&lt;/p&gt;
&lt;p&gt;하지만 이 평가들에 너무 매몰되면 온전한 나 자신을 잃어버릴 수 있다. 물론 타인의 평가나 조언을 듣고 나의 가치관이나 삶의 방향성에 대한 수정이 필요할 수도 있겠지만, 결국 이에 대한 결정 주체는 오롯이 나 자신이어야 하며, 이 결정 권한을 타인에게 위임해서는 안 된다.&lt;/p&gt;
&lt;p&gt;우리가 타인에게 하는 말이나 평가에는 어떠한 비용도 들지 않는다. 또한 타인은 나에 대해 평가를 할 수는 있지만 그 평가에 대한 책임을 지는 경우는 거의 없다.&lt;/p&gt;
&lt;p&gt;즉, 그 행위를 함에 있어서 마치 10억이 넘는 아파트에 대한 구매 결정을 할 때와 비슷한 수준의 고민을 하지는 않는다는 이야기이다.&lt;/p&gt;
&lt;p&gt;그러니 필자는 그런 행위에 너무 무게를 두지 않는 것을 추천한다. 결국 내 가치는 내 이성이 결정하는 것이며, 올바른 자기 가치관을 가진 성인이라면 응당 그래야만 한다고 생각한다.&lt;/p&gt;
&lt;p&gt;앞서 이야기했듯이 인간의 사상과 가치관에는 정답이라고 할 만한 것이 없다. 그저 그런 생각들이 존재할 뿐, 그 생각들에 대한 가치판단은 모두 다를 수 있다는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“스타트업에 다니는 것이 옳은 것인가? 대기업에 다니는 것이 옳은 것인가?”&lt;/p&gt;
&lt;p&gt;“높은 소득과 워라밸을 맞바꾸는 것이 옳은 것인가? 돈보다는 내 시간을 챙기는 것이 옳은 것인가?”&lt;/p&gt;
&lt;p&gt;“기회의 평등이 옳은 것인가? 결과의 평등이 옳은 것인가?”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;이러한 이데올로기들에 대한 정답은 그 누구도 제시할 수 없다. 그저 자신이 믿는 가치에 따라 선택할 뿐이다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그러니 정답을 찾으려 하거나 모두에게 사랑받으려고 하지 말고 자신이 믿는 신념에 따라 자신이 옳다고 생각하는 길을 따라 자신만의 페이스를 유지하며 걷자.&lt;/p&gt;
&lt;p&gt;주변과 나를 비교하거나, 지나고 나면 별 것 아닌 상황에 감정을 이입하거나, 당장 가질 수 없는 것을 가지기 위해 발버둥 쳐 나를 더 힘들게 하는 것도 결국은 나 자신이다.&lt;/p&gt;
&lt;p&gt;나 자신을 온전히 통제하고 주변의 현상들을 이성적으로 관찰하다보면 사실 별 것 아닌 단순한 문제들을 때로는 너무 복잡하게 바라보고 있지는 않았나 하는 생각이 든다.&lt;/p&gt;
&lt;p&gt;이상으로 나는 타인의 평가에서 자유로울 수 있을까 포스팅을 마치며, 오늘도 인간들 사이에서 많은 고민을 하고 행복을 느끼고 상처를 받기도 하는 독자분들에게 이 글을 바친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[What Do People Work For? – The Psychology of Motivation]]></title><description><![CDATA[In this post, I want to briefly share what I’ve been thinking about over the past three years, not as an IC (Individual Contributor) but as a leader, about what makes a good leader and what competencies that requires. No matter how good someone was as an IC, that experience doesn’t automatically translate into leadership capability. That realization is what naturally led me down this path of inquiry.]]></description><link>https://evan-moon.github.io/2023/10/03/how-to-be-a-better-leader/en/</link><guid isPermaLink="false">20231003-how-to-be-a-better-leader-en</guid><pubDate>Mon, 30 Oct 2023 01:04:23 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I want to briefly share what I’ve been thinking about over the past three years, not as an IC (Individual Contributor) but as a leader, about what makes a good leader and what competencies that requires.&lt;/p&gt;
&lt;p&gt;No matter how good someone was as an IC, that experience doesn’t automatically translate into leadership capability. That realization is what naturally led me down this path of inquiry.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;What many developers find difficult when they take on a leader or manager role stems from the fact that, unlike computers, humans don’t behave logically at all.&lt;/p&gt;
&lt;p&gt;When you give a computer the command A, it understands A and executes A. Humans almost never interpret A as straightforwardly as that. Every person carries biases shaped by the environment they grew up in and the experiences they’ve accumulated, so even when you say the same thing, each person may react differently.&lt;/p&gt;
&lt;p&gt;Computers are also guaranteed to deliver the same performance under the same conditions. Humans, on the other hand, might deliver 100% performance one day and suddenly drop to 50% for entirely illogical reasons — making their behavior hard to predict.&lt;/p&gt;
&lt;p&gt;People who were recognized for their ability to work with computers — those perfectly logical machines — are suddenly asked to deal with humans, who are anything but logical. It would be stranger if they didn’t find it difficult.&lt;/p&gt;
&lt;p&gt;I, too, have experienced various types of failure — demoralizing team members through poor decisions, or failing to provide psychological support when it was needed — largely because I lacked a fundamental understanding of human nature.&lt;/p&gt;
&lt;p&gt;That’s why I came to believe that a leader needs more than just communication skills. You need a humanities-grounded understanding of yourself, of human psychology and instinct, and of organizational dynamics. To become a good leader, I thought I first needed to deepen my understanding of human nature and the characteristics that emerge when these “human objects” form a group.&lt;/p&gt;
&lt;h2 id=&quot;what-makes-a-good-leader&quot; style=&quot;position:relative;&quot;&gt;What makes a good leader?&lt;a href=&quot;#what-makes-a-good-leader&quot; aria-label=&quot;what makes a good leader permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When I first took on the F-Lead role at Toss three years ago, and later the Frontend Chapter Lead role at Quotalab, the first question I asked myself was: “What is a good leader?”&lt;/p&gt;
&lt;p&gt;Since “good” is a subjective value judgment that inevitably differs from person to person, there’s no definitive right answer. But I believed that without my own philosophy and definition, I’d lose direction and end up being a leader who stands for nothing.&lt;/p&gt;
&lt;p&gt;A leader’s role is to get diverse people within an organization moving in a particular direction, in step with each other. The word “lead” implies pulling from the front, so you might think that’s what good leadership looks like. But I believe that as long as you can get people moving in the right direction, it doesn’t much matter whether you’re pulling from the front or pushing from behind.&lt;/p&gt;
&lt;h2 id=&quot;what-makes-people-move&quot; style=&quot;position:relative;&quot;&gt;What makes people move?&lt;a href=&quot;#what-makes-people-move&quot; aria-label=&quot;what makes people move permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If a leader’s role isn’t simply to control people but to get them moving in a particular direction, then the next question is: what is the force that makes people move?&lt;/p&gt;
&lt;p&gt;Fortunately, fields like psychology and education have already spent a long time discussing and experimenting with the principles of human motivation and behavior. I was able to approach the problem step by step by reading research papers and experimental findings.&lt;/p&gt;
&lt;h3 id=&quot;self-determination-theory&quot; style=&quot;position:relative;&quot;&gt;Self-determination theory&lt;a href=&quot;#self-determination-theory&quot; aria-label=&quot;self determination theory permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The theory that caught my attention was &lt;a href=&quot;https://en.wikipedia.org/wiki/Self-determination_theory&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Self-Determination Theory&lt;/a&gt;, one of the major theories of motivation. It states that humans are beings who motivate themselves through internal factors like interest and curiosity, actively developing their sense of self toward psychological growth and integration. The theory identifies three key needs, autonomy, competence, and relatedness, that show a strong positive correlation with intrinsic motivation.&lt;/p&gt;
&lt;p&gt;Similar to &lt;a href=&quot;https://en.wikipedia.org/wiki/Andragogy&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Andragogy&lt;/a&gt;, which is often discussed in the context of lifelong learning, understanding what drives adult behavior places particular emphasis on autonomy — the learner’s own will.&lt;/p&gt;
&lt;p&gt;Since autonomy is ultimately a psychological product of feeling that you’re acting by your own choice, I believe that to guide people’s behavior in a particular direction, you first need their empathy toward that direction.&lt;/p&gt;
&lt;p&gt;Empathy, after all, isn’t something that can be force-fed from the outside (short of brainwashing). It’s an emotion that must be self-determined and self-convinced, which makes it the most suitable emotion for triggering intrinsic motivation.&lt;/p&gt;
&lt;p&gt;However, if you try to drive people’s behavior through external control factors alone — without any intrinsic motivation in place — their resistance to stress will be low when obstacles arise.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e5da4b9f591a004456c5e04af9415083/0ff19/tree2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 53.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwElEQVR42pVSO08CQRBeHiIatdCWxsZCG7G00tZoaaMWNlQYH4WF8R+oiSZqpZ29oSDBhNgDWUgOPI7jdSLBaLjjIBxG8bHOHCc5DCayydx8O9/M7Oy3R8gfizFm1T3Puz+q1adPMMRmrqcFRXbdNxqHsiyziqoyVq8fmLleG7YmjEaXmprWaNbrL4zSxX9PCEmWDk+IHWwIzMpCoXF2fT0B2GLE7N1qujXtw9MfCBmAokFspseXl23M5RowDrIip+dALtZ0vZoaibjlQkGoJpMnHVe+vBwu5/PBaqEQlK+uRsycEo8fq8ViUqV0ph2Hjw03JUo9DU1j5fv7hPkajz7f5EM+//VcKn283d5OmbmSKCaar69M4TiPEbe1X+zU6x1j5fIuU5TZH9KYpJ9VKmtvkrROUFdo1v4DarVZrLnY2Rn9/fpOLARDncwCoz4O0tLSafBmzaxGzGHwhGSz2aNAIKBrIAjCcUYQ5hBnMpl9SumKjkVxA7hNxOFweFWSpD09P5GYF6EGsd/vn87lcicknU5rkLyEQVEUFZ7ntxBD/A72Z4hTqdQN4BvEwJ8Dl0TMcdw2YBVxLBZbgOHevwE+GTuxd0aw3gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;tree2&quot; title=&quot;&quot; src=&quot;/static/e5da4b9f591a004456c5e04af9415083/6af66/tree2.png&quot; srcset=&quot;/static/e5da4b9f591a004456c5e04af9415083/69538/tree2.png 160w,
/static/e5da4b9f591a004456c5e04af9415083/72799/tree2.png 320w,
/static/e5da4b9f591a004456c5e04af9415083/6af66/tree2.png 640w,
/static/e5da4b9f591a004456c5e04af9415083/d9199/tree2.png 960w,
/static/e5da4b9f591a004456c5e04af9415083/21b4d/tree2.png 1280w,
/static/e5da4b9f591a004456c5e04af9415083/0ff19/tree2.png 2084w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Some argue that leadership through persuasion and empathy doesn&apos;t scale with larger teams,&lt;br&gt;
  but organizations that large typically don&apos;t have the leader directly communicating with every member anyway.&lt;br&gt;
  The leader communicates this way to middle leaders, who in turn do the same with their teams.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;This is especially critical in environments like startups, where people often have to endure high workloads and long hours to achieve distant missions. Stress undermines productivity, engagement, and sense of belonging — it’s not something you can dismiss as just an individual’s problem.&lt;/p&gt;
&lt;p&gt;In other words, no matter how passionately a leader talks about their goals, team members without intrinsic motivation won’t simply fall in line and give their all. Even if they go along, their behavior is fundamentally driven by external control factors — the leader’s goals and authority — so expecting that behavior to persist under severe stress is unrealistic.&lt;/p&gt;
&lt;p&gt;External motivation also tends to focus on results rather than the act itself, giving it an instrumental quality. Some research suggests that if controlling stimuli are applied — like saying “You’re doing well following my instructions” — it can undermine autonomy and intrinsic motivation, significantly reducing productivity.&lt;/p&gt;
&lt;p&gt;This is particularly true for people in industries like IT that require creativity rather than mechanical repetition. There’s also the view that extrinsic motivators like monetary incentives are even less effective for such workers. Moreover, continuously providing extrinsic motivation risks damaging intrinsic motivation in the long run, so very careful reward design is needed. &lt;em&gt;(Imagine a company that provides performance-linked bonuses and then suddenly stops. Wouldn’t people start thinking “Why bother if there’s no money in it?“)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s why I concluded that to keep team members highly motivated and actively contributing even in stressful environments, you need to build an environment where they feel maximum autonomy, ensuring a strong tendency toward self-actualization among the people in the organization.&lt;/p&gt;
&lt;h3 id=&quot;making-people-feel-they-decided-for-themselves&quot; style=&quot;position:relative;&quot;&gt;Making people feel they decided for themselves&lt;a href=&quot;#making-people-feel-they-decided-for-themselves&quot; aria-label=&quot;making people feel they decided for themselves permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From a leader’s perspective, it’s certainly easier to use external control factors (rewarding high performers, punishing underperformers, or leveraging organizational politics) to get people moving.&lt;/p&gt;
&lt;p&gt;But as I mentioned, intrinsic motivation matters a lot in driving adult behavior. Relying solely on external control factors creates an environment ripe for side effects like low morale, gossip, or people checking out entirely.&lt;/p&gt;
&lt;p&gt;Unlike material resources, human resources are entities capable of emotion and thought, making them difficult to predict and control through a mechanistic lens.&lt;/p&gt;
&lt;p&gt;So leaders need to create an environment where intrinsic motivation can emerge. There are many methods: appropriate delegation of decision-making authority, environments where people can taste small wins (technical and business), clear goals and expectations. But among these, I placed the most weight on the value of autonomy.&lt;/p&gt;
&lt;p&gt;The autonomy a team member feels at work comes from things like exercising decision-making authority over their product, a leader who asks for opinions rather than issuing directives, and being given choices and allowed to make their own selections. It’s about the team member feeling — or actually experiencing — that they’re contributing to the organization through their own autonomous agency.&lt;/p&gt;
&lt;p&gt;Since autonomy isn’t a clear-cut sensation like pain but rather a psychological awareness of exercising one’s own agency, even if team members are unknowingly moving in the direction the organization wants, as long as they believe they have autonomy, that autonomy is effectively secured.&lt;/p&gt;
&lt;p&gt;There’s also substantial empirical research — both domestic and international — showing that work autonomy has a significant positive correlation with organizational trust, job satisfaction, engagement, and performance. In other words, the fact that autonomy can trigger intrinsic motivation appears to hold regardless of commonly cited East-West differences in thinking.&lt;/p&gt;
&lt;p&gt;Of course, given the nature of a company, you can’t guarantee 100% autonomy for everyone. But as I mentioned, autonomy is a psychological awareness rather than an objective sensation — so even just showing that the leader supports team members’ autonomy can have an effect. Alternatively, depending on the leader’s skill, it may be possible to help internalize and integrate externally assigned motivations.&lt;/p&gt;
&lt;h2 id=&quot;actions-leaders-can-take-to-strengthen-team-autonomy&quot; style=&quot;position:relative;&quot;&gt;Actions leaders can take to strengthen team autonomy&lt;a href=&quot;#actions-leaders-can-take-to-strengthen-team-autonomy&quot; aria-label=&quot;actions leaders can take to strengthen team autonomy permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what specific methods can strengthen team members’ autonomy?&lt;/p&gt;
&lt;p&gt;I believe the first step is to analyze and diagnose the current state of the organization — specifically, what motivates each person. Since autonomy is a precondition for creating intrinsic motivation to boost productivity and engagement, if people already have intrinsic motivation, there’s not much to worry about. &lt;em&gt;(Though in practice, when you actually observe and analyze, surprisingly few people operate on intrinsic motivation.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You could ask directly in 1-on-1 meetings — “Do you find your current work enjoyable?” or “Why did you become a developer?” — but personally, I prefer analyzing information that comes up in casual conversation.&lt;/p&gt;
&lt;p&gt;The reason is that the moment you ask someone a question, they might develop biased thinking around that question. Combined with the inherent discomfort of meeting with a leader and the collectivist tendency of not wanting to stand out, they may not share their true feelings. Asking questions without biasing the other person is critically important in situations like user research and interviews — and it’s harder than you’d think.&lt;/p&gt;
&lt;p&gt;That’s why I believe the information that emerges in relaxed settings — smoking a cigarette together, chatting at a café, grabbing dinner after work — tends to be more honest and valuable than what comes out in official 1-on-1 meetings.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/88bbaa99baf8428b6ba76c3155bfa436/92f8c/coffeechat.webp&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRqAAAABXRUJQVlA4IJQAAADQAwCdASoUAAoAPtFUo0uoJKMhsAgBABoJYwCw7BkpyV2/BHFckAAA/pvji9/W2qDheS63N7lYqMRN5bw/LSPvJdYOLlD/IEO4bR7tqTNTS5aW2M9ZvgsCUzkZUItHH3NW15GyKNZA6i2r90hoG+c//yAGLbxjKNebsEjIWGyXkz4QRqq7P7+S2Fqulyh/0AfV8AAA&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;coffeechat&quot; title=&quot;&quot; src=&quot;/static/88bbaa99baf8428b6ba76c3155bfa436/0ba47/coffeechat.webp&quot; srcset=&quot;/static/88bbaa99baf8428b6ba76c3155bfa436/60a22/coffeechat.webp 160w,
/static/88bbaa99baf8428b6ba76c3155bfa436/4c812/coffeechat.webp 320w,
/static/88bbaa99baf8428b6ba76c3155bfa436/0ba47/coffeechat.webp 640w,
/static/88bbaa99baf8428b6ba76c3155bfa436/e46b2/coffeechat.webp 960w,
/static/88bbaa99baf8428b6ba76c3155bfa436/92f8c/coffeechat.webp 1200w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;The more comfortable the environment and the more friendly gestures you show, the more likely people are to be honest with you.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;I’d record pieces of information I deemed meaningful, and then categorize people’s motivations using the classification method proposed in an &lt;a href=&quot;https://scholarworks.bwise.kr/hanyang/handle/2021.sw.hanyang/143183&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;academic paper on applying Self-Determination Theory to HRD&lt;/a&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Motivation Type&lt;/th&gt;
&lt;th&gt;Behavioral Principle&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Amotivation&lt;/td&gt;
&lt;td&gt;Don’t know why I’m doing this&lt;/td&gt;
&lt;td&gt;I don’t know why I have to do this work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External Regulation&lt;/td&gt;
&lt;td&gt;To obtain a result&lt;/td&gt;
&lt;td&gt;I do this work to score well on performance reviews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Introjected Regulation&lt;/td&gt;
&lt;td&gt;Out of obligation&lt;/td&gt;
&lt;td&gt;I do this because I should be a good team member&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identified Regulation&lt;/td&gt;
&lt;td&gt;Because it’s important&lt;/td&gt;
&lt;td&gt;I do this because it’s necessary for the company’s growth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integrated Regulation&lt;/td&gt;
&lt;td&gt;Because it represents my values&lt;/td&gt;
&lt;td&gt;I do this because it expresses who I am&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Intrinsic Motivation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Because the work itself is interesting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;I do this because the work itself is fascinating and fun&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;🤔 One interesting observation: people who were earlier in their careers more often had introjected regulation or intrinsic motivation, while those with more experience more often showed external regulation or identified regulation.&lt;/p&gt;
&lt;p&gt;Perhaps those who chose development because “coding is fun” still carry that initial learning motivation, while more senior developers have accumulated responsibilities beyond personal interest.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In any case, the leader’s role as I defined it is to move people operating on extrinsic motivations — external regulation, introjected regulation, identified regulation, integrated regulation — toward operating on intrinsic motivation. Simply put, it means figuring out what makes “an environment where people enjoy working” and striving to create it.&lt;/p&gt;
&lt;p&gt;And the way to internalize motivation is to make team members feel autonomy. Given that a leader’s role inherently involves conveying messages on behalf of the organization, leaders easily become the source of extrinsic motivation — which is why I had to consciously take actions that strengthened team members’ autonomy.&lt;/p&gt;
&lt;p&gt;Here are the main methods I used:&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;Avoid top-down, notification-style decision-making&lt;/li&gt;
&lt;li&gt;Delegate final decision-making authority to each squad’s frontend engineers for their own services&lt;/li&gt;
&lt;li&gt;Always discuss the frontend chapter’s reason for existence, goals, and mission together&lt;/li&gt;
&lt;li&gt;Communicate that a leader is not a boss, and that mutual feedback is essential&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;avoid-top-down-decision-making&quot; style=&quot;position:relative;&quot;&gt;Avoid top-down decision-making&lt;a href=&quot;#avoid-top-down-decision-making&quot; aria-label=&quot;avoid top down decision making permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most fundamental stance I took as a leader was avoiding notification-style decisions. Notification is essentially external pressure that expects compliance, and it severely undermines team members’ autonomy.&lt;/p&gt;
&lt;p&gt;So when making decisions about the chapter, I made a point of sharing problems and directions openly — posting agenda items in Slack channels, walking over to ask people directly, adding items to weekly meeting agendas — ensuring everyone in the chapter had an opportunity to participate in the decision-making process.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 78.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABumprSpigf//EABoQAAIDAQEAAAAAAAAAAAAAAAACAQMTBBL/2gAIAQEAAQUCzQwgzrF71gZva2dC1v8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAgEFAQAAAAAAAAAAAAAAAAECETEyQZEi/9oACAEBAAY/AsFwwiWXDBnmSVdjhem0f//EABwQAQEBAAEFAAAAAAAAAAAAAAERABAhMVGhsf/aAAgBAQABPyEZhkj8ocfbfRNKZDs6zQw+YI7/2gAMAwEAAgADAAAAEGjf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EFtL/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Qh//EABwQAQADAQADAQAAAAAAAAAAAAEAESExUWGR0f/aAAgBAQABPxAAmvAP5Ddtq0Mk518cfn0UCnh2BrQhBaY9ORaLqWmE/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;meeting&quot; title=&quot;&quot; src=&quot;/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg&quot; srcset=&quot;/static/783da1105578e0f9950fffb6d49bf961/0913d/meeting.jpg 160w,
/static/783da1105578e0f9950fffb6d49bf961/cb69c/meeting.jpg 320w,
/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg 640w,
/static/783da1105578e0f9950fffb6d49bf961/6a068/meeting.jpg 960w,
/static/783da1105578e0f9950fffb6d49bf961/eea4a/meeting.jpg 1280w,
/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg 1685w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Not everyone&apos;s opinion can be reflected in every decision,&lt;br&gt;but at least opening the opportunity to participate provides a degree of autonomy.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;It’s true that having the leader make decisions first and then announce them for feedback is faster. But I believed that preserving team members’ intrinsic motivation mattered more than the speed gained from top-down announcements. That’s why I chose to collect feedback before making decisions. Besides, in a small organization of just 5–6 people like the one I led, the leader actively gathering opinions doesn’t significantly slow things down. &lt;em&gt;(And no matter how talented the leader, it’s hard to beat collective intelligence.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I also judged that if people are given the chance to participate in decision-making, they’re more likely to empathize with the final decision compared to a simple announcement. Even if their opinion wasn’t adopted, they had the chance to voice it and hear the reasoning behind why it wasn’t — a form of equality of opportunity.&lt;/p&gt;
&lt;p&gt;Of course, depending on the team member’s personality and situation, some may find it hard to voice their opinions. But since the organization provided ample opportunity to speak up, whether or not they actually do so is their own choice, which doesn’t significantly violate their autonomy.&lt;/p&gt;
&lt;p&gt;However, the leader’s response should differ depending on whether someone’s reluctance stems from an internal characteristic like an introverted personality, or from external factors like being new to the company, having recently been criticized, or having been burned by office politics at a previous job.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/072a9adb700670671eb12dbe4a7c7d4a/b4294/pressure.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAUDAf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAbXZtA4kjXQMgf/EABoQAAICAwAAAAAAAAAAAAAAAAECABIDERP/2gAIAQEAAQUCtotEe64yelp1fdqw5WlQZ//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAAMAAgMAAAAAAAAAAAAAAAABEQIQITFR/9oACAEBAAY/Ap7q4lORzIai71T/xAAbEAACAwADAAAAAAAAAAAAAAABEQAhMUFRYf/aAAgBAQABPyEqmLwHsbfJUDGbD332YawghAy6gMwkALZUyccnaE//2gAMAwEAAgADAAAAELDnAv/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABYRAAMAAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxAj/8QAHRABAQADAAIDAAAAAAAAAAAAAREAITFBUWFxsf/aAAgBAQABPxAShtLaPzAzVJSXmADbtaNPjHdC1ls9b8FwQoQRWOwyQCyOM3lghXswyA5tmSDpu0B9Z//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;pressure&quot; title=&quot;&quot; src=&quot;/static/072a9adb700670671eb12dbe4a7c7d4a/b4294/pressure.jpg&quot; srcset=&quot;/static/072a9adb700670671eb12dbe4a7c7d4a/0913d/pressure.jpg 160w,
/static/072a9adb700670671eb12dbe4a7c7d4a/cb69c/pressure.jpg 320w,
/static/072a9adb700670671eb12dbe4a7c7d4a/b4294/pressure.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;This is a common preconception among workers in Korean corporate culture,&lt;br&gt;so don&apos;t expect people to speak up enthusiastically just because you ask for opinions.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;In the former case, if someone’s personality simply doesn’t incline them toward asserting their views, pushing them to share opinions probably won’t change anything. You can change simple behaviors like habits, but altering the personality of someone already in adulthood is no easy feat. &lt;em&gt;(This is why hiring well from the start is so important.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this case, the person may be in a state of amotivation or may not have clearly established their growth direction, so you need to find some motivating factor through conversation and at least provide extrinsic motivation. In the latter case, simply removing the blocking factor or showing supportive gestures can naturally increase their participation.&lt;/p&gt;
&lt;p&gt;Of course, given the nature of a company, there are decisions made by executives or decisions that can’t be openly discussed — situations where notification becomes unavoidable.&lt;/p&gt;
&lt;p&gt;In those cases, explain in detail to the team: why the notification is happening, who the decision-maker is, and the reasoning behind the decision. Express that you’re sorry it had to be communicated this way.&lt;/p&gt;
&lt;p&gt;If you don’t properly explain the rationale behind such notifications, team members will feel disrespected by the organization, which can damage intrinsic motivation. The leader must make clear that this isn’t about disrespecting the team, and thoroughly explain the circumstances that made it unavoidable.&lt;/p&gt;
&lt;h3 id=&quot;delegate-final-decision-making-authority-to-each-squads-frontend-engineers&quot; style=&quot;position:relative;&quot;&gt;Delegate final decision-making authority to each squad’s frontend engineers&lt;a href=&quot;#delegate-final-decision-making-authority-to-each-squads-frontend-engineers&quot; aria-label=&quot;delegate final decision making authority to each squads frontend engineers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The second value I upheld was ensuring that each squad’s frontend engineers had final decision-making authority over their own services.&lt;/p&gt;
&lt;p&gt;Even as chapter lead, I couldn’t make product decisions on their behalf. If I had a good idea, I’d propose it to the relevant squad’s engineer and delegate the choice to them. Many organizations withhold decision-making authority from juniors or new hires, but I delegated trust and authority regardless of experience level.&lt;/p&gt;
&lt;p&gt;I had two main reasons for this. First, to create intrinsic motivation through autonomy, as discussed above. Second, to ensure that the emotions around success and failure from decision outcomes were felt most strongly by the team member themselves.&lt;/p&gt;
&lt;p&gt;I believe all humans grow through failure, so each individual’s sense and emotional response to failure within the team is extremely important.&lt;/p&gt;
&lt;p&gt;But if a leader gives specific instructions, the emotions around success and failure no longer belong to the team member. The leader held the final decision-making authority, and the team member merely followed orders — so the emotional weight of outcomes tends to be attributed to the decision-maker, the leader. &lt;em&gt;(If the leader also has a self-serving bias (taking credit for successes and blaming others or circumstances for failures), team members’ frustration will only grow. In the worst case, the team implodes.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When a team member makes their own decision and faces the consequences, the sense of responsibility they feel is far greater than when the leader made the call for them. I believe this is the most fundamental element of what people commonly call the “autonomy and responsibility” principle.&lt;/p&gt;
&lt;p&gt;However, if you design this environment and then blame team members for their failures, that’s a shortcut to disaster. This kind of environment must be accompanied by a value like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everyone can fail. It’s okay to fail.&lt;/p&gt;
&lt;p&gt;But if you do fail, make sure you extract the lessons learned and share them so your colleagues don’t repeat the same mistakes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;New hires and junior members especially tend to fear failure, so the leader absolutely needs to say this explicitly. You could also intentionally show small failures of your own as the leader, though this approach can backfire and erode trust if you haven’t built enough rapport yet — so read the room.&lt;/p&gt;
&lt;p&gt;These kinds of practices aren’t common in typical Korean companies, so some team members may be experiencing them for the first time. In such cases, side effects can occur — people being afraid of being the decision-maker, or beating themselves up for not expressing their thoughts well — requiring appropriate responses from the leader.&lt;/p&gt;
&lt;p&gt;From the leader’s perspective, when you delegate final decision-making authority, you’re still on the hook if things go wrong. Delegating authority doesn’t free you from responsibility for the team’s failures. In other words, by delegating final decision-making to team members, you deliberately create a situation where you have responsibility without authority. &lt;del&gt;(You have to dig your own grave.)&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;Some leaders might feel anxious about losing control when they delegate decision-making authority. But if you’ve built sufficient rapport or present solid logical reasoning, most team members will seriously consider the leader’s proposals before making their decision — and in the end, things often go the way the leader suggested anyway.&lt;/p&gt;
&lt;p&gt;What matters, then, is the leader’s persuasive ability and the trust they’ve built with team members. If a team member doesn’t follow my suggestion, I think it’s healthier to reflect on whether I failed to persuade them, rather than to blame them.&lt;/p&gt;
&lt;p&gt;Over a year and a half, I delegated final decision-making authority to various frontend engineers. Regardless of experience level, anyone who passed the three-month probation could participate as an interviewer, among other policies. Apart from occasional cases where someone was nervous about having decision-making responsibility, it was rarely a problem. In most cases, through chapter-wide discussions or suggestions from me or other colleagues, people made good decisions.&lt;/p&gt;
&lt;p&gt;For interview process participation in particular, there were reactions like “Am I really qualified to evaluate someone?” But starting with résumé screening, they quickly adapted — and some even ended up proposing improvements to fill gaps in the interview process.&lt;/p&gt;
&lt;p&gt;If anything, this decision-making structure enabled the frontend chapter to make decisions quickly, which translated to increased overall performance.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/56eb2f16b822e0987728e86234b6bad5/019a6/commits.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 27.500000000000004%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAyUlEQVR42p2QzY7CMAyE8z6U5o/SNkmTLELaQuHGEd7/MYZJumIlJC4cPo09cWzLYqNHfI16jx2E3Ee0u/Ad+wDZUy11KPEEoUpDGz7z3sSsutUBKnuoE5k99NXX5kJ2Eyd5tP06sVLint7wl3e+si2bRH6+OMjkYW4O9kHuK3rx3HBIMD8J+hChU4Q9ZJgjYW6OqXomZtiUoQNrf1mzTLBzwm6hf06ENXNEd80Qjfk/bFNx9cCNcq+jv3zWNpLaru81lmPNixbvCdRBw12y6juTAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;commits&quot; title=&quot;&quot; src=&quot;/static/56eb2f16b822e0987728e86234b6bad5/6af66/commits.png&quot; srcset=&quot;/static/56eb2f16b822e0987728e86234b6bad5/69538/commits.png 160w,
/static/56eb2f16b822e0987728e86234b6bad5/72799/commits.png 320w,
/static/56eb2f16b822e0987728e86234b6bad5/6af66/commits.png 640w,
/static/56eb2f16b822e0987728e86234b6bad5/d9199/commits.png 960w,
/static/56eb2f16b822e0987728e86234b6bad5/21b4d/commits.png 1280w,
/static/56eb2f16b822e0987728e86234b6bad5/019a6/commits.png 1818w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;You can roughly gauge performance by looking at the trend of commits merged to main.&lt;br&gt;I joined in March 2022, and the frontend chapter only grew by three people over that period.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;While some expressed concern about this system, the reality is that I only delegated final decision-making — I didn’t tell anyone to be a dictator. Any team member’s decision-making process was naturally accompanied by suggestions and feedback from other team members. The pressure of being responsible for their own decisions also compelled them to strive for the most rational choices possible.&lt;/p&gt;
&lt;p&gt;This feedback came in various forms — code reviews, Slack discussions, or offline conversations — and the decision-maker would hear diverse opinions from colleagues before making the final call. Most problems get caught through this process.&lt;/p&gt;
&lt;p&gt;There may be small failures early on when you first delegate, but as I discussed, since the failure resulted from their own choice, they’ll naturally work to avoid repeating the same mistakes. The motivation for this effort might be extrinsic — not wanting to lose colleagues’ trust, or self-satisfaction — but humans inherently possess a need for competence, a desire to be recognized by others. Nobody wants to look incompetent, so they inevitably make the effort.&lt;/p&gt;
&lt;p&gt;Of course, if someone keeps repeating the same failures, you need to provide appropriate feedback while being careful not to let them lose too much sense of competence through self-deprecation like “I’m hopeless at everything.” Just be honest — acknowledge what they’re doing well and suggest working together on areas that need improvement. &lt;em&gt;(I found myself saying this kind of thing a lot when helping colleagues strategize for passing their probation period.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By delegating decision-making authority to the engineer who knows their squad’s situation best and supporting them, you remove the funnel of reporting to and getting approval from someone — increasing decision speed. You accelerate growth by letting team members directly experience the emotions of failure. And in the long run, you strengthen team members’ autonomy and competence.&lt;/p&gt;
&lt;p&gt;However, this kind of decision-making structure carries a high risk of devolving into everyone-does-their-own-thing chaos, so clear goal alignment across the entire team is absolutely essential.&lt;/p&gt;
&lt;h3 id=&quot;always-discuss-the-chapters-reason-for-existence-and-mission-together&quot; style=&quot;position:relative;&quot;&gt;Always discuss the chapter’s reason for existence and mission together&lt;a href=&quot;#always-discuss-the-chapters-reason-for-existence-and-mission-together&quot; aria-label=&quot;always discuss the chapters reason for existence and mission together permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The third value I upheld was always discussing the frontend chapter’s reason for existence and mission together as a team. An organization, by definition, is a group formed to achieve goals that can’t be accomplished alone — its very raison d’être comes from its mission.&lt;/p&gt;
&lt;p&gt;If people have no say in something this important, it’s only natural for their sense of belonging to decline. So when defining the frontend chapter’s purpose, I made every effort to incorporate as many team members’ opinions as possible.&lt;/p&gt;
&lt;p&gt;These missions were typically defined in OKR format, and I made sure discussions focused more on the Objective — the essence of the mission — than on Key Results, which are merely indicators of whether the mission has been achieved.&lt;/p&gt;
&lt;p&gt;A clear goal like “we are a team organized to achieve X, our mission is Y, and our strategy to achieve it is Z” is essentially a belief about why the frontend chapter can meaningfully exist within the company.&lt;/p&gt;
&lt;p&gt;If this belief wavers, sentiment like “I don’t even know why the frontend chapter exists” can form both inside and outside the chapter. This leads to declining morale and sense of belonging, which in turn erodes competence and intrinsic motivation.&lt;/p&gt;
&lt;p&gt;Another reason organizational mission matters so much is that running an organization isn’t like StarCraft, where you just hotkey your units and attack-move. It’s more like Overwatch or PUBG — games where diverse humans with individual decision-making abilities come together to fight toward a shared objective.&lt;/p&gt;
&lt;p&gt;StarCraft units don’t question orders. They faithfully execute whatever command is given, even if you send naked Marines without Medics into a field of Lurkers for certain annihilation. That’s why a single player can comfortably control dozens of units with 100% compliance.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f65bcc2a376d4096f7dd96c85e80a523/e811e/starcraft.webp&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRnQAAABXRUJQVlA4IGgAAACQAwCdASoUAAsAPtFUo0uoJKMhsAgBABoJZwAAKZMiOSZ6N48AAP6D8LCXxye6Sw9VzNZuMt908H/TIL5d9rtu/M2Jh7bGriXafJbW3eH9HIkK85FXn/wNpS2QjFIPbwt1UH2+10oAAA==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;starcraft&quot; title=&quot;&quot; src=&quot;/static/f65bcc2a376d4096f7dd96c85e80a523/0ba47/starcraft.webp&quot; srcset=&quot;/static/f65bcc2a376d4096f7dd96c85e80a523/60a22/starcraft.webp 160w,
/static/f65bcc2a376d4096f7dd96c85e80a523/4c812/starcraft.webp 320w,
/static/f65bcc2a376d4096f7dd96c85e80a523/0ba47/starcraft.webp 640w,
/static/f65bcc2a376d4096f7dd96c85e80a523/e46b2/starcraft.webp 960w,
/static/f65bcc2a376d4096f7dd96c85e80a523/e811e/starcraft.webp 1060w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;If you mistake organizational management for StarCraft, team pushback is inevitable.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;But in games like Overwatch or PUBG, calling out orders is critical. These are games where multiple humans form a team to achieve objectives together.&lt;/p&gt;
&lt;p&gt;When you’re supposed to push the payload together but one teammate keeps charging into enemy lines for kills and dying, while another is left guarding the payload alone and getting overwhelmed — the game grinds to a halt. The leader needs to call out clearly: “Everyone focus on pushing the payload,” “The rest of you draw aggro from the payload while Genji takes out Widowmaker.” &lt;em&gt;(Unless the team is deep in the lower ranks, this shouldn’t happen too often… I think.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Real organizational management works similarly. Games at least provide a clear built-in objective, so there’s no need to think about goals. Real organizations have to align on goals first. Without this process, you end up with a team in name only — where one person is playing Overwatch and another is playing PUBG.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ddd1754f6428521be9f2d73642b9e0b1/e1596/star.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB5b8cFhYf/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAECERID/9oACAEBAAEFAoqyXOhoU2jbNH//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwGn/8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGBABAQEBAQAAAAAAAAAAAAAAAQARITH/2gAIAQEAAT8hOZdul4gQe99lN//aAAwDAQACAAMAAAAQiN//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxCI/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/EIa//8QAGBABAQEBAQAAAAAAAAAAAAAAAREAIVH/2gAIAQEAAT8QYBZgEI0pG6CwkI+vcWOhVpkKnd//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;star&quot; title=&quot;&quot; src=&quot;/static/ddd1754f6428521be9f2d73642b9e0b1/c08c5/star.jpg&quot; srcset=&quot;/static/ddd1754f6428521be9f2d73642b9e0b1/0913d/star.jpg 160w,
/static/ddd1754f6428521be9f2d73642b9e0b1/cb69c/star.jpg 320w,
/static/ddd1754f6428521be9f2d73642b9e0b1/c08c5/star.jpg 640w,
/static/ddd1754f6428521be9f2d73642b9e0b1/6a068/star.jpg 960w,
/static/ddd1754f6428521be9f2d73642b9e0b1/eea4a/star.jpg 1280w,
/static/ddd1754f6428521be9f2d73642b9e0b1/e1596/star.jpg 2048w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;An organization&apos;s goal is the coordinates of a star everyone navigates toward.&lt;br&gt;If everyone doesn&apos;t have the same star&apos;s coordinates in their heads, the voyage will struggle.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;That’s why I made sure that important values like the frontend chapter’s purpose and mission were always defined through everyone’s participation, input, and discussion. Most internal policies were also established in the same way, which I believe kept team members’ autonomy quite high.&lt;/p&gt;
&lt;p&gt;Team members with high autonomy would work late into the night to pursue directions they believed in — without anyone asking them to. Their capabilities weren’t constrained at all; if they wanted to try something, they just had to persuade their chapter colleagues with sound reasoning. It would have been strange if it &lt;em&gt;weren’t&lt;/em&gt; fun. &lt;em&gt;(Of course, proposals did get rejected plenty of times too…)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Organizational goals — being somewhat abstract and distant concepts — are easily forgotten in the busyness of daily work. But naturally, goals you set yourself stick in your mind longer than goals imposed by someone else.&lt;/p&gt;
&lt;p&gt;I let the frontend chapter determine its own direction. My role was simply to nudge that direction ever so slightly to ensure it benefited the company as a whole.&lt;/p&gt;
&lt;h3 id=&quot;communicate-that-a-leader-is-not-a-boss-and-that-mutual-feedback-is-essential&quot; style=&quot;position:relative;&quot;&gt;Communicate that a leader is not a boss, and that mutual feedback is essential&lt;a href=&quot;#communicate-that-a-leader-is-not-a-boss-and-that-mutual-feedback-is-essential&quot; aria-label=&quot;communicate that a leader is not a boss and that mutual feedback is essential permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The final value I considered important was mutual feedback. I believe that a leader and team members aren’t in a hierarchical relationship — they simply have different roles. And to perform well in each of those roles, you inevitably need help from your colleagues.&lt;/p&gt;
&lt;p&gt;A mutual feedback environment also enhances team members’ autonomy by giving them the power to influence the leader’s direction. Of course, simply exchanging feedback isn’t enough — the leader needs to express gratitude after receiving feedback and demonstrate genuine receptiveness. &lt;em&gt;(And if you disagree with the feedback, just explain your reasoning in detail.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;No human is perfect. Even the most talented person has both strengths and weaknesses, and no matter how long someone has worked, they’re inevitably a beginner in areas outside their expertise.&lt;/p&gt;
&lt;p&gt;I have clear strengths, but I also have clear weaknesses. My knowledge in areas outside frontend development — the field I’ve spent years in — is relatively limited, and I can’t claim to be an expert in everything.&lt;/p&gt;
&lt;p&gt;I imagine the same is true for most people. A single, small human can’t possibly be good at everything in this world.&lt;/p&gt;
&lt;p&gt;In very small startups with around ten employees, a talented leader might handle many things simultaneously like a firefighter. But as organizations grow, that becomes increasingly difficult, and failing to delegate properly can produce various side effects.&lt;/p&gt;
&lt;p&gt;Moreover, in such leader-dependent structures, if the leader isn’t exceptionally capable, the entire organization’s performance crumbles along with them. Active mutual feedback can serve as a means to grow the leader when they’re falling short, or to hedge against the leader’s insufficient decision-making ability.&lt;/p&gt;
&lt;p&gt;However, in traditional companies where leaders are often equated with bosses, it’s hard to establish a robust feedback culture unless the leader genuinely possesses the capacity to accept feedback and the ability to separate feedback from their emotions.&lt;/p&gt;
&lt;p&gt;Feedback receptiveness connects to metacognition. Since metacognition is the high-level concept of “knowing what you don’t know,” it’s not easy to cultivate on your own. Most people find themselves in a state where they don’t even know what they don’t know, yet think “I know a lot” — a kind of Sophist thinking.&lt;/p&gt;
&lt;p&gt;Paradoxically, I believe the best way to develop metacognitive ability is through team members’ feedback. In practice, as I worked in a leadership role and talked with many people, I often found significant gaps between how I saw myself and how others saw me.&lt;/p&gt;
&lt;p&gt;Here’s my own example. The left column is my self-assessment; the right is feedback from colleagues:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Trait&lt;/th&gt;
&lt;th&gt;My Assessment&lt;/th&gt;
&lt;th&gt;Others’ Assessment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Not very emotionally volatile&lt;/td&gt;
&lt;td&gt;I can make decisions without emotional interference&lt;/td&gt;
&lt;td&gt;Your tone is too cold. We’d like to see more inclusion, not exclusion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I tend to share opinions first&lt;/td&gt;
&lt;td&gt;I express my thoughts clearly&lt;/td&gt;
&lt;td&gt;Your expression is so strong that it’s hard to voice opposing views&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I don’t show personal emotions at work&lt;/td&gt;
&lt;td&gt;I clearly separate work and personal life&lt;/td&gt;
&lt;td&gt;You seem unapproachable and lacking warmth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These value judgments inherently include a kind of self-serving bias, so one tends to judge oneself leniently and others strictly. Personal rapport can introduce bias as well. I’m just another human who can’t escape these biases — which is why my self-assessment was skewed positively.&lt;/p&gt;
&lt;p&gt;But ultimately, one thing matters: a leader is in a position where they need to earn others’ trust. So rather than how you see yourself, what matters more is how others perceive your characteristics — and you need to know that clearly and respond accordingly.&lt;/p&gt;
&lt;p&gt;My point isn’t “don’t fall into bias.” While I’m no psychology expert, I believe it’s nearly impossible to completely eliminate these biases.&lt;/p&gt;
&lt;p&gt;What matters is the leader recognizing: “I have biases and errors,” “I’m not that perfect.”&lt;/p&gt;
&lt;p&gt;A leader is human, so naturally there will be areas of strength and areas of weakness. But if you’re not clearly aware of your strengths and weaknesses and try to micromanage beyond your competence or grab excessive decision-making authority, the result can be worse for the organization overall — and it can create problems in earning team members’ trust.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3ab89b5cf9446157970eacacf05d02a3/7bf67/control.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAULnWaBCH//EABsQAAMAAgMAAAAAAAAAAAAAAAABAgMSExQh/9oACAEBAAEFAib2E/OxTJyODnZ//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRABAAIDAAAAAAAAAAAAAAAAAAExEBFB/9oACAEBAAY/ArTp3Eqf/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARIVFBwf/aAAgBAQABPyF99ZkMJJXSHT4qarCZAG+zmCf/2gAMAwEAAgADAAAAELsP/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8Qp//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/EIf/xAAcEAEAAwACAwAAAAAAAAAAAAABABEhMWFxsdH/2gAIAQEAAT8QdjuAoDa2HHXWVb4jdnhwPaAQhoBVU5+wgAu3tMQGCsXZ/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;control&quot; title=&quot;&quot; src=&quot;/static/3ab89b5cf9446157970eacacf05d02a3/c08c5/control.jpg&quot; srcset=&quot;/static/3ab89b5cf9446157970eacacf05d02a3/0913d/control.jpg 160w,
/static/3ab89b5cf9446157970eacacf05d02a3/cb69c/control.jpg 320w,
/static/3ab89b5cf9446157970eacacf05d02a3/c08c5/control.jpg 640w,
/static/3ab89b5cf9446157970eacacf05d02a3/7bf67/control.jpg 680w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Humans tend to think in ways biased by their experiences,&lt;br&gt;
  so if your early career was spent in a control-heavy organization, your leadership may unconsciously lean toward control as well. This is why metacognition matters.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;A leader isn’t someone who controls team members. They’re someone complementary to them. After all, the role of leader can only exist because team members exist.&lt;/p&gt;
&lt;p&gt;So you need to learn how others perceive you through their feedback, and by taking appropriate action items, shape how you appear to your team in the right direction.&lt;/p&gt;
&lt;p&gt;But stepping out of the ideal and into reality, you’ll find that in most organizations where feedback culture hasn’t taken root, people are afraid to transparently share their thoughts about others. Especially in Eastern cultures that value the group over the individual, a “leader” is often equated with a “commander” — so breaking this preconception is important.&lt;/p&gt;
&lt;p&gt;That’s why leaders need to actively communicate that they want feedback, and deliberately — even exaggeratedly — demonstrate a receptive attitude.&lt;/p&gt;
&lt;p&gt;I held coffee chats with everyone in the frontend chapter every two weeks, and at the end of each session, I always asked for feedback. I consistently made explicit statements like: “Giving me feedback helps me grow,” “I’m not perfect either, and I want to improve my weaknesses through feedback,” “Just as you want to grow, I’m just another developer who wants to grow too.” My goal was to make team members think, “This person is genuinely obsessed with feedback…”&lt;/p&gt;
&lt;p&gt;Of course, extracting meaningful feedback every two weeks isn’t easy — most sessions were a parade of “Nothing in particular.” But by persistently maintaining this practice, I was able to receive meaningful feedback from time to time. &lt;em&gt;(Like being told to come in earlier in the morning…)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When I received feedback I resonated with, I’d establish action items to address it and always share the results afterward. Many things didn’t actually improve, but it was a way of actively signaling that I didn’t ignore their feedback.&lt;/p&gt;
&lt;p&gt;It varies somewhat by personality, but in an authority-oriented culture like Korea’s, giving feedback to a leader takes considerable courage. So naturally, the person receiving feedback should express gratitude for the courage it took, and demonstrate that every word was taken to heart.&lt;/p&gt;
&lt;p&gt;Even if you didn’t agree with the feedback, always express gratitude first for the courage it took, and then explain why you didn’t fully resonate with it.&lt;/p&gt;
&lt;p&gt;Be careful, though: reacting emotionally to feedback, or saying “thank you” but then showing no action items or sharing no follow-through. These patterns will cause team members to develop the mindset “Talking to this person won’t change anything,” and they’ll eventually stop speaking up.&lt;/p&gt;
&lt;p&gt;If more and more colleagues start feeling this way, the organization can become like a boiling pressure cooker, ready to blow at any moment. Frustration with the leader has already built up, but people either fear speaking up or feel powerless that nothing will change even if they do.&lt;/p&gt;
&lt;p&gt;That’s why a leader should consistently and proactively seek feedback from colleagues — continuously gathering information that helps develop metacognition: how colleagues perceive you, where you’re falling short, and what you’re doing well.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After about three years of leadership experience and reflection, the dominant feeling I’ve had is probably “…this is really hard.”&lt;/p&gt;
&lt;p&gt;Computers are friendly companions. Give them a command and they faithfully execute it. Humans, by contrast, are wildly inconsistent in behavior and thought, emotional, riddled with all kinds of biases, and astonishingly diverse.&lt;/p&gt;
&lt;p&gt;Of course, people with high empathy intelligence who genuinely enjoy working with others might thrive in such an environment. But I’m a capital-T on the MBTI — not particularly high in empathy intelligence, and not someone who draws energy from people. So I needed a lot of reflection and research on topics like “what makes good leadership” and “what drives people.”&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dfc9d10866e65a8c46faf88ef1edd58a/2a614/estj.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 52.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB/klEQVR42pWSS28SYRSG+VH+he50rUZjigsTdWFxocSwtF5iF2bQpqLQFkq5OkMHehlsCpkaKDNMhkI7UKYz1Ja2XIoj7fAB31wQbE1J48ZnfZ735OQ9ht4f9N4luq5rmtb7F5o+PNgzXDGHM1QF9mNKPw4EsVSH3V/tzrmv6UPyGVS3JCBDpQ1amqruCiJFUdKpXG5IoAUw15cXZtOT5IaFzVCVyvCygYzkDh4TTK7W/CnLigqdyMQD42iuUk+VK035tMqlwvaJ54HgMxy/43S5GYaun5204YW8d3iIe51MrfY0RY1jQaPNbcNXotn8VLqA0bRlMWJ2zzlnZz0ulxVBbChKCEdCsz2QpU4HY+iXnyctWOgRSd6a9484Fh/OBG96V6/Nk5YkfzsYued0TU59eo9YZxyOd3b7ApWqyvJA5kQxQBDT7rml2Fp4Z+e1xztqvD9mNt9w4COe+PUodxclx0ymV2/eItYP8XicTdNLsdh3lgUt2dABgC8UEskNJp0uiwLNsti36CoZT1OpEJkYJxIfw9FpXwANR0RRaDROqrVqGwAVwm63O7gZQigIu/3Uryjq9/mCAX9oIbSyvLweW2OS61mG3sxm8vnt/f294+MjAMBlz/rf3hVFkSSpWCxmNi/I9sltbXMcz/OlUqler/U7vvok51/V+39+A6aNKxTcsapfAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;estj&quot; title=&quot;&quot; src=&quot;/static/dfc9d10866e65a8c46faf88ef1edd58a/6af66/estj.png&quot; srcset=&quot;/static/dfc9d10866e65a8c46faf88ef1edd58a/69538/estj.png 160w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/72799/estj.png 320w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/6af66/estj.png 640w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/d9199/estj.png 960w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/21b4d/estj.png 1280w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/2a614/estj.png 5000w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;For the record, my MBTI is a strong ESTJ. I don&apos;t love admitting it, but it&apos;s surprisingly accurate.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;I’m actually someone who’s good at analyzing relationships and connecting them through logical reasoning. So the approach that worked best for me was building knowledge from academic research on human psychology and behavioral principles, then observing and analyzing the people around me to test those theories against reality.&lt;/p&gt;
&lt;p&gt;Of course, no theory explains reality perfectly — especially human behavior, which remains a largely unsolved domain with no definitive answers. All I can do is observe the various situations happening around me, ask myself “why is that person behaving that way?”, and conduct my own analysis.&lt;/p&gt;
&lt;p&gt;Perhaps that’s exactly why I found it so difficult. There aren’t many problems in the world with predetermined right answers, but analyzing and defining something as illogical as humans seems truly, genuinely hard.&lt;/p&gt;
&lt;p&gt;I’m still a fledgling leader with only three years under my belt, so these reflections are just the beginning. There are plenty of days ahead for this kind of thinking, and I’m in no rush.&lt;/p&gt;
&lt;p&gt;This concludes my post: What Do People Work For? — The Psychology of Motivation.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[인간은 무엇을 위해 일하는가? – 동기 부여의 심리학]]></title><description><![CDATA[이번 포스팅에서는 지난 3년 간 IC(Individual Contributor)가 아닌 한 명의 리더로써 좋은 리더란 무엇인지, 또 좋은 리더가 되려면 어떤 역량들이 필요한지에 대해 고민해봤던 내용에 대해서 간단하게 적어보려고 한다. 아무리 IC로써 일을 잘 했던 사람이라고 해도 이 경험이 좋은 리더로써의 역량으로 이어지리란 법은 없기 때문에 자연스럽게 이런 고민을 시작하게 되었던 것 같다.]]></description><link>https://evan-moon.github.io/2023/10/03/how-to-be-a-better-leader/</link><guid isPermaLink="false">20231003-how-to-be-a-better-leader</guid><pubDate>Mon, 30 Oct 2023 01:04:23 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 지난 3년 간 IC(Individual Contributor)가 아닌 한 명의 리더로써 좋은 리더란 무엇인지, 또 좋은 리더가 되려면 어떤 역량들이 필요한지에 대해 고민해봤던 내용에 대해서 간단하게 적어보려고 한다.&lt;/p&gt;
&lt;p&gt;아무리 IC로써 일을 잘 했던 사람이라고 해도 이 경험이 좋은 리더로써의 역량으로 이어지리란 법은 없기 때문에 자연스럽게 이런 고민을 시작하게 되었던 것 같다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;많은 개발자들이 리더나 매니저 역할을 맡게 되면 어렵다고 느끼는 부분은 컴퓨터와 다르게 인간은 전혀 논리적으로 행동하지 않는다는 점에서 기인한다.&lt;/p&gt;
&lt;p&gt;A라는 명령을 내리면 그대로 A라고 알아듣고 수행하는 컴퓨터와 다르게 인간은 A라고 이야기를 했을 때 곧이 곧대로 A라고 이해하는 경우가 거의 없다. 인간은 각자 자라온 환경이나 지금까지 겪어온 경험에 따른 편향을 가지고 있을 수 밖에 없기 때문에, 똑같이 A라고 이야기를 해도 각자 다르게 반응할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;또한 컴퓨터는 동일한 환경이라면 동일한 퍼포먼스를 내는 것이 보장되지만, 인간은 평소에 100%의 퍼포먼스를 잘 내다가도 논리적이지 않은 이유로 인해 갑자기 50%의 퍼포먼스를 내는 등 행동에 대한 예측이 어렵다.&lt;/p&gt;
&lt;p&gt;애초에 컴퓨터라는 계산기를 잘 다루는 능력으로 인정받았던 사람들이 어느 날 갑자기 전혀 논리적이지 않은 인간이라는 객체를 다뤄야 하니, 어렵지 않다고 하면 더 이상할 것이다.&lt;/p&gt;
&lt;p&gt;필자 또한 인간에 대한 근본적 이해가 부족했던 탓에 잘못된 의사결정으로 인한 팀원들의 사기를 저하시키거나 심리적 지지를 해줘야 하는 순간에 그러지 못해 상처를 입히는 등 여러가지 유형의 실패를 경험했다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 리더에게는 단지 커뮤니케이션 뿐 아니라 나 스스로에 대한 이해와 인간 본연의 심리와 본능, 조직의 특성에 대한 이해와 같은 인문학적인 소양까지도 필요하다고 느꼈고, 좋은 리더가 되기 위해 우선 인간 본연에 대한 이해와 이러한 인간 객체들이 집단을 이루었을 때 어떤 특성을 띄는지에 대한 이해도를 높혀야 한다고 생각했다.&lt;/p&gt;
&lt;h2 id=&quot;좋은-리더란-무엇일까&quot; style=&quot;position:relative;&quot;&gt;좋은 리더란 무엇일까?&lt;a href=&quot;#%EC%A2%8B%EC%9D%80-%EB%A6%AC%EB%8D%94%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C&quot; aria-label=&quot;좋은 리더란 무엇일까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;3년 전 토스에서 처음 F-Lead라는 역할을, 그리고 쿼타랩에서 Frontend Chapter Lead라는 역할을 맡게 되었을 때 스스로에게 가장 먼저 물었던 질문은 “좋은 리더란 무엇인가?”였다.&lt;/p&gt;
&lt;p&gt;“좋다”라는 가치판단의 기준은 각각의 인간 객체마다 다를 수 밖에 없는 주관적인 것이기에 정답이라고 말할 수 있는 건 없겠지만, 필자는 이 질문에 대한 스스로의 철학과 정의가 없다면 방향성을 잃고 이도 저도 아닌 리더가 되어버릴 것이라고 생각했다.&lt;/p&gt;
&lt;p&gt;결국 리더라는 역할은 다양한 사람들이 모인 조직에서 그 사람들을 특정한 방향으로 발맞춰 움직이게 만드는 것이다. Lead라는 단어가 이끈다는 의미를 가지고 있기 때문에 남을 이끄는 것이 좋은 리더의 역량이라고 생각할 수도 있지만, 필자는 사람들을 특정 방향으로 움직이게 할 수만 있다면 앞에서 이끌든 뒤에서 밀든 크게 상관 없다고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;사람들을-움직이게-하는-힘은-무엇일까&quot; style=&quot;position:relative;&quot;&gt;사람들을 움직이게 하는 힘은 무엇일까?&lt;a href=&quot;#%EC%82%AC%EB%9E%8C%EB%93%A4%EC%9D%84-%EC%9B%80%EC%A7%81%EC%9D%B4%EA%B2%8C-%ED%95%98%EB%8A%94-%ED%9E%98%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C&quot; aria-label=&quot;사람들을 움직이게 하는 힘은 무엇일까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;리더라는 역할이 단순히 사람들을 통제하는 역할이 아니라 사람들을 특정 방향으로 움직이게 만들어야 하는 것이라면, 이제 사람들을 움직이게 만드는 힘이 무엇인지에 대해서 고민을 해봐야할 차례이다.&lt;/p&gt;
&lt;p&gt;다행히도 이미 심리학, 교육학 등의 분야에서는 이미 오랜 시간 동안 인간의 동기와 행동 유발 원리에 대한 많은 논의와 실험이 진행되어왔기 때문에 필자는 이런 실험 결과나 논문을 읽어보며 문제에 차근차근 접근해볼 수 있었다.&lt;/p&gt;
&lt;h3 id=&quot;자기결정성-이론&quot; style=&quot;position:relative;&quot;&gt;자기결정성 이론&lt;a href=&quot;#%EC%9E%90%EA%B8%B0%EA%B2%B0%EC%A0%95%EC%84%B1-%EC%9D%B4%EB%A1%A0&quot; aria-label=&quot;자기결정성 이론 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;그 중 필자가 주목한 이론은 동기 이론 중 하나인 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EA%B8%B0%EA%B2%B0%EC%A0%95%EC%84%B1_%EC%9D%B4%EB%A1%A0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;자기결정성 이론&lt;/a&gt;이었다. 이 이론은 인간은 흥미, 호기심과 같은 내적 통제 요인에 의해 스스로 동기를 부여하고 행동하며 심리적인 성장과 통합을 향해 능동적으로 자아를 발전시키는 존재라고 말하고 있으며, 이러한 대상의 자율성, 유능성, 관계성이 내재적 동기와 높은 정적 상관관계를 보인다고 말한다.&lt;/p&gt;
&lt;p&gt;평생교육에 대한 담론에서 주로 이야기하는 &lt;a href=&quot;http://www.kcsedu.kr/bbs_detail.php?bbs_num=63&amp;#x26;b_category=&amp;#x26;id=&amp;#x26;tb=board_info&amp;#x26;pg=&amp;#x26;links_number=&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;안드라고지(Andragogy)&lt;/a&gt;처럼 성인의 행동 유발 원리를 이해할 때는 학습자의 의지와 같은 자율성을 더더욱 중요하게 생각하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;그리고 결국 자율성이란 자신이 스스로 선택하여 행동한다는 의지가 반영된 심리의 산물이므로, 필자는 사람들의 행동을 특정 방향으로 이끌어내기 위해서 먼저 그 방향성에 대한 공감이 필요하다고 생각한다.&lt;/p&gt;
&lt;p&gt;결국 공감이라는 것은 세뇌라도 시키지 않는 이상 누군가가 외부에서 강제로 주입할 수 있는 것이 아니며, 스스로가 결정하고 납득해야하는 감정이기 때문에 내재적인 동기를 유발시키기에 가장 적합한 감정이기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 내재된 동기가 없는 상태에서 이러한 외적 통제 요인으로만 사람들의 행동을 이끌어낸다면 그 행동을 수행하기에 방해가 되는 스트레스가 주어졌을 때 스트레스에 대한 저항력이 낮을 수 밖에 없다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e5da4b9f591a004456c5e04af9415083/0ff19/tree2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 53.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwElEQVR42pVSO08CQRBeHiIatdCWxsZCG7G00tZoaaMWNlQYH4WF8R+oiSZqpZ29oSDBhNgDWUgOPI7jdSLBaLjjIBxG8bHOHCc5DCayydx8O9/M7Oy3R8gfizFm1T3Puz+q1adPMMRmrqcFRXbdNxqHsiyziqoyVq8fmLleG7YmjEaXmprWaNbrL4zSxX9PCEmWDk+IHWwIzMpCoXF2fT0B2GLE7N1qujXtw9MfCBmAokFspseXl23M5RowDrIip+dALtZ0vZoaibjlQkGoJpMnHVe+vBwu5/PBaqEQlK+uRsycEo8fq8ViUqV0ph2Hjw03JUo9DU1j5fv7hPkajz7f5EM+//VcKn283d5OmbmSKCaar69M4TiPEbe1X+zU6x1j5fIuU5TZH9KYpJ9VKmtvkrROUFdo1v4DarVZrLnY2Rn9/fpOLARDncwCoz4O0tLSafBmzaxGzGHwhGSz2aNAIKBrIAjCcUYQ5hBnMpl9SumKjkVxA7hNxOFweFWSpD09P5GYF6EGsd/vn87lcicknU5rkLyEQVEUFZ7ntxBD/A72Z4hTqdQN4BvEwJ8Dl0TMcdw2YBVxLBZbgOHevwE+GTuxd0aw3gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;tree2&quot; title=&quot;&quot; src=&quot;/static/e5da4b9f591a004456c5e04af9415083/6af66/tree2.png&quot; srcset=&quot;/static/e5da4b9f591a004456c5e04af9415083/69538/tree2.png 160w,
/static/e5da4b9f591a004456c5e04af9415083/72799/tree2.png 320w,
/static/e5da4b9f591a004456c5e04af9415083/6af66/tree2.png 640w,
/static/e5da4b9f591a004456c5e04af9415083/d9199/tree2.png 960w,
/static/e5da4b9f591a004456c5e04af9415083/21b4d/tree2.png 1280w,
/static/e5da4b9f591a004456c5e04af9415083/0ff19/tree2.png 2084w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;사람이 많아지면 설득과 공감을 통한 리더십이 불가능하다는 의견도 있지만&lt;br&gt;
  어차피 그 정도로 큰 조직이면 리더가 매번 모든 팀원과 직접 소통하는 구조가 아닐 가능성이 높다.&lt;br&gt;
  리더는 중간 리더들에게, 중간 리더들은 팀원들에게 같은 방식으로 소통하면 된다.&lt;br&gt;
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;특히 스타트업과 같이 먼 곳에 있는 미션을 달성하기 위해 높은 업무 강도, 긴 업무 시간 등 거친 상황을 감수해야하는 상황이 발생하기 쉬운 환경이라면 더더욱 스트레스 저항력에 대한 고민이 필요하다. 스트레스는 조직 구성원의 생산성, 몰입도, 소속감 등을 저해하는 요소이기 때문에 단순히 한 인간의 문제로만 치부하고 넘어갈 수 있는 문제가 아니라고 생각한다.&lt;/p&gt;
&lt;p&gt;결국 내재적 동기가 없는 팀원에게 열심히 리더의 목표를 이야기한다고 사람들이 알잘딱 따라주거나 열심히 해주지는 않는다는 이야기이다. 혹은 어찌어찌 따라주더라도 근본적으로 리더의 목표와 권위라는 외적 통제 요인으로부터 비롯된 행동이니, 팀원들에게 가혹한 스트레스가 주어지는 환경에서 그 행동을 오랜 시간 지속하기를 기대하기란 어려울 것이다.&lt;/p&gt;
&lt;p&gt;또한 외재적 동기는 행위 자체보다는 결과에 초점을 맞추는 경향이 있기 때문에 도구적인 특성이 강하며, 만약 “제가 말씀드린대로 잘 해주고 계시네요”와 같이 통제 목적의 자극이 주어진다면 자율성과 내재적 동기가 훼손되어 생산성이 크게 떨어진다는 시각 또한 존재한다.&lt;/p&gt;
&lt;p&gt;특히 IT와 같이 기계적인 업무를 반복하는 것이 아닌 창의력이 요구되는 업계에 종사하는 사람인 경우, 인센티브와 같은 물적 보상에서 비롯된 외재적 동기가 더욱 힘을 쓰지 못 한다는 의견도 있다. 게다가 이러한 외재적 동기를 지속적으로 부여하게 되면 장기적으로 내재적 동기를 손상시킬 위험도 있기에 이런 방법을 사용할 때는 상당히 정교한 보상 설계가 필요하다. &lt;small&gt;(회사가 성과와 연동된 인센티브를 주다가 갑자기 끊는다고 생각해보자. “어차피 돈도 안 나오는데 왜 함”이라고 생각하게 되지 않을까?)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그래서 필자는 팀원들이 스트레스풀한 환경에서도 높은 동기를 유지하고 적극적으로 조직에 기여를 하게 만들기 위해서는 최대한 높은 자율성을 느낄 수 있는 환경을 구축하여 조직 내 인간 객체들의 높은 자기실현 경향성을 보장해주어야 한다고 생각했다.&lt;/p&gt;
&lt;h3 id=&quot;내가-스스로-결정했다고-느끼게-만들어주기&quot; style=&quot;position:relative;&quot;&gt;내가 스스로 결정했다고 느끼게 만들어주기&lt;a href=&quot;#%EB%82%B4%EA%B0%80-%EC%8A%A4%EC%8A%A4%EB%A1%9C-%EA%B2%B0%EC%A0%95%ED%96%88%EB%8B%A4%EA%B3%A0-%EB%8A%90%EB%81%BC%EA%B2%8C-%EB%A7%8C%EB%93%A4%EC%96%B4%EC%A3%BC%EA%B8%B0&quot; aria-label=&quot;내가 스스로 결정했다고 느끼게 만들어주기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;사실 리더 입장에서는 성과를 낸 사람에게는 상을 주고 제대로 해내지 못 한 사람에게는 벌을 주거나, 혹은 정치와 같은 외적 통제 요인을 사용하여 사람들을 움직이게 만드는 것이 더 편하기는 하다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 이야기했듯 성인의 행동 유발 원리에는 내적 동기가 꽤나 중요한 부분을 차지하기 때문에 이런 외적 통제 요인만을 부여하게 되면 사기가 떨어지거나, 뒷담화가 생기거나, 조직의 상황에 관심을 끊어버리는 등과 같은 사이드이펙트가 터지기 쉬운 환경이 될 위험이 존재한다.&lt;/p&gt;
&lt;p&gt;물적자원과 다르게 인적자원은 각각의 객체가 감정을 가지고 사고할 수 있기 때문에 기계론적인 시각으로는 예측과 통제가 어려운 것이다.&lt;/p&gt;
&lt;p&gt;그래서 리더는 사람들의 내적 동기가 유발될 수 있는 환경을 마련해주어야 하는데, 이런 환경을 구축하기 위해서 적절한 의사결정권의 위임, 기술/비즈니스적으로 Small Win을 맛볼 수 있는 환경, 명확한 목표/기대치 제시 등 여러가지 방법들을 사용해볼 수 있지만, 그 중에서 필자는 자율성의 가치에 가장 무게를 두었다.&lt;/p&gt;
&lt;p&gt;팀원이 회사에서 느끼는 자율성이란 결국 자신이 맡은 제품에 대한 의사결정권 행사, 통보가 아닌 의견을 물어보는 리더의 태도, 팀원에게 몇 가지 선택권을 주고 직접 선택하게 하는 행위 등을 통해 팀원이 자신의 자율성을 행사하여 스스로 조직에 기여하고 있다는 느낌을 받거나 혹은 실제로 기여하는 것을 의미한다.&lt;/p&gt;
&lt;p&gt;어차피 자율성은 통증과 같은 명확한 감각이 아니라 자신이 스스로 자율성을 행사하고 있다고 믿는 심리적인 자각이므로, 팀원들이 알게 모르게 조직이 원하는 방향으로 움직이고 있더라도 본인이 자율성이 있다고 믿는다면 자율성이 확보된다고 보는 것이다.&lt;/p&gt;
&lt;p&gt;또한 국내와 해외 관계없이 업무 자율성이 조직에 대한 신뢰나 업무 만족도, 몰입도, 성과에 대해 유의미한 정적 상관관계를 보인다는 실증 연구 결과도 이미 많이 존재한다. 즉, 자율성이 내재적 동기를 불러일으킬 수 있다는 사실에는 흔히 이야기하는 서양과 동양의 사고 방식 차이와도 큰 관련이 없다고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;물론 회사라는 조직의 특성 상 모든 인간의 자율성을 100% 보장해줄 수는 없겠지만, 앞서 이야기했듯 자율성은 객관적 감각이 아닌 심리적인 자각이므로 리더가 팀원의 자율성을 지지하는 행위를 보이는 것만으로도 어느 정도 효과를 볼 수도 있으며, 또는 리더의 역량에 따라 조직으로부터 부여되는 외재적 동기들을 내재화하여 통합할 수 있도록 만들어 볼 수도 있을 것이다.&lt;/p&gt;
&lt;h2 id=&quot;팀원들의-자율성을-강화할-수-있는-리더의-행동&quot; style=&quot;position:relative;&quot;&gt;팀원들의 자율성을 강화할 수 있는 리더의 행동&lt;a href=&quot;#%ED%8C%80%EC%9B%90%EB%93%A4%EC%9D%98-%EC%9E%90%EC%9C%A8%EC%84%B1%EC%9D%84-%EA%B0%95%ED%99%94%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%A6%AC%EB%8D%94%EC%9D%98-%ED%96%89%EB%8F%99&quot; aria-label=&quot;팀원들의 자율성을 강화할 수 있는 리더의 행동 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;그렇다면 팀원들의 자율성을 높힐 수 있는 방법들에는 어떤 것들이 있을까?&lt;/p&gt;
&lt;p&gt;필자는 가장 먼저 현재 조직의 상태, 즉 조직 내부에 있는 각 인간 객체들의 동기가 무엇인지에 대해서 분석하고 진단해야 한다고 생각한다. 어차피 자율성은 내재적 동기를 만들어내어 업무 생산성과 몰입도를 높히기 위한 선결조건이니 이미 사람들이 내재적 동기를 가지고 있다면 딱히 큰 고민을 할 필요가 없기 때문이다. &lt;small&gt;(근데 막상 분석과 관찰을 해보면 생각보다 내재적 동기를 기반으로 움직이는 사람은 별로 없는 것 같다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;팀원들과 1 on 1 미팅을 해보며 “현재 하고 계신 업무가 재밌으신가요”, “개발자가 왜 되셨나요”와 같이 직접적인 질문을 통해 물어보는 방법도 있지만, 개인적으로 필자는 사담에서 나오는 정보를 토대로 분석을 진행하는 편이다.&lt;/p&gt;
&lt;p&gt;왜냐하면 내가 상대방에게 질문을 던지는 순간 상대방이 그 질문에 편향된 사고를 하거나 리더와의 미팅이라는 불편한 자리의 특성과 괜히 모난 돌이 되기 싫다는 동양 특유의 집단주의가 맞물려 자신의 본래 마음을 100% 털어놓지 않을 가능성도 있기 때문이다. 특히 상대방을 편향시키지 않는 질문 방법은 유저 리서치, 인터뷰 등 상대방에게 정보를 얻어내야 하는 상황에서 굉장히 중요한데, 이게 생각보다 쉽지 않다.&lt;/p&gt;
&lt;p&gt;그런 이유로 필자는 1 on 1 미팅 같은 오피셜한 시간보다는 평소 함께 담배 한 대 피는 상황, 카페에서 수다떠는 상황, 퇴근 후 같이 저녁먹는 상황처럼 편안한 환경에서 나오는 정보들이 더 솔직하고 가치있는 정보일 가능성이 높다고 생각한 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/88bbaa99baf8428b6ba76c3155bfa436/92f8c/coffeechat.webp&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRqAAAABXRUJQVlA4IJQAAADQAwCdASoUAAoAPtFUo0uoJKMhsAgBABoJYwCw7BkpyV2/BHFckAAA/pvji9/W2qDheS63N7lYqMRN5bw/LSPvJdYOLlD/IEO4bR7tqTNTS5aW2M9ZvgsCUzkZUItHH3NW15GyKNZA6i2r90hoG+c//yAGLbxjKNebsEjIWGyXkz4QRqq7P7+S2Fqulyh/0AfV8AAA&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;coffeechat&quot; title=&quot;&quot; src=&quot;/static/88bbaa99baf8428b6ba76c3155bfa436/0ba47/coffeechat.webp&quot; srcset=&quot;/static/88bbaa99baf8428b6ba76c3155bfa436/60a22/coffeechat.webp 160w,
/static/88bbaa99baf8428b6ba76c3155bfa436/4c812/coffeechat.webp 320w,
/static/88bbaa99baf8428b6ba76c3155bfa436/0ba47/coffeechat.webp 640w,
/static/88bbaa99baf8428b6ba76c3155bfa436/e46b2/coffeechat.webp 960w,
/static/88bbaa99baf8428b6ba76c3155bfa436/92f8c/coffeechat.webp 1200w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;편한 환경을 만들어주고 우호적인 제스처를 보여줄수록 나에게 진심을 말할 가능성이 높아진다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그렇게 얻어낸 정보들 중 의미가 있다고 판단되는 것들은 기록해두고 &lt;a href=&quot;https://scholarworks.bwise.kr/hanyang/handle/2021.sw.hanyang/143183&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;자기결정성이론의 HRD 적용에 대한 논의&lt;/a&gt;라는 학술자료에서 제안한 분류 방법을 사용하여 다음과 같은 유형으로 사람들의 동기를 나눠보았다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;동기 유형&lt;/th&gt;
&lt;th&gt;행동 원리&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;무동기&lt;/td&gt;
&lt;td&gt;왜 하는지 모른다&lt;/td&gt;
&lt;td&gt;나는 왜 이 일을 해야 하는지 모르겠다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;외적조절&lt;/td&gt;
&lt;td&gt;결과를 얻기 위해&lt;/td&gt;
&lt;td&gt;나는 사내평가에서 높은 점수를 받기 위해서 이 일을 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;내사조절&lt;/td&gt;
&lt;td&gt;의무감 때문에&lt;/td&gt;
&lt;td&gt;내가 좋은 팀원이 되려면 이 일을 해야하기 때문에 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;동일시조절&lt;/td&gt;
&lt;td&gt;그 일이 중요하기 때문에&lt;/td&gt;
&lt;td&gt;이 일이 회사의 성장을 위해 필요한 일이기 때문에 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;통합조절&lt;/td&gt;
&lt;td&gt;그 일이 곧 나의 가치이기 때문에&lt;/td&gt;
&lt;td&gt;이 일을 하는 것이 내 가치관을 표현하는 것이기 때문에 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;내재동기&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;그 일 자체가 흥미롭기 때문에&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;나는 이 일 자체가 너무 흥미롭고 재밌기 때문에 한다&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;🤔 한 가지 특이한 점은 일을 시작한지 얼마 안 된 사람일수록 내사조절 또는 내재동기를 가지고 있는 케이스가 많으며, 일을 시작한지 오래된 사람인 경우 외적조절 또는 동일시조절인 케이스가 많았다는 점이다.&lt;/p&gt;
&lt;p&gt;아무래도 개발자라는 직업을 선택한 이유가 “개발이 재밌어서”인 경우 아직 그 학습동기를 마음 속에 가지고 있어서인 것 같기도 하고, 아무래도 나이가 더 많은 시니어의 경우에는 자신의 흥미 외에도 책임져야 할 일들이 많아서인 것 같기도 하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;어쨌든 필자가 정의한 리더의 역할은 외적조절, 내사조절, 동일시조절, 통합조절과 같은 외재적 동기에 의해 움직이는 사람들을 내재적 동기에 의해 움직일 수 있도록 만드는 것이다. 쉽게 말하면 “사람들이 재밌게 일할 수 있는 환경”이 무엇인지 고민하고 그런 환경을 만들기 위해 노력해야한다는 것이다.&lt;/p&gt;
&lt;p&gt;그리고 동기를 내재화 시킬 수 있는 방법은 팀원들에게 자율성을 느끼게 해주는 것이다. 사실 회사라는 조직의 특성과 그 조직을 대변하는 메세지를 주로 전달하는 리더의 역할 특성 상 리더는 대부분 외재적 동기를 부여하는 존재가 되어버리기 쉽기 때문에 필자는 의식적으로 팀원들의 자율성을 강화할 수 있는 행동을 해나가야 했다.&lt;/p&gt;
&lt;p&gt;필자 같은 경우는 팀원들에게 자율성을 느끼게 해주기 위해 다음과 같은 방법들을 주로 사용했다.&lt;/p&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;통보식 의사결정 하지않기&lt;/li&gt;
&lt;li&gt;각 스쿼드의 프론트엔드 엔지니어들에게 자신이 맡은 서비스에 대한 최종의사결정권을 위임한다.&lt;/li&gt;
&lt;li&gt;프론트엔드 챕터라는 조직의 존재 이유, 목표, 미션에 대해서는 반드시 함께 논의하기.&lt;/li&gt;
&lt;li&gt;리더는 상사가 아니며 상호 피드백이 반드시 필요하다는 사실을 이야기하고 다니기&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;통보식-의사결정-하지않기&quot; style=&quot;position:relative;&quot;&gt;통보식 의사결정 하지않기&lt;a href=&quot;#%ED%86%B5%EB%B3%B4%EC%8B%9D-%EC%9D%98%EC%82%AC%EA%B2%B0%EC%A0%95-%ED%95%98%EC%A7%80%EC%95%8A%EA%B8%B0&quot; aria-label=&quot;통보식 의사결정 하지않기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 리더로써 취한 가장 기본적인 태도는 단순 통보식 의사결정을 피하는 것이었다. 애초에 통보라는 행위는 복종을 기대하는 외압이기 때문에 팀원의 자율성을 크게 저해한다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 필자는 챕터에 대한 의사결정을 할 때 슬랙 채널에 안건 공개, 자리에 찾아가서 직접 물어보기, 위클리 미팅 아젠다로 올리기 등의 액션을 통해 가급적이면 필자가 고민하는 문제나 방향성을 공개적으로 공유하고 챕터의 모두가 이 의사결정에 참여할 수 있는 기회를 마련했다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 78.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABumprSpigf//EABoQAAIDAQEAAAAAAAAAAAAAAAACAQMTBBL/2gAIAQEAAQUCzQwgzrF71gZva2dC1v8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAgEFAQAAAAAAAAAAAAAAAAECETEyQZEi/9oACAEBAAY/AsFwwiWXDBnmSVdjhem0f//EABwQAQEBAAEFAAAAAAAAAAAAAAERABAhMVGhsf/aAAgBAQABPyEZhkj8ocfbfRNKZDs6zQw+YI7/2gAMAwEAAgADAAAAEGjf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EFtL/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Qh//EABwQAQADAQADAQAAAAAAAAAAAAEAESExUWGR0f/aAAgBAQABPxAAmvAP5Ddtq0Mk518cfn0UCnh2BrQhBaY9ORaLqWmE/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;meeting&quot; title=&quot;&quot; src=&quot;/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg&quot; srcset=&quot;/static/783da1105578e0f9950fffb6d49bf961/0913d/meeting.jpg 160w,
/static/783da1105578e0f9950fffb6d49bf961/cb69c/meeting.jpg 320w,
/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg 640w,
/static/783da1105578e0f9950fffb6d49bf961/6a068/meeting.jpg 960w,
/static/783da1105578e0f9950fffb6d49bf961/eea4a/meeting.jpg 1280w,
/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg 1685w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;의사결정에 모든 이의 의견이 반영될 수는 없지만&lt;br&gt;최소한 의사결정에 참여할 기회라도 열어준다면 어느 정도의 자율성은 충족된다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;물론 리더가 의사결정을 미리 한 후 통보를 하고 피드백을 받는 방식이 속도는 더 빠르다. 하지만 필자는 여기서 얻는 속도의 이점보다 팀원들의 내재 동기를 최대한 해치지 않는 것이 더 중요하다고 생각했기 때문에 의사결정 전에 피드백을 받는 방식을 택한 것이다. 게다가 필자가 리더로 있던 꼴랑 5-6명 짜리 조직에서는 리더가 바쁘게 움직이며 의견을 수집한다면 속도가 크게 떨어지지도 않는다. &lt;small&gt;(게다가 리더가 아무리 잘났어도 집단지성을 이기기란 쉽지 않다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;또한 의사결정에 참여할 수 있는 기회를 준다면 이후 결정된 내용에 대해서 공감할 확률이 단순 통보 방식보다 높다고 판단했다. 자신의 의견이 반영되지 않았더라도 팀원들에게 그 의견을 이야기할 수는 있었고, 반영되지 않는 이유에 대해서도 그 자리에서 충분히 들을 수 있었을테니 말이다. 일종의 기회의 평등인 셈이다.&lt;/p&gt;
&lt;p&gt;물론 팀원의 성향과 상황에 따라 자신의 의견을 내기 어려워하는 경우도 있지만, 조직에서 자신의 의견을 말할 수 있는 기회를 충분히 주었으니, 이후 발언 여부 자체는 본인의 선택이기 때문에 자율성을 크게 침해하지 않는다.&lt;/p&gt;
&lt;p&gt;다만 이 사람이 의견을 내기 어려워하는 이유가 내성적인 성격과 같은 내면적 특성에서 발현된 것인지, 혹은 원래는 자기 주관이 있는 편인데도 입사한 지 얼마 안 되었거나, 최근 누군가에게 비난을 받았거나, 전직장에서 의견을 밝혔다가 정치질을 당했거나하는 외적 요인으로부터 그 행동이 가로막히고 있는 것인지에 따라 리더의 행동도 달라져야 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/072a9adb700670671eb12dbe4a7c7d4a/b4294/pressure.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAUDAf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAbXZtA4kjXQMgf/EABoQAAICAwAAAAAAAAAAAAAAAAECABIDERP/2gAIAQEAAQUCtotEe64yelp1fdqw5WlQZ//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAAMAAgMAAAAAAAAAAAAAAAABEQIQITFR/9oACAEBAAY/Ap7q4lORzIai71T/xAAbEAACAwADAAAAAAAAAAAAAAABEQAhMUFRYf/aAAgBAQABPyEqmLwHsbfJUDGbD332YawghAy6gMwkALZUyccnaE//2gAMAwEAAgADAAAAELDnAv/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABYRAAMAAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxAj/8QAHRABAQADAAIDAAAAAAAAAAAAAREAITFBUWFxsf/aAAgBAQABPxAShtLaPzAzVJSXmADbtaNPjHdC1ls9b8FwQoQRWOwyQCyOM3lghXswyA5tmSDpu0B9Z//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;pressure&quot; title=&quot;&quot; src=&quot;/static/072a9adb700670671eb12dbe4a7c7d4a/b4294/pressure.jpg&quot; srcset=&quot;/static/072a9adb700670671eb12dbe4a7c7d4a/0913d/pressure.jpg 160w,
/static/072a9adb700670671eb12dbe4a7c7d4a/cb69c/pressure.jpg 320w,
/static/072a9adb700670671eb12dbe4a7c7d4a/b4294/pressure.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이게 일반적인 대한민국 직장인들의 선입견이니&lt;br&gt;그냥 의견을 묻는다고 해서 처음부터 바로 적극적으로 이야기하는 사람이 많지는 않을 것이다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;전자의 경우 애초에 성격 자체가 자기 주장하는 것을 좋아하지 않는 것이니 굳이 의견을 이야기해달라고 푸쉬해봤자 바뀌지 않을 가능성이 높다. 습관과 같은 간단한 행동을 바꿀 수는 있어도 이미 인격이 형성되어버린 성인기의 성격을 바꾸는 것은 쉬운 일이 아니기 때문이다. &lt;small&gt;(이래서 처음부터 채용을 잘 하는 것 또한 굉장히 중요하다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이 경우 무동기 상태이거나 아직 자신의 발전 방향성을 명확하게 잡지 못 했을 가능성이 있으니 대화를 통해 어떻게든 동기가 될만한 포인트를 찾아서 외재적 동기라도 부여하는 조치가 필요하지만, 후자의 경우 그냥 해당 요인을 제거해주거나 팀원을 지지해주는 제스쳐를 보여주는 것만으로 자연스레 참여도가 높아지기도 한다.&lt;/p&gt;
&lt;p&gt;물론 회사라는 조직의 특성 상 경영진이 내린 의사결정이나 공개된 토론을 할 수 없는 의사결정도 있기 마련이라 부득이하게 통보를 하게 되는 상황이 발생할 수도 있다.&lt;/p&gt;
&lt;p&gt;이 경우는 통보를 하게 된 이유, 의사결정권자가 누구인지, 이런 의사결정이 내려진 이유 등을 팀원들에게 상세히 설명하고 이렇게 전달드리게되어 죄송하다는 이야기를 하자.&lt;/p&gt;
&lt;p&gt;특히 이렇게 통보를 하는 경우 이 의사결정의 근거와 이유를 제대로 설명하지 않는다면 팀원들은 조직으로부터 존중받지 못 한다는 느낌을 받아 내재적 동기가 훼손될 수 있기 때문에 리더는 반드시 이 통보가 팀원들을 존중하지 않아서 그런 게 아니라는 것과 그럴 수 밖에 없었던 상황을 잘 설명해야 한다.&lt;/p&gt;
&lt;h3 id=&quot;각-스쿼드의-프론트엔드-엔지니어들에게-자신이-맡은-서비스에-대한-최종의사결정권을-위임한다&quot; style=&quot;position:relative;&quot;&gt;각 스쿼드의 프론트엔드 엔지니어들에게 자신이 맡은 서비스에 대한 최종의사결정권을 위임한다.&lt;a href=&quot;#%EA%B0%81-%EC%8A%A4%EC%BF%BC%EB%93%9C%EC%9D%98-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%93%A4%EC%97%90%EA%B2%8C-%EC%9E%90%EC%8B%A0%EC%9D%B4-%EB%A7%A1%EC%9D%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EC%97%90-%EB%8C%80%ED%95%9C-%EC%B5%9C%EC%A2%85%EC%9D%98%EC%82%AC%EA%B2%B0%EC%A0%95%EA%B6%8C%EC%9D%84-%EC%9C%84%EC%9E%84%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;각 스쿼드의 프론트엔드 엔지니어들에게 자신이 맡은 서비스에 대한 최종의사결정권을 위임한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 중요하게 지켰던 가치 중 두 번째는 바로 각 스쿼드의 프론트엔드 엔지니어들이 자신이 맡은 서비스에 대한 최종의사결정권을 가지도록 하는 것이었다.&lt;/p&gt;
&lt;p&gt;챕터 리드라고 해도 각 제품에 대한 의사결정을 대신 할 수는 없으며, 좋은 아이디어가 있다면 해당 스쿼드의 엔지니어에게 제안을 하고 선택권을 위임한다. 많은 조직들이 특히 주니어나 신입 엔지니어에게는 의사결정권을 주지 않는 경우가 많은데, 필자는 경력 여하와 상관없이 일단 신뢰를 보내고 의사결정권을 위임했다.&lt;/p&gt;
&lt;p&gt;이런 정책을 사용한 이유는 크게 2가지였는데, 첫 번째는 앞서 이야기했던 자율권에서 비롯된 내재적 동기를 만들어내기 위해서이고 두 번째는 의사결정으로 인해 파생된 결과로 인한 성공과 실패에 대한 감정을 오롯이 팀원이 더 강하게 느끼도록 하기 위해서이다.&lt;/p&gt;
&lt;p&gt;필자는 모든 인간은 실패를 통해 성장한다고 생각하기에 팀 내의 개개인들이 느끼는 실패에 대한 감각과 감정 또한 굉장히 중요하다고 생각한다.&lt;/p&gt;
&lt;p&gt;하지만 리더가 팀원에게 특정한 지시를 한다면 그 액션에 대한 성공과 실패에 대한 감정은 팀원의 것이 아니게 된다. 리더가 해당 액션에 대한 최종의사결정권을 가졌고 팀원은 그저 타인이 시키는대로 한 것이기 때문에 결과에 대한 감정들 또한 의사결정권자인 리더에게 강하게 귀속될 가능성이 높다. &lt;small&gt;(만약 잘 되면 내 탓, 안 되면 남이나 상황 탓을 하는 자기고양편향까지 가진 리더라면 팀원들의 불만은 더 커질 것이다. 최악의 경우에는 팀이 폭파된다.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그러나 팀원이 스스로 의사결정을 내린 이후 발생한 결과에 대해 스스로가 느끼는 책임감은 리더가 의사결정을 해주었을 때에 비해 크게 다가올 것이다. 필자는 이것이 흔히 이야기하는 자율과 책임 원칙의 가장 근본이 되는 요소라고 생각한다.&lt;/p&gt;
&lt;p&gt;다만 이런 환경을 설계해놓고 실패한 팀원을 비난해버리면 그야말로 망하는 지름길이니, 이런 환경을 구성하려면 반드시 아래와 같은 가치관이 동반되어야 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;누구나 다 실패할 수 있어요. 실패해도 됩니다.&lt;/p&gt;
&lt;p&gt;다만 실패했다면 Lesson &amp;#x26; Learn만 확실하게 뽑고 다른 동료들이 똑같은 삽질을 하지 않도록 공유해주세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;특히 신규입사자나 신입은 실패를 두려워하는 경우가 많으니 리더가 이런 이야기를 반드시 해줘야 한다. 혹은 의도적으로 리더가 작은 실패를 하는 모습을 보여줘도 되지만, 이 방법은 팀원에게서 라포가 어느 정도 쌓여있는 상황이 아니면 오히려 신뢰를 잃어버릴 수도 있으니 상황 봐가면서 하자.&lt;/p&gt;
&lt;p&gt;이런 행동들은 대한민국의 일반적인 기업들에서 흔히 볼 수 있는 리더십은 아니기 때문에 이런 경험을 처음 해보는 팀원들도 있기 마련이다. 이 경우 자신이 의사결정권자라는 사실을 두려워하거나 자신의 생각을 제대로 표현하지 못해 자책하는 등 사이드 이펙트도 발생할 수 있으니 이에 따른 리더의 대응이 필요할 수 있다.&lt;/p&gt;
&lt;p&gt;또한 리더의 입장에서는 이런 식으로 최종의사결정권을 위임했을 때 뭔가가 잘못되면 결국 책임을 져야한다. 의사결정권을 위임했다고 해서 팀의 실패에 대한 책임에서까지 자유로운 것은 아니기 때문이다. 즉, 최종의사결정권을 팀원에게 위임함으로써 권한은 없고 책임만 있는 상황을 자기가 스스로 만들어야 한다는 부담을 져야한다. &lt;small&gt;&lt;del&gt;(내 무덤을 스스로 파야한다)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;또한 리더가 팀원에게 의사결정권을 위임하게되면 더 이상 팀을 컨트롤하지 못 한다는 불안감을 가지게 될 수도 있는데, 어차피 어느 정도 라포를 쌓았거나 충분한 논리적 근거를 제시한다면 팀원들 대부분은 리더가 제안한 내용에 대해서 진지하게 받아들인 상태로 의사결정을 검토하기 때문에 결국은 리더가 제안한 대로 되는 경우가 많다.&lt;/p&gt;
&lt;p&gt;즉, 리더의 설득 역량과 팀원으로부터 쌓아놓은 신뢰 자산이 중요한 것이다. 필자는 내 말을 안 들어주는 팀원이 있다면 그 팀원을 책망하는 것보다 내가 설득하지 못한 것은 아닌지 한번 생각해보는 것이 더 건강한 사고라고 생각한다.&lt;/p&gt;
&lt;p&gt;이렇게 필자는 1년 반 동안 다양한 프론트엔드 엔지니어에게 최종의사결정권을 위임했었고, 경력과 관계없이 3개월의 수습기간을 통과하면 누구든 면접관으로 참여할 수 있는 등의 정책을 사용했었지만, 의사결정 경험이 부족해서 조금 두려워하는 케이스를 제외하면 별로 문제가 되었던 적은 없었다. 대부분의 경우 챕터 내 논의 또는 필자나 다른 동료의 제안을 통해 좋은 의사결정을 하셨기 때문이다.&lt;/p&gt;
&lt;p&gt;특히 인터뷰 프로세스 참여의 경우 “제가 감히 평가를 할 수 있을까요” 뭐 이런 반응도 있었는데, 처음에는 서류 평가부터 참여해보시더니 금방 적응하셔서 나중에는 인터뷰 프로세스에 대한 허점을 보완할 수 있는 제안까지 하시는 경우도 있었다.&lt;/p&gt;
&lt;p&gt;오히려 이러한 의사결정체제로 인해 프론트엔드 챕터는 빠른 속도의 의사결정을 해나갈 수 있었고, 이는 챕터 전체의 퍼포먼스 증가로 이어졌다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/56eb2f16b822e0987728e86234b6bad5/019a6/commits.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 27.500000000000004%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAyUlEQVR42p2QzY7CMAyE8z6U5o/SNkmTLELaQuHGEd7/MYZJumIlJC4cPo09cWzLYqNHfI16jx2E3Ee0u/Ad+wDZUy11KPEEoUpDGz7z3sSsutUBKnuoE5k99NXX5kJ2Eyd5tP06sVLint7wl3e+si2bRH6+OMjkYW4O9kHuK3rx3HBIMD8J+hChU4Q9ZJgjYW6OqXomZtiUoQNrf1mzTLBzwm6hf06ENXNEd80Qjfk/bFNx9cCNcq+jv3zWNpLaru81lmPNixbvCdRBw12y6juTAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;commits&quot; title=&quot;&quot; src=&quot;/static/56eb2f16b822e0987728e86234b6bad5/6af66/commits.png&quot; srcset=&quot;/static/56eb2f16b822e0987728e86234b6bad5/69538/commits.png 160w,
/static/56eb2f16b822e0987728e86234b6bad5/72799/commits.png 320w,
/static/56eb2f16b822e0987728e86234b6bad5/6af66/commits.png 640w,
/static/56eb2f16b822e0987728e86234b6bad5/d9199/commits.png 960w,
/static/56eb2f16b822e0987728e86234b6bad5/21b4d/commits.png 1280w,
/static/56eb2f16b822e0987728e86234b6bad5/019a6/commits.png 1818w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;main 브랜치에 머지되는 커밋의 변화 추이를 보면 대략적인 퍼포먼스를 볼 수 있다.&lt;br&gt;필자는 2022년 3월에 입사했고 그 동안 프론트엔드 챕터의 인원은 3명밖에 늘지 않았다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;몇몇 분들이 이러한 의사결정체제에 대한 불안감을 표하시기는 했지만 사실 팀원에게 최종의사결정권을 위임했을 뿐이지 독재를 하라고 한 게 아니기 때문에 어떤 팀원의 의사결정과정에는 반드시 다른 팀원들의 제안과 피드백이 동반되기 마련이고, 본인이 결정한 내용에 대해서 책임을 져야한다는 부담도 있어 최대한 합리적인 의사결정을 하기 위해 노력할 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;이러한 피드백은 코드 리뷰, 슬랙 채널 또는 오프라인에서의 토론과 같은 다양한 형태로 주어지며 의사결정권자는 동료들의 다양한 의견을 듣고 최종의사결정을 내리게 된다. 이 과정에서 대부분의 문제는 잡히기 마련이다.&lt;/p&gt;
&lt;p&gt;처음 위임을 했을 때는 작은 실패들이 있을 수 있지만, 앞서 이야기한대로 결국 본인이 직접 선택한 행위로 인해 실패한 것이므로 다음에는 같은 실패를 반복하지 않기 위해 당연히 노력할 것이다. 이 노력에 대한 동기는 동료들의 신뢰를 잃지 않기 위해서, 자기만족 등 외재적 동기일 수 있지만 인간은 누구나 어느 정도는 타인에게 인정받고 싶어하는 유능감을 지니고 있어 무능한 사람으로 보이고 싶어하지 않기 때문에 노력할 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;물론 이 과정 속에서 계속 같은 실패를 반복한다면 적절한 방법으로 피드백을 줘야하며, “난 뭘 해도 안 되는 놈이야”와 같은 자기모멸감 때문에 유능감을 너무 크게 잃지 않도록 신경써야한다. 그냥 솔직하게 잘 하는 건 잘 한다고 얘기해주고 부족한 점은 같이 보완해보자고 이야기하면 되는 부분인 것 같다. &lt;small&gt;(필자는 동료들의 수습기간 통과 전략을 함께 고민할 때 이런 이야기를 특히 많이 했었던 것 같다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이렇게 의사결정권을 각 스쿼드의 상황을 제일 잘 알고 있는 엔지니어에게 위임하고 지지함으로써 누군가에게 보고를 하고 허락을 받는 퍼널을 제거하여 의사결정의 속도를 높히고, 실패에 대한 감정을 팀원이 직접 느끼게 하여 성장을 촉진함으로써 퀄리티를 높힐 수 있으며, 장기적으로는 팀원의 자율성과 유능성까지도 챙겨볼 수 있다.&lt;/p&gt;
&lt;p&gt;다만 이런 식의 의사결정체제는 각자가 그냥 하고 싶은대로 해버리는 동상이몽 체제가 되어 대혼란이 발생할 가능성이 높으므로 팀 전체의 명확한 목표 싱크가 반드시 동반되어야 한다.&lt;/p&gt;
&lt;h3 id=&quot;프론트엔드-챕터라는-조직의-존재-이유-미션에-대해서는-반드시-함께-논의하기&quot; style=&quot;position:relative;&quot;&gt;프론트엔드 챕터라는 조직의 존재 이유, 미션에 대해서는 반드시 함께 논의하기&lt;a href=&quot;#%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%B1%95%ED%84%B0%EB%9D%BC%EB%8A%94-%EC%A1%B0%EC%A7%81%EC%9D%98-%EC%A1%B4%EC%9E%AC-%EC%9D%B4%EC%9C%A0-%EB%AF%B8%EC%85%98%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C%EB%8A%94-%EB%B0%98%EB%93%9C%EC%8B%9C-%ED%95%A8%EA%BB%98-%EB%85%BC%EC%9D%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;프론트엔드 챕터라는 조직의 존재 이유 미션에 대해서는 반드시 함께 논의하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 지켰던 세 번째 가치는 바로 프론트엔드 챕터라는 조직의 존재 이유나 미션에 대해서는 반드시 함께 논의한다는 것이다. 애초에 조직은 혼자서는 완수할 수 없는 목표를 달성하기 위한 집단을 의미하는 만큼, 조직의 존재의의는 미션에서부터 온다고 해도 과언이 아니다.&lt;/p&gt;
&lt;p&gt;이렇게 중요한 가치에 대해서 아무런 참여도 할 수 없다면 조직에 대한 소속감이 떨어지는 것이 당연하기 때문에 필자는 프론트엔드 챕터라는 조직의 존재의의를 정의할 때 가급적 많은 팀원들의 의견을 반영하기 위해 노력했다.&lt;/p&gt;
&lt;p&gt;이러한 미션은 주로 OKR의 형태로 정의되었는데, 미션 달성의 여부를 나타내는 지표인 Key Result보다는 미션의 본질인 Objective에 더욱 집중해서 논의하도록 만들었었다.&lt;/p&gt;
&lt;p&gt;“우리는 무엇을 달성하기위해 조직된 팀이며, 우리 팀의 미션은 무엇이고 그 미션을 달성하기 위한 전략은 무엇이다”와 같은 명확한 목표는 말 그대로 프론트엔드 챕터라는 조직이 회사 내에서 어떤 의미를 가지고 존재할 수 있는지에 대한 믿음이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;이 믿음이 흔들린다면 챕터 내외부에서 모두 “프론트엔드 챕터는 왜 있는건지 모르겠다”와 같은 여론이 형성될 수 있으며, 이 경우 팀원들의 사기, 소속감 하락으로 인해 유능성의 상실과 내재적 동기 훼손으로 이어질 가능성이 높다.&lt;/p&gt;
&lt;p&gt;그리고 이러한 조직의 미션이 중요한 또 한 가지 이유는 바로 조직 운영이라는 것이 마치 유닛을 부대지정하고 어택땅때리면 되는 스타크래프트가 아니라는 것이다. 오히려 조직 운영은 각각의 의사결정역량을 가진 다양한 인간이 모여 하나의 목표를 달성하기 위해 싸워야 하는 오버워치나 배틀그라운드에 가깝다.&lt;/p&gt;
&lt;p&gt;스타크래프트의 유닛들은 명령을 받았을 때 이 명령에 대한 아무런 판단을 하지 않는다. 그저 명령을 내린대로 충실하게 수행할 뿐이다. 비록 메딕도 안 붙은 쌩마린을 럴커 밭에 보내서 전멸이 확정되어있더라도 그 유닛들은 그대로 명령을 따른다. 그렇기 때문에 수 많은 유닛들을 100% 플레이어의 의도대로 편하게 컨트롤할 수 있는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f65bcc2a376d4096f7dd96c85e80a523/e811e/starcraft.webp&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRnQAAABXRUJQVlA4IGgAAACQAwCdASoUAAsAPtFUo0uoJKMhsAgBABoJZwAAKZMiOSZ6N48AAP6D8LCXxye6Sw9VzNZuMt908H/TIL5d9rtu/M2Jh7bGriXafJbW3eH9HIkK85FXn/wNpS2QjFIPbwt1UH2+10oAAA==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;starcraft&quot; title=&quot;&quot; src=&quot;/static/f65bcc2a376d4096f7dd96c85e80a523/0ba47/starcraft.webp&quot; srcset=&quot;/static/f65bcc2a376d4096f7dd96c85e80a523/60a22/starcraft.webp 160w,
/static/f65bcc2a376d4096f7dd96c85e80a523/4c812/starcraft.webp 320w,
/static/f65bcc2a376d4096f7dd96c85e80a523/0ba47/starcraft.webp 640w,
/static/f65bcc2a376d4096f7dd96c85e80a523/e46b2/starcraft.webp 960w,
/static/f65bcc2a376d4096f7dd96c85e80a523/e811e/starcraft.webp 1060w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;조직 운영을 스타크래프트로 착각하게 되면 당연히 팀원들의 반발이 있을 수 밖에 없다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;하지만 오버워치나 배틀그라운드 같은 게임은 오더(Order)가 굉장히 중요하다. 이런 게임은 여러 명의 인간이 하나의 팀을 이뤄 목표를 달성하는 게임이기 때문이다.&lt;/p&gt;
&lt;p&gt;분명 다 같이 화물을 목표지점까지 밀어야 이기는 게임인데, 어떤 팀원은 혼자서 킬먹겠다고 계속 적진으로 달려들다가 죽어나가고, 어떤 팀원은 혼자 화물지키고 있다가 죽고 있으면 게임이 진행이 안 된다. 이 경우 리더는 명확하게 “님들 화물 미는 것에만 집중합시다”, “나머지는 화물에서 시선을 끌고 겐지가 위도우 좀 따주세요”와 같은 명확한 요구사항을 이야기하며 팀원들을 이끌어야 한다. &lt;small&gt;(물론 왠만큼 심해가 아니라면 이런 경우는 많지 않다…고 생각한다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;현실에서의 조직 운영도 이와 비슷하다. 심지어 게임은 게임을 클리어하기 위한 명확한 목표를 자체적으로 부여해주기 때문에 목표에 대한 고민을 할 필요도 없지만, 현실의 조직 운영은 목표부터 함께 싱크해야한다. 이런 과정이 없으면 이름만 같은 팀이지 누구는 오버워치를 하고 있고 누구는 배틀그라운드를 하고 있는 진풍경이 펼쳐지는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ddd1754f6428521be9f2d73642b9e0b1/e1596/star.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB5b8cFhYf/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAECERID/9oACAEBAAEFAoqyXOhoU2jbNH//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwGn/8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGBABAQEBAQAAAAAAAAAAAAAAAQARITH/2gAIAQEAAT8hOZdul4gQe99lN//aAAwDAQACAAMAAAAQiN//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxCI/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/EIa//8QAGBABAQEBAQAAAAAAAAAAAAAAAREAIVH/2gAIAQEAAT8QYBZgEI0pG6CwkI+vcWOhVpkKnd//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;star&quot; title=&quot;&quot; src=&quot;/static/ddd1754f6428521be9f2d73642b9e0b1/c08c5/star.jpg&quot; srcset=&quot;/static/ddd1754f6428521be9f2d73642b9e0b1/0913d/star.jpg 160w,
/static/ddd1754f6428521be9f2d73642b9e0b1/cb69c/star.jpg 320w,
/static/ddd1754f6428521be9f2d73642b9e0b1/c08c5/star.jpg 640w,
/static/ddd1754f6428521be9f2d73642b9e0b1/6a068/star.jpg 960w,
/static/ddd1754f6428521be9f2d73642b9e0b1/eea4a/star.jpg 1280w,
/static/ddd1754f6428521be9f2d73642b9e0b1/e1596/star.jpg 2048w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;조직의 목표는 다양한 사람들이 하나의 별을 향해 항해하기 위한 좌표이다.&lt;br&gt;모두의 머릿속에 같은 별의 좌표가 들어있지 않다면 항해는 난항을 겪을 수 밖에 없다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그래서 필자는 프론트엔드 챕터의 존재 의의, 미션과 같은 중요한 가치들은 반드시 모두가 참여해서 의견을 내고 함께 논의하고 정의했다. 또한 챕터 내부에서 정해지는 여러 정책들 또한 대부분 같은 방식으로 정해갔기 때문에 팀원들의 자율성은 상당히 높은 편이었다고 생각한다.&lt;/p&gt;
&lt;p&gt;이렇게 높은 자율성을 가진 팀원들은 누가 시키지 않아도 밤 늦게까지 자신들이 옳다고 생각하는 방향성을 관철하기 위해 일했다. 본인들의 역량이 전혀 제한받지도 않고, 해보고 싶은 것이 있으면 챕터 동료들을 논리적 근거로 설득하기만 하면 해볼 수 있었으니 재미가 없다면 더 이상했을 것이다. &lt;small&gt;(물론 제안이 빠꾸먹는 케이스도 많기는 했지만…)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;애초에 조직의 목표라는 다소 추상적이고 멀어보이는 개념은 평소 바쁘게 일하다보면 쉽사리 잊혀지기 마련이다. 그러나 남이 주입해준 목표보다 스스로의 의지로 정한 목표가 마음 속에 오래 남는 것은 당연하다.&lt;/p&gt;
&lt;p&gt;필자는 프론트엔드 챕터가 스스로 방향성을 결정하되, 그저 이 방향이 회사 전체에 유익한 방향이 될 수 있도록 약간의 방향타만 잡아주었을 뿐이다.&lt;/p&gt;
&lt;h3 id=&quot;리더는-상사가-아니며-상호-피드백이-반드시-필요하다는-사실을-이야기하기&quot; style=&quot;position:relative;&quot;&gt;리더는 상사가 아니며 상호 피드백이 반드시 필요하다는 사실을 이야기하기&lt;a href=&quot;#%EB%A6%AC%EB%8D%94%EB%8A%94-%EC%83%81%EC%82%AC%EA%B0%80-%EC%95%84%EB%8B%88%EB%A9%B0-%EC%83%81%ED%98%B8-%ED%94%BC%EB%93%9C%EB%B0%B1%EC%9D%B4-%EB%B0%98%EB%93%9C%EC%8B%9C-%ED%95%84%EC%9A%94%ED%95%98%EB%8B%A4%EB%8A%94-%EC%82%AC%EC%8B%A4%EC%9D%84-%EC%9D%B4%EC%95%BC%EA%B8%B0%ED%95%98%EA%B8%B0&quot; aria-label=&quot;리더는 상사가 아니며 상호 피드백이 반드시 필요하다는 사실을 이야기하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;마지막으로 필자가 중요하게 생각했던 가치는 바로 상호 피드백이다. 필자는 리더와 팀원은 상하관계가 아니라 서로 맡은 역할이 다를 뿐이며, 서로의 자리에서 자신의 역량을 잘 발휘하기 위해서는 반드시 동료들의 도움이 필요하다고 생각한다.&lt;/p&gt;
&lt;p&gt;또한 상호 피드백 환경은 팀원이 직접 리더의 방향을 변화시킬 수 있는 환경을 구축하여 팀원의 자율성을 향상시켜줄 수 있는 요소이기도 하다. 물론 피드백만 주고 받는다고 끝나는게 아니라 피드백을 받은 이후 리더가 직접 감사를 표하거나 실제로 피드백을 수용하는 태도가 함께 동반되어야 한다. &lt;small&gt;(물론 동의가 어려운 피드백은 그 이유에 대해서 자세히 이야기해주면 된다.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;어차피 인간은 완벽할 수 없다. 아무리 뛰어난 인간이라도 여러가지 강점과 약점이 동시에 존재하며, 아무리 일을 오래 했다고 해도 결국 자신의 전문성이 아닌 분야에서는 초보자가 될 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;필자 또한 강점이 있는 반면 명확한 약점도 함께 보유하고 있으며, 오랜 세월 몸 담아온 프론트엔드가 아닌 다른 분야에 대한 지식은 상대적으로 부족하기 때문에 모든 분야에 대한 전문가라고 말할 수는 없다.&lt;/p&gt;
&lt;p&gt;아마 필자가 아닌 다른 사람들 또한 마찬가지일 것이라고 생각한다. 한낱 한 명의 작은 인간이 이 세상 모든 것들을 다 잘할 수는 없는 법이니 말이다.&lt;/p&gt;
&lt;p&gt;물론 직원이 10명 남짓의 규모가 작은 스타트업에서는 뛰어난 리더 한 명이 일종의 소방관처럼 많은 일들을 동시에 처리하기도 하지만, 조직의 규모가 커지면 커질수록 이러한 행위는 점점 더 어려워지며 이러한 위임을 제대로 하지 못 했을 때는 다양한 사이드 이펙트가 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;게다가 이러한 형태의 조직은 리더의 역량에 굉장히 많은 부분이 좌우되는 만큼, 리더가 훌륭한 역량을 보유한 인재가 아니라면 조직 전체의 역량이 함께 무너지게 되는 리스크 또한 존재한다. 즉, 활발한 상호 피드백은 리더의 역량이 부족할 경우 리더를 성장시키거나, 혹은 리더의 부족한 의사결정역량을 헷징(Hedging)할 수 있는 수단도 될 수 있다.&lt;/p&gt;
&lt;p&gt;다만 전통적인 기업에서 리더는 상사와 동일시되는 경우가 많기 때문에 리더 스스로가 피드백에 대한 수용력과 피드백과 자신의 감정을 분리할 수 있는 능력을 보유하고 있지 않다면 활발한 상호 피드백 환경을 만들어내기 어려울 것이다.&lt;/p&gt;
&lt;p&gt;피드백 수용력은 메타인지 역량과도 연결되는데, 사실 메타인지는 “내가 모른다는 것을 안다”라는 고차원적인 개념이기 때문에 스스로 깨우치기는 쉽지 않다고 생각한다. 대부분은 내가 무엇을 모르는지, 무엇을 아는지 조차 명확하지 않은 상황 속에서 스스로 “난 많은 것을 알아”라는 소피스트적 사고를 하게 되기 마련이다.&lt;/p&gt;
&lt;p&gt;필자는 역설적으로 메타인지 역량을 키우기 위한 가장 좋은 방법 또한 팀원들의 피드백이라고 생각한다. 실제로 리더의 역할로 업무를 수행하며 많은 사람들과 이야기를 나눠보면 내가 바라보는 나의 모습과 타인이 바라보는 나의 모습이 꽤나 다른 경우가 많았다.&lt;/p&gt;
&lt;p&gt;필자의 사례를 보자. 왼쪽은 필자가 스스로를 정의한 내용이고, 오른쪽은 동료들이 필자에 대해서 피드백을 주었던 내용이다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;th&gt;필자의 평가&lt;/th&gt;
&lt;th&gt;타인의 평가&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;감정의 기복이 크지 않다.&lt;/td&gt;
&lt;td&gt;감정을 배제한 의사결정을 할 수 있다.&lt;/td&gt;
&lt;td&gt;너무 말투가 차갑다. 배척보다는 포용을 보여줬으면 좋겠다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주로 의견을 먼저 내는 편이다.&lt;/td&gt;
&lt;td&gt;자신의 생각을 명확하게 표현한다.&lt;/td&gt;
&lt;td&gt;너무 표현이 강해 반대 의견을 내기가 어렵다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사적인 감정을 회사에서 보이지 않는다.&lt;/td&gt;
&lt;td&gt;공과 사가 명확하다.&lt;/td&gt;
&lt;td&gt;인간미가 부족해서 다가가기 어렵다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;사실 이러한 가치판단에는 일종의 자기 고양 편향 또한 포함되기 때문에 스스로에 대해서는 관대하게, 타인에 대해서는 엄격하게 판단하는 성향이나 개인적인 친밀도로 인한 편향까지 포함될 수 있다. 필자 또한 그런 편향에서 자유로울 수 없는 한낱 인간 중 하나이기 때문에 스스로에 대한 평가가 좋은 방향으로 편향되어있던 것이다.&lt;/p&gt;
&lt;p&gt;하지만 결국 중요한 점은 한 가지이다. 리더는 타인의 신뢰를 얻어야 하는 입장에 놓여있다는 것이다. 그러니 내가 나를 어떻게 생각하는지보다는 타인이 나의 특성을 어떻게 바라보고 있는지에 대해서 확실하게 알아두고 대처해야할 필요가 있다.&lt;/p&gt;
&lt;p&gt;필자가 이야기하고 싶은 것은 편향에 빠지지 말자는 것이 아니다. 비록 필자가 심리학에 대한 전문가는 아니지만 이러한 편향을 완벽히 제거하는 것은 불가능에 가깝다고 생각한다.&lt;/p&gt;
&lt;p&gt;중요한 것은 리더 스스로가 “나는 편향과 오류를 가지고 있다”, “내가 그렇게까지 완벽한 인간이 아니다”라는 것을 인지하고 있는 것이라 생각한다.&lt;/p&gt;
&lt;p&gt;리더도 결국 인간인 이상 당연히 역량이 좋은 부분도 있을 것이고 부족한 부분도 있을 것이며, 모든 것이 완벽할 수는 없다. 하지만 자신의 강점과 약점에 대해서 명확하게 인지하지 못 한 채로 자신의 능력을 벗어난 부분까지 마이크로 매니징하려고 하거나 과도한 의사결정권을 가져가려고 한다면 조직 전체적으로는 오히려 좋지 않은 결과가 발생할 수도 있고, 팀원들의 신뢰를 확보하는 데에도 문제가 발생할 수 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3ab89b5cf9446157970eacacf05d02a3/7bf67/control.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAULnWaBCH//EABsQAAMAAgMAAAAAAAAAAAAAAAABAgMSExQh/9oACAEBAAEFAib2E/OxTJyODnZ//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRABAAIDAAAAAAAAAAAAAAAAAAExEBFB/9oACAEBAAY/ArTp3Eqf/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARIVFBwf/aAAgBAQABPyF99ZkMJJXSHT4qarCZAG+zmCf/2gAMAwEAAgADAAAAELsP/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8Qp//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/EIf/xAAcEAEAAwACAwAAAAAAAAAAAAABABEhMWFxsdH/2gAIAQEAAT8QdjuAoDa2HHXWVb4jdnhwPaAQhoBVU5+wgAu3tMQGCsXZ/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;control&quot; title=&quot;&quot; src=&quot;/static/3ab89b5cf9446157970eacacf05d02a3/c08c5/control.jpg&quot; srcset=&quot;/static/3ab89b5cf9446157970eacacf05d02a3/0913d/control.jpg 160w,
/static/3ab89b5cf9446157970eacacf05d02a3/cb69c/control.jpg 320w,
/static/3ab89b5cf9446157970eacacf05d02a3/c08c5/control.jpg 640w,
/static/3ab89b5cf9446157970eacacf05d02a3/7bf67/control.jpg 680w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;아무래도 인간은 자신의 경험에 편향된 사고를 하기 마련이니&lt;br&gt;
  주니어 시절 통제 성향이 강한 조직을 경험했다면 리더십도 알게 모르게 통제 성향으로 편향될 수 있으니 메타인지가 중요하다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;리더는 팀원을 통제하는 존재가 아니라 상호보완적인 존재이다. 애초에 리더라는 역할은 팀원이 존재함으로써 존재할 수 있으니 말이다.&lt;/p&gt;
&lt;p&gt;그래서 팀원들의 피드백을 통해 타인이 나를 어떻게 바라보고 있는지에 대해서 알아내고 그에 알맞는 액션 아이템을 실천함으로써 팀원들에게 비춰지는 나의 모습을 알맞은 방향으로 만들어나가야 하는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 이상을 벗어나 현실을 보다보면 피드백 문화가 제대로 자리잡지 않은 대부분의 조직의 구성원들은 상대방에 대한 자신의 생각을 투명하게 드러내는 것에 대해서 두려워 하는 경우가 많다는 것을 알 수 있다. 특히 개인보다 집단의 가치를 더 중요하게 생각하는 동양 문화에서 리더라는 존재는 명령권자와 동일시 되는 경우가 많기 때문에 이런 고정관념을 없애는 것이 중요하다.&lt;/p&gt;
&lt;p&gt;그래서 리더는 더더욱 자신이 피드백을 원한다는 사실을 팀원들에게 적극적으로 알리고 수용적인 태도를 의도적으로라도 과장해서 보여줘야 할 필요가 있다.&lt;/p&gt;
&lt;p&gt;필자는 2주에 한번씩 프론트엔드 챕터의 모두와 커피챗을 가지면서 그 자리의 마지막에는 항상 피드백을 요청해왔다. 그리고 “저에게 피드백을 주시는 것은 저의 성장을 위한 일이다”, “저도 완벽하지 않으니 피드백을 통해 단점들을 보완하고 싶다”, “ㅇㅇ님이 성장을 원하시는 만큼 저도 성장을 원하는 개발자 중 한 명일 뿐이다”와 같은 명확한 의사 표현을 꾸준히 함으로써 팀원들이 “이 사람 진짜 피드백에 미친 놈인가보다…”라는 생각을 하게 만드려고 노력했다.&lt;/p&gt;
&lt;p&gt;물론 2주에 한번씩 의미있는 피드백을 뽑아내는 것은 쉬운 일이 아니니만큼 대부분의 시간은 “딱히 없어요”의 화려한 향연이었지만, 그래도 계속 이 시간을 유지하다보니 간간히 의미있는 피드백들을 받을 수 있었다. &lt;small&gt;(아침에 일찍 좀 나오라던가…)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;또한 그렇게 받은 피드백 중 공감가는 내용이 있다면 그것을 개선하기 위한 액션 아이템을 수립하고 이후 실행 결과를 꼭 공유했다. 물론 결과적으로 개선이 잘 되지 않았던 것들도 많지만, 내가 상대방의 피드백을 무시하지 않았다는 것을 적극적으로 알리기 위한 일종의 수단이었던 것이다.&lt;/p&gt;
&lt;p&gt;사람 성격마다 조금씩 다르긴 하지만, 대한민국과 같은 권위주의적 문화가 강한 곳에서는 팀원이 리더에게 피드백을 준다는 행위가 꽤나 많은 용기를 필요로 한다. 그러니 당연히 피드백을 받은 사람은 팀원이 용기내어 해준 이야기들에 대해서 감사를 표해야하는 것이고, 그 피드백 한 마디 한 마디를 새겨들었다는 표현 또한 해줘야 하는 것이다.&lt;/p&gt;
&lt;p&gt;물론 그 피드백에 대해서 공감이 되지 않았을 수도 있지만, 그래도 팀원이 용기내서 해준 이야기에 대한 감사 표시는 반드시 한 이후에 그 피드백에 대해서 공감가지 않았던 이유가 무엇인지에 대해서 이야기하도록 하자.&lt;/p&gt;
&lt;p&gt;다만 팀원이 피드백을 줬을 때 감정적으로 반응하거나, 말로는 감사하다고 해놓고 피드백 이후 액션아이템이나 액션 실행에 따른 어려움 공유가 전혀 없는 것은 아닌지 경계해야한다. 이런 상황들이 반복되면 팀원은 “어차피 이 사람은 이야기해도 안 바뀌는구나”와 같은 부정적 사고가 강해지게 되고 결국 입을 다물게 된다.&lt;/p&gt;
&lt;p&gt;이런 감정을 느끼는 동료들이 점점 많아지게 되면 조직은 마치 끓고 있는 압력솥처럼 언제 터져도 이상하지 않은 상태가 되어버릴 수도 있다. 리더에 대한 불만은 이미 가득한데, 이에 대해 투명하게 말하는 것을 두려워하거나, 혹은 말해도 바뀌지 않을거란 무력감에 아무도 이야기를 하지 않는 상황이니 말이다.&lt;/p&gt;
&lt;p&gt;그래서 리더는 항상 동료들에게 적극적인 피드백을 구함으로써 동료들이 자신을 어떻게 바라보고 있는지, 내가 부족한 점은 무엇인지, 잘 하고 있는 부분은 무엇인지와 같은 메타인지 역량 향상에 도움이 되는 정보들을 꾸준히 수집해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지 3년 정도 리더십에 대한 경험과 고민을 이어가며 필자가 느꼈던 감정은 주로 “어…개어렵네…?”였던 것 같다.&lt;/p&gt;
&lt;p&gt;뭐 컴퓨터야 대충 명령내리면 내리는 대로 알잘딱 수행해주는 친절한 친구이지만, 인간은 굉장히 일관되지 않은 행동과 사고를 보이고 감정적이며 가지각색의 편향으로 가득한, 너무나도 다양한 성향을 지닌 대상이었던 것이다.&lt;/p&gt;
&lt;p&gt;물론 공감 지능도 높고 사람 자체를 좋아하는 분들 입장에서는 이렇게 다양한 인간 객체가 모인 곳에서 좋은 역량을 발휘하실 수도 있겠지만, 필자는 MBTI도 대문자 T라 딱히 공감 지능이 높은 편도 아니고 사람에게서 에너지를 얻는 타입도 아니라서 좋은 리더십이란 무엇인가, 사람은 무엇으로 움직이는가와 같은 주제에 대해 굉장히 많은 고민과 리서치가 필요했다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dfc9d10866e65a8c46faf88ef1edd58a/2a614/estj.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 52.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB/klEQVR42pWSS28SYRSG+VH+he50rUZjigsTdWFxocSwtF5iF2bQpqLQFkq5OkMHehlsCpkaKDNMhkI7UKYz1Ja2XIoj7fAB31wQbE1J48ZnfZ735OQ9ht4f9N4luq5rmtb7F5o+PNgzXDGHM1QF9mNKPw4EsVSH3V/tzrmv6UPyGVS3JCBDpQ1amqruCiJFUdKpXG5IoAUw15cXZtOT5IaFzVCVyvCygYzkDh4TTK7W/CnLigqdyMQD42iuUk+VK035tMqlwvaJ54HgMxy/43S5GYaun5204YW8d3iIe51MrfY0RY1jQaPNbcNXotn8VLqA0bRlMWJ2zzlnZz0ulxVBbChKCEdCsz2QpU4HY+iXnyctWOgRSd6a9484Fh/OBG96V6/Nk5YkfzsYued0TU59eo9YZxyOd3b7ApWqyvJA5kQxQBDT7rml2Fp4Z+e1xztqvD9mNt9w4COe+PUodxclx0ymV2/eItYP8XicTdNLsdh3lgUt2dABgC8UEskNJp0uiwLNsti36CoZT1OpEJkYJxIfw9FpXwANR0RRaDROqrVqGwAVwm63O7gZQigIu/3Uryjq9/mCAX9oIbSyvLweW2OS61mG3sxm8vnt/f294+MjAMBlz/rf3hVFkSSpWCxmNi/I9sltbXMcz/OlUqler/U7vvok51/V+39+A6aNKxTcsapfAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;estj&quot; title=&quot;&quot; src=&quot;/static/dfc9d10866e65a8c46faf88ef1edd58a/6af66/estj.png&quot; srcset=&quot;/static/dfc9d10866e65a8c46faf88ef1edd58a/69538/estj.png 160w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/72799/estj.png 320w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/6af66/estj.png 640w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/d9199/estj.png 960w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/21b4d/estj.png 1280w,
/static/dfc9d10866e65a8c46faf88ef1edd58a/2a614/estj.png 5000w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;참고로 필자의 MBTI는 파워 ESTJ인데, 인정하긴 싫지만 은근히 잘 맞는 것 같다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;필자는 사실 관계를 분석하고 논리적 추론으로 연결하는 능력이 좋은 사람이기 때문에 필자에게 가장 잘 맞는 방법은 사람의 심리와 행동원리를 연구한 학문에 대한 지식을 쌓고 주변에 있는 사람들을 관찰하고 분석하여 이 이론과 맞춰보는 것이었다.&lt;/p&gt;
&lt;p&gt;물론 이런 이론이 현실을 100% 설명해줄 수는 없다. 특히 인간 행동원리는 아직도 제대로 밝혀지지 않은 부분이기 때문에 어떤 정답이라고 할 게 없는 것이다. 다만 필자는 주변에서 실제로 발생하는 여러가지 문제들을 관찰하면서 “저 사람은 왜 저렇게 행동할까?”라는 고민과 나름의 분석을 진행할 수 있을 뿐이다.&lt;/p&gt;
&lt;p&gt;그래서 더더욱 어렵다고 느꼈던 것은 아닐까. 물론 세상에 정답이 정해져있는 문제가 얼마나 있겠냐만은 인간처럼 논리적이지 않은 대상을 분석하고 나름의 정의를 내리기란 정말 어려운 것 같다.&lt;/p&gt;
&lt;p&gt;물론 필자는 아직 3년 밖에 되지 않은 병아리 리더이니 이런 고민은 이제 시작 단계이고, 앞으로도 이런 고민을 할 수 있는 날은 많이 남아있으니 서두르지는 않으려고 한다.&lt;/p&gt;
&lt;p&gt;이상으로 인간은 무엇을 위해 일하는가? – 동기 부여의 심리학 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Becoming Someone Who Survives the Market]]></title><description><![CDATA[In this post, I want to calmly lay out some of the thoughts I’ve had as a player participating in the market economy. I’ve written a lot about personal growth, motivation, and philosophy, but this time I want to talk about something more grounded in reality. Rather than telling you “just keep working hard and things will work out,” I want to offer an agenda that might actually help in practical terms.]]></description><link>https://evan-moon.github.io/2023/05/07/improve-my-career/en/</link><guid isPermaLink="false">20230507-improve-my-career-en</guid><pubDate>Sun, 07 May 2023 01:54:45 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I want to calmly lay out some of the thoughts I’ve had as a player participating in the market economy.&lt;/p&gt;
&lt;p&gt;I’ve written a lot about personal growth, motivation, and philosophy, but this time I want to talk about something more grounded in reality. Rather than telling you “just keep working hard and things will work out,” I want to offer an agenda that might actually help in practical terms.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;As a developer, you surprisingly often encounter opportunities to help — or situations where you have to help — developers with less experience than you.&lt;/p&gt;
&lt;p&gt;Most of the junior developers I’ve met or exchanged messages with were hungry for growth, and I usually shared topics that would help them reflect on growth — things like motivation, consistent effort, and metacognition.&lt;/p&gt;
&lt;p&gt;And when someone asked about compensation, I’d often say this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you grow and become a competent developer, the rewards will naturally follow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It’s true to some extent. But rather than rewards materializing on their own just because you’re good at your job, it’s more like having the capability to seize good opportunities when they come. Being good at your job and being good at making money are slightly different things.&lt;/p&gt;
&lt;p&gt;There are senior developers out there who’ve built solid skills through consistent effort yet receive less compensation than entry-level developers because nobody knows about them. Conversely, there are developers whose programming skills are unremarkable but who command high compensation through personal branding.&lt;/p&gt;
&lt;p&gt;Of course, it’s true that better programming skills generally correlate with better compensation. But no matter how skilled you are, if you just sit there quietly, chances are nobody will notice. And honestly, unless you’re a truly top 1% standout, most developers at a similar level of experience are roughly comparable in programming skills.&lt;/p&gt;
&lt;p&gt;The beautiful story of “hard work proportionally rewarded” can be motivating, but if you look closely at reality, you’ll find that things don’t work that way more often than not.&lt;/p&gt;
&lt;p&gt;That’s why in this post, rather than talking about growth, I want to talk about something more practical: the market.&lt;/p&gt;
&lt;h2 id=&quot;develop-a-basic-understanding-of-the-market-game&quot; style=&quot;position:relative;&quot;&gt;Develop a basic understanding of the market game&lt;a href=&quot;#develop-a-basic-understanding-of-the-market-game&quot; aria-label=&quot;develop a basic understanding of the market game permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;South Korea, where we live, is a capitalist country. Simply put, capitalism is an economic system where market participants exchange their respective values within the market.&lt;/p&gt;
&lt;p&gt;In other words, the labor market where working professionals like us seek jobs fundamentally operates on the principle of exchanging the worker’s labor — a commodity — for the company’s financial compensation.&lt;/p&gt;
&lt;p&gt;It’s a simple and clear concept, yet we often forget it in our daily lives. The very first thing we need to do to survive in the ruthless game of the market is to change how we view the labor market itself.&lt;/p&gt;
&lt;p&gt;The market is a game where participants make decisions to maximize their own gains. There are many &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_theory&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;game theories&lt;/a&gt; that model and study the decisions made in markets, but I think the &lt;a href=&quot;https://en.wikipedia.org/wiki/Prisoner%27s_dilemma&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Prisoner’s Dilemma&lt;/a&gt; most closely resembles reality.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Other confesses&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Other stays silent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;I confess&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;Both get 3 years&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;I go free, other gets 10 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;I stay silent&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;I get 10 years, other goes free&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;Both get 1 year&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The defining feature of the Prisoner’s Dilemma is that even when each individual makes the best choice for themselves, the collective outcome may not be optimal. If both stay silent, both get just 1 year. But if I stay silent while the other confesses, I alone face 10 years — that risk exists.&lt;/p&gt;
&lt;p&gt;So both sides end up choosing to confess — the option that benefits them regardless of what the other does — and they serve 3 years together.&lt;/p&gt;
&lt;p&gt;This is similar to how eliminating nuclear weapons would clearly benefit the entire planet, yet no country can easily make that choice. Most interactions in the market follow the same pattern — participants tend to act in their own interest rather than for the collective good.&lt;/p&gt;
&lt;p&gt;Now let’s set aside the heavy theory and talk about something every working professional cares about, salary, to start shifting our perspective on the market.&lt;/p&gt;
&lt;h3 id=&quot;there-are-no-absolute-winners-and-losers-in-the-market&quot; style=&quot;position:relative;&quot;&gt;There are no absolute winners and losers in the market&lt;a href=&quot;#there-are-no-absolute-winners-and-losers-in-the-market&quot; aria-label=&quot;there are no absolute winners and losers in the market permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most working professionals have thought at least once about wanting a higher salary. A higher salary doesn’t automatically make you wealthy, but it does noticeably improve your quality of life.&lt;/p&gt;
&lt;p&gt;Many people vaguely think of salary as something that increases with tenure or through job changes, but in reality, salaries are determined by the market’s cold evaluation.&lt;/p&gt;
&lt;p&gt;To increase your salary, you first need to clearly recognize and accept that it doesn’t go up simply because you’ve worked longer — it’s the price the market assigns to your skills and labor. We’re engaged in a transaction where we sell our skills and labor, and in return, the buyer — the company — provides us with the value we call salary.&lt;/p&gt;
&lt;p&gt;Every interaction in a capitalist market economy starts from the transaction of exchanging value for value. The higher the perceived value of the skills and labor you provide as a seller, the more the buyer — the company — will pay.&lt;/p&gt;
&lt;p&gt;I think demanding a higher salary without any improvement in your abilities is no different from trying to charge consumers more for a product with zero improvements, just to pad your margins. &lt;small&gt;(Think about how consumers react when chicken prices go up with no justification.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The most fundamental principle for increasing your salary in the market is: &lt;strong&gt;raise the value of what you’re selling — your skills and labor — before making a deal.&lt;/strong&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7e75357bf1d72f21d3f9cf4fcf4753a2/38a65/market.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 61.24999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB5UlEQVR42q1S2Y7TQBDM//8MLzwgVmh5iAQrJASLNomP+Ai+xzPxFcfHjIvpySbsSiBeGKnkcnuqut3dqwULqnMHfqoh+lrzFmpZcD2L5lJKg5eH4vXQGc1F1xndapQzgirBockQ1oQUOWdgRQHGGOI4huM48DwPaZqCc469u4fjufjZ5kYTaI1/TDDMI1ZyUXj0t3hz9xbv1h/wefMVrc7Wn3qM44hpmlCWJQqd4PpeVRWY4Ai0yf2XNe4+fYSVehjVfKnQ4xF2OrBL9oY/WVvYlm2M8jw3FRKIZxqsYChKBl/EsDIfThHCE9HvCvNOID8JZCeOoheYdBIl1a13SqlXvSRM8/Ss48g6rjnHrCRW+M/nj4ZUzRUvY3/79spQygVF0iKPLiA+z+pZDDOIYRh0bEbf9zcjqVtSJB2YRhETWkitW42DxMEV8C2GwC41P6LIOZhuOk02CAKDKIrMYGhQtm1h82QhDVvsHiO4m8x4DD1NeZiRBDU23wJsv4fIDh3iKEPJSwghzP6RYRiGxpSSNE2jjY/6bov79w94WP9A7FcYz9pwGiVCRxgENtcfGlg7F77vGUNa5izLLiujn2TIOe0lNxr6IwLxgQypJc1xQM3PBsSVWv45Teol3a14r3X9TfcLA1WSOhNpt3QAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;market&quot; title=&quot;&quot; src=&quot;/static/7e75357bf1d72f21d3f9cf4fcf4753a2/6af66/market.png&quot; srcset=&quot;/static/7e75357bf1d72f21d3f9cf4fcf4753a2/69538/market.png 160w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/72799/market.png 320w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/6af66/market.png 640w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/d9199/market.png 960w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/38a65/market.png 1075w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;A labor market transaction isn&apos;t fundamentally different from buying and selling a coffee at a café.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Of course, in the labor market, there’s often an information asymmetry between us (the sellers) and the companies (the buyers). If you go in unprepared, you’ll likely find yourself in a disadvantaged position, providing quality labor below market rate.&lt;/p&gt;
&lt;p&gt;But since this is fundamentally still a market transaction, these positions can always be reversed depending on factors like information, the relative value of your product, supply and demand, negotiation skills, and market conditions.&lt;/p&gt;
&lt;p&gt;Contrary to the belief that companies are always in a position of power and workers are always at a disadvantage, there are workers who hold the upper hand in negotiations thanks to their quality labor and information advantage. It just appears as though workers are always disadvantaged because such workers make up a very small proportion.&lt;/p&gt;
&lt;p&gt;When someone commands a high salary, it means the value of their labor is high, demand is strong, and supply falls short. Workers at this level are desired by companies of all sizes, and companies end up competing with each other for them.&lt;/p&gt;
&lt;p&gt;Workers who can provide high-quality labor often hold a stronger position than companies in the market. Instead of submitting resumes and going through interviews, they receive outreach from companies and gather information through coffee chats and recruiting dinners before choosing where to go. There are no absolute winners and losers in the labor market.&lt;/p&gt;
&lt;p&gt;These are all obvious facts when you think of them as regular market transactions, but the unique characteristics of the labor market — combined with the reality that most workers negotiate from a weaker position — cause us to view this market through a slightly different lens.&lt;/p&gt;
&lt;p&gt;The first perspective shift for surviving the market is to abandon the self-deprecating mindset and recognize that you can become a player capable of transacting on equal terms with companies — putting yourself in a state where you can engage in productive strategizing.&lt;/p&gt;
&lt;h3 id=&quot;all-market-participants-are-selfish&quot; style=&quot;position:relative;&quot;&gt;All market participants are selfish&lt;a href=&quot;#all-market-participants-are-selfish&quot; aria-label=&quot;all market participants are selfish permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Occasionally, the news makes it seem like companies and workers are enemies. Unions going on strike because companies won’t pay fair wages, or workers being laid off and threatened in their livelihoods due to poor corporate governance — these aren’t rare occurrences.&lt;/p&gt;
&lt;p&gt;Since we’re usually on the worker’s side, it’s natural to empathize more with workers than with companies. But viewed coldly, these situations are simply a series of cooperation and betrayal among game participants fighting for their own interests.&lt;/p&gt;
&lt;p&gt;The very concept of a labor union is a group that bands together to negotiate on equal footing with companies and secure workers’ interests. Naturally, most decisions are made in favor of workers, not companies. Conversely, companies will make decisions that favor the company over workers.&lt;/p&gt;
&lt;p&gt;As I said at the beginning, the market is fundamentally a game where all participants act selfishly to maximize their gains within the bounds of the law. To survive in the market, you need logical judgment and a neutral perspective that can coldly analyze situations and make optimal decisions — rather than emotional judgments about good versus evil.&lt;/p&gt;
&lt;p&gt;As sellers, we want to sell our abilities at a high price; as buyers, companies want to buy at the lowest price possible. This, too, is perfectly natural when you think of it as a regular market transaction. There’s no reason to call a worker demanding high pay greedy, and no reason to call a company offering low pay evil.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/28f028c4465567d2f13fa16ff2cc7326/8e1fc/carrot.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 103.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAVABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAe1Nc5dlQ70LkDf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAQIREBITIf/aAAgBAQABBQLwtCskmzmiMYrFWapH/8QAFxEBAAMAAAAAAAAAAAAAAAAAAQAQEf/aAAgBAwEBPwEyN//EABYRAAMAAAAAAAAAAAAAAAAAAAERIP/aAAgBAgEBPwEuP//EABkQAAIDAQAAAAAAAAAAAAAAAAABECExEf/aAAgBAQAGPwLHGo4yynFmH//EABwQAAICAwEBAAAAAAAAAAAAAAABETEhcYEQkf/aAAgBAQABPyFxuwVSxsx5doUwfCGzXRNZ3yFafBUkP//aAAwDAQACAAMAAAAQ7DA//8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERMeH/2gAIAQMBAT8QRtZF4WFZ/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERMeH/2gAIAQIBAT8QZMQrOmkR/8QAHBABAAMBAAMBAAAAAAAAAAAAAQARMSEQQVHR/9oACAEBAAE/EACiLffu77lK3HHBE3dX6RHdFsVw7y5Usm9p+RCUFvHhIg+wRRTeE//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;carrot&quot; title=&quot;&quot; src=&quot;/static/28f028c4465567d2f13fa16ff2cc7326/c08c5/carrot.jpg&quot; srcset=&quot;/static/28f028c4465567d2f13fa16ff2cc7326/0913d/carrot.jpg 160w,
/static/28f028c4465567d2f13fa16ff2cc7326/cb69c/carrot.jpg 320w,
/static/28f028c4465567d2f13fa16ff2cc7326/c08c5/carrot.jpg 640w,
/static/28f028c4465567d2f13fa16ff2cc7326/8e1fc/carrot.jpg 900w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;If either side offers a ridiculous price, the transaction simply doesn&apos;t happen&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;There are certainly bad actors — companies that exploit information asymmetry to lowball quality talent, or pile on work beyond what was originally agreed. These unfair practices exist.&lt;/p&gt;
&lt;p&gt;But from the other side, there are workers who engage in quiet quitting despite receiving high salaries, demand excessive perks not in the original agreement, or show a completely different attitude after joining compared to the passion they displayed during interviews. Unfair behavior goes both ways.&lt;/p&gt;
&lt;p&gt;Because evaluations of the other party are relative, there are no absolute heroes or villains.&lt;/p&gt;
&lt;p&gt;At the end of the day, both companies and workers are simply equal game participants acting selfishly in their own interests. If a worker’s default position in the market is that of the underdog, we should acknowledge it and come up with strategies to flip that position.&lt;/p&gt;
&lt;p&gt;For a successful transaction in the market, you can’t just think about your own position — you need to understand the other party’s position and psychology and propose appropriate terms. Of course, you don’t have to keep cooperating after getting burned once — think of it as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tit_for_tat&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;tit-for-tat&lt;/a&gt; strategy.&lt;/p&gt;
&lt;p&gt;Tit-for-tat starts with cooperation but reciprocates: if the other side betrays you, you respond in kind; if they cooperate, you cooperate back. Deals between workers and companies mainly happen during compensation negotiations. You might cooperate during the initial negotiation, but if subsequent negotiations don’t go your way, there’s no reason to stay — consider looking at opportunities elsewhere.&lt;/p&gt;
&lt;p&gt;When negotiations fall through, some people take an emotional approach: “I devoted so much to this company, how could they do this to me?” But getting emotional with a buyer who won’t pay your asking price won’t make them hand over what you want for free.&lt;/p&gt;
&lt;p&gt;Imagine telling a café owner who wants to charge &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;80&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mtext&gt;—&lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;?&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;!&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mtext&gt;—&lt;/mtext&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mtext&gt;—&lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mtext&gt;—&lt;/mtext&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;80 for an americano, &quot;That&apos;s too expensive, I&apos;m not buying.&quot; If the owner gets angry — &quot;How is this expensive?!&quot; — or tries to guilt you — &quot;My family is going through hard times...&quot; — you&apos;re still not buying that coffee. They&apos;d have a far better chance presenting a rational justification for the &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9463em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;anam&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ooe&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mn&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&quot;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;ry&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;—&quot;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Ho&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;?!&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;—&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;gu&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;yo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;—&quot;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ami&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ro&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;ug&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;im&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;...&quot;—&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;yo&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;ll&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;ff&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ee&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;tt&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;erc&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;han&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ce&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;rese&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;na&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05724em;&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;80 price tag.&lt;/p&gt;
&lt;p&gt;To create an effective strategy for getting the price we want for our labor, we need to understand the market game and the company we’re dealing with, and find ways for both sides to win.&lt;/p&gt;
&lt;p&gt;The second perspective shift for surviving the market is to accept that both you and the company are simply players making decisions to maximize their own interests, and to develop an objective view that sees situations as they are rather than reacting emotionally — enabling you to coolly assess what the other party wants and how to approach them to spark buying interest.&lt;/p&gt;
&lt;h3 id=&quot;customer-centric&quot; style=&quot;position:relative;&quot;&gt;Customer Centric&lt;a href=&quot;#customer-centric&quot; aria-label=&quot;customer centric permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I won’t be discussing specific strategies for raising your salary by increasing the value of your abilities in this post. Everyone’s capabilities and circumstances are so different that while there may be some useful techniques, there’s no silver bullet strategy that guarantees “do this and your salary goes up.”&lt;/p&gt;
&lt;p&gt;All I can do is offer a small nudge to help you start thinking about these strategies by shifting how you view the labor market and its basic concepts.&lt;/p&gt;
&lt;p&gt;As I mentioned, we’re sellers — or producers — in the labor market, needing to sell our abilities to companies. In other words, we should think of our abilities as a product and consider what information buyers need to make a purchase decision.&lt;/p&gt;
&lt;p&gt;Some might object to treating people as products and putting price tags on them. But we’re already providing labor to companies and receiving a salary in return, aren’t we? That’s the price tag on us. More precisely, it’s the &lt;strong&gt;price assigned to the abilities a person possesses&lt;/strong&gt;, not the person themselves. &lt;small&gt;(That’s why we use the term “talent acquisition” — hiring the talent within a person, not purchasing the person.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Of course, factors like minimum wage laws exist to guarantee basic survival, but fundamentally, it’s just a price formed by supply and demand for a product.&lt;/p&gt;
&lt;p&gt;The act of companies purchasing our abilities in the labor market isn’t much different from us buying an expensive product on an e-commerce platform. For example, imagine you need to buy a robot vacuum.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3e1d7d064e044b9f2a9991365283f479/d9ed5/coupang.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAACf0lEQVR42k1Uy27TUBDttyAWqP8CG1iA1AV/hERFV/0AQEJ0W1SQQFSqRFq1Tdu8nDqxndiJ38/r69dh7nXidKQr38e8zpkZ70UJQ1mWEFIr/2B9/gDfWCCIMlSqijzn4FWNJo5RajryokAldF0X5dJE3tCe3rey57oO0jSVh97FOd69eonXb95iZDjyLstyMJZ3BpqmIYqi7hwnFLiqdg5TMuAUVciPs5949vwF9vf3MRzcyztFecRspnUGx8fH6Pf7cs95gf7dkAIkO4dxnBCsNoOcc3w/OcHZz18YDEdwPA/Xt7dQCboQQY1u6PB9f5M9w83dA/wgfOowQpK0EaIwgrm0YJomgiDAPSlrcw0uOWZk7Ns2VqYFy1rJ97Xt0DeETfeMsR3kYgM5MjXoDxcIPRM1kR0uR9Af7xGRckM8rZUr6PoUjPRLzrBWH7ByLBSUedM0rUNB8NZ7kawQuQtUdUtyGDuw3XUX0E9ceL4HYVs3BezlGI69xlPZE3C3HIooNaUmvu2q5ZJvFLRyHDQbw5raiBMVdWu4c5hlGTnZ9BE9FLxEGCa0WqKHgwE+HR2hIr2GeONFiZKC1pRIQlxnPKfipFRxvi1KTMUIuyqyjGM+MzCZTOWdYRj4eHgoW0TCDmK5L6mZDWpsmyB/+foN0+lj6zCkyjpO28RiOv78vcTv8x7cKKYJqDCeKOj1LlvSaV31qDBzXepfX9/g4OA9Tk/POspkldM0a7s+ZViuHGrUWPJaURZMdAHBEbQw+orgCaESwmgsF4uFRNZVWUAuiha/tzBgKWNSZHLcluoAynwCm/gqKIA1HkGdzRFQ4JLO7lyFR1MSUULV5n/wH/vB1RAe8gUlAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;coupang&quot; title=&quot;&quot; src=&quot;/static/3e1d7d064e044b9f2a9991365283f479/6af66/coupang.png&quot; srcset=&quot;/static/3e1d7d064e044b9f2a9991365283f479/69538/coupang.png 160w,
/static/3e1d7d064e044b9f2a9991365283f479/72799/coupang.png 320w,
/static/3e1d7d064e044b9f2a9991365283f479/6af66/coupang.png 640w,
/static/3e1d7d064e044b9f2a9991365283f479/d9199/coupang.png 960w,
/static/3e1d7d064e044b9f2a9991365283f479/21b4d/coupang.png 1280w,
/static/3e1d7d064e044b9f2a9991365283f479/d9ed5/coupang.png 2880w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Robot vacuums are surprisingly expensive...&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;When buying products online, you can’t try them out beforehand. And while you might impulse-buy something cheap, when it comes to an expensive product like a robot vacuum, you’ll be more careful to avoid wasting your hard-earned money.&lt;/p&gt;
&lt;p&gt;So we typically read the product detail page carefully, check reviews and ratings from other buyers, maybe even look at video reviews on YouTube, and only when we think “this seems like a reasonable purchase” do we pull the trigger. &lt;small&gt;&lt;del&gt;(Some people just buy on impulse, sure…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The customers buying our abilities are the same way. Buyers in the labor market can’t directly experience our abilities before purchasing. They make their buying decisions based on a simple product brochure (resume), roughly 2 hours of door-to-door sales (interviews), and maybe reviews from previous customers (reference checks).&lt;/p&gt;
&lt;p&gt;At this stage, it’s not the product’s actual specs but the information presenting the product and others’ reviews that have the biggest influence on the purchase decision.&lt;/p&gt;
&lt;p&gt;On top of that, human ability is an extremely expensive product — costing tens of thousands to hundreds of thousands of dollars per year — and once purchased, it’s hard to return after the probation period. The risk of a failed purchase decision is enormous, which is why it demands such careful deliberation. &lt;small&gt;(This is also why companies should avoid low-density hiring out of urgency without a proper exit strategy.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;As producers, to increase the probability of selling our abilities, we need to gather information about our customers — what culture and characteristics the company has, what kind of talent they’re currently looking for, whether our abilities can solve their business or technical problems — and develop a strategy for how to sell our abilities to that specific company.&lt;/p&gt;
&lt;p&gt;At the end of the day, the labor market is still a market. To sell our abilities to companies and receive better compensation, we need to think not only about “How can I become a better developer? (How can I make a better product?)” but also about consumer-centric questions like “What kind of talent do our customers want to hire? (What kind of product do they want to buy?)”&lt;/p&gt;
&lt;p&gt;The third perspective shift for surviving the market is to stop viewing employment as an administrative process of taking a company’s test, passing, and becoming a member of that organization — and instead see it as an economic activity where you jump into the market, promote your abilities, and match customer needs to create buying interest.&lt;/p&gt;
&lt;h2 id=&quot;adopt-a-professional-mindset&quot; style=&quot;position:relative;&quot;&gt;Adopt a professional mindset&lt;a href=&quot;#adopt-a-professional-mindset&quot; aria-label=&quot;adopt a professional mindset permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you’ve recognized and accepted that you’re just another participant in a market driven by capital and selfish choices, it’s time to think about how to maximize your own gains.&lt;/p&gt;
&lt;p&gt;Earlier, I discussed three perspective shifts:&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Recognizing that workers and companies can be players transacting on equal terms&lt;/li&gt;
&lt;li&gt;Recognizing that both workers and companies are selfish actors moving to maximize their own interests&lt;/li&gt;
&lt;li&gt;Recognizing that employment is an economic activity where you sell your abilities to someone&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Once you define the relationship as one between equals, the company is no longer an “employer” but a “customer” who buys your abilities. The company purchased your labor and skills, not you as a human being — so they can’t be called your owner.&lt;/p&gt;
&lt;p&gt;Of course, some people feel like serfs because of the labor market’s nature — the product (labor) can’t be separated from the seller (worker), and while providing labor, your freedom is constrained by the buyer (company). But think about it.&lt;/p&gt;
&lt;p&gt;What we do when we get a job isn’t really different from a famous athlete or a star instructor signing a contract with a team or academy for high pay. Either way, you’re signing a contract to provide your abilities to someone in exchange for money, and your freedom is constrained while providing those abilities.&lt;/p&gt;
&lt;p&gt;Athletes and instructors often work even harder than the average office worker, who can fulfill their contractual obligations and go home after 8-10 hours.&lt;/p&gt;
&lt;p&gt;Yet we call those people professionals, not serfs. It’s strange logic to say that if your job title is “office worker” you’re a serf, but if you’re a sports star you’re a professional — when both are providing abilities to others for money.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/b918a/3hours.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC6ElEQVR42iWSy2tcZRjGD+jCleBSxIW2ohmmycxkMsxkMuNccs6Zc7/NOTNzppncTNLRNp1QrRSzCLaNUFovGEUUwViIdCFaisFesF5Su6h0kVUFQfwDCi50KT+/TBcPfIvv/X3P+3yPFHtZBu1D9KME03KNUrXOVKXKeC7HSCJJInmESpDF6BRoz08xt6agt6pU6hqKbtIwbTozs6wOTtHu9pDils76SpqNY0kCV0UWl6Y1nUKpxNhYmmQ6Q9wtceXSLJfP9tg4E+Evmqi6ixNEOM0WC0vHeP30GRZWXkXS7ADVjpDNiIbtopqGgBpMlsqkUhkBTNPvaNz6ZMDOOz3OnpBZOO5TUyxsL8AVQC9s40cd2kdnkSzP40Cm66LbjgAKhw2dfLFEcjRNenyc9eVFrr73Fl+d73HuNZ1mzxB3LEzbE9AQP+wQtru04hkkw3E5kCZgDcum3tCI/IDAsKhOTnE4keBkM+S78+t8/kZAs1EW7mtoIjvddLHc5tBlIBxGra4AWg669QimGsKd2sAW5w9Pr7IUeOhi4ORKnwtLITvnltn+7CM6YrV8vkRDszCsA5dNvEBAhVNJM2weyRJBm8iqhq5b3Hj3bXbf3+Te3m/sfrvLxRMxP2xf4L9//uXhw7/5dPuLIUzTbSzbxxEPe36EJKv6EKKK3BQhWVFEbWTWYp9rWxe5u3efO7d/5acvP2Z/7xcePPiL/bv73Ln0DV2/K+qjiFlTgK2hpEpNoTatiRXKpFM5JidLFMtVTs2FbHgxX+9c5db122xvbfHjzZ/5/Y8/ufLBZTaf8HDTMoVqhZfLdSpVmVpdRnLCeaKjfUZeGmM8k0MVueSyWYL6FMpEAUcE3+nEhAd9m3tFdHKG2ZTO5lPiM5J1UoUchXxxaCRfLCMFrXmcaI4joyn6x1fZ/f4ma4MBtdERDj33Is8/c5jYDVleFLBpm4nHnqb4+LO8+aSO+UKZkcwYmUyWVHYCZyLD/+qCwmwngweRAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3hours&quot; title=&quot;&quot; src=&quot;/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/6af66/3hours.png&quot; srcset=&quot;/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/69538/3hours.png 160w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/72799/3hours.png 320w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/6af66/3hours.png 640w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/d9199/3hours.png 960w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/21b4d/3hours.png 1280w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/b918a/3hours.png 2780w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    Honestly, the working conditions of a star instructor earning $10M a year are far more intense than most office workers&apos;.&lt;br&gt;But nobody would call them a corporate serf.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;As long as we live as working professionals, the fact that we provide labor to others in exchange for compensation doesn’t change. The difference is in perspective: if you see yourself as a serf, you’re a serf. If you see yourself as a professional who must hone their craft to satisfy customers, you’re a professional.&lt;/p&gt;
&lt;p&gt;I want to say that &lt;strong&gt;every working professional is a professional who receives compensation in exchange for their abilities&lt;/strong&gt; — there isn’t a single amateur among us.&lt;/p&gt;
&lt;h3 id=&quot;our-customers-are-obsessed-with-money&quot; style=&quot;position:relative;&quot;&gt;Our customers are obsessed with money&lt;a href=&quot;#our-customers-are-obsessed-with-money&quot; aria-label=&quot;our customers are obsessed with money permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I said earlier that we’re all professionals and sellers who provide our skills and abilities to others for money, and that companies are our customers and buyers.&lt;/p&gt;
&lt;p&gt;So the first thing we need to do is clearly understand what our customers — these entities called companies — exist for and what their goals are.&lt;/p&gt;
&lt;p&gt;We go through all that trouble to identify user personas, behavioral patterns, and needs even when building a tiny MVP. Wouldn’t it be stranger if we knew nothing about the important customers who actually buy our abilities?&lt;/p&gt;
&lt;p&gt;I can sum up what a company is in a single sentence. A company is…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💰 &lt;strong&gt;A group that exists to make money.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
&lt;/center&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b59c02f9579a4c68f819893ea391f1db/131f1/of_course.webp&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmgAAABXRUJQVlA4IFwAAABwAwCdASoUAAsAPtFWo0uoJKMhsAgBABoJZwDLLA6txFN1AvAA/tTKt0VjlQLiE/Sva1I/x9Q/Vtoofwt8vNkc8YEfqkw38U9SAkQK5LKmA6lLA1XLFdeZCK0AAA==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;of course&quot; title=&quot;&quot; src=&quot;/static/b59c02f9579a4c68f819893ea391f1db/0ba47/of_course.webp&quot; srcset=&quot;/static/b59c02f9579a4c68f819893ea391f1db/60a22/of_course.webp 160w,
/static/b59c02f9579a4c68f819893ea391f1db/4c812/of_course.webp 320w,
/static/b59c02f9579a4c68f819893ea391f1db/0ba47/of_course.webp 640w,
/static/b59c02f9579a4c68f819893ea391f1db/131f1/of_course.webp 900w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Obviously, everyone knows that&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;I built that up quite dramatically, but the fact that companies exist to make money is something even a kid knows.&lt;/p&gt;
&lt;p&gt;The investors who put money into your company are people who invested massive sums expecting the company to make more money in the future and become more valuable. They jumped into the game bearing the risk that their investment could turn to dust — all for their own gains.&lt;/p&gt;
&lt;p&gt;Some CEOs aim to realize their vision or dreams through their companies rather than just making money, but everyone would agree that as long as you’re running a for-profit organization, you can’t achieve those dreams without making money.&lt;/p&gt;
&lt;p&gt;The reason I’m emphasizing something so obvious is that we often forget the fact that a company is &lt;strong&gt;a for-profit organization whose top priority is making money.&lt;/strong&gt; Understanding and accepting this is the first step toward understanding our customers.&lt;/p&gt;
&lt;p&gt;Because companies must make money, they will never hire us if they don’t think we’ll be profitable.&lt;/p&gt;
&lt;p&gt;When a company signs a one-year salary contract with us, it’s essentially making a futures investment of tens to hundreds of thousands of dollars. &lt;small&gt;(If you’re not familiar with futures contracts, check out my post on &lt;a href=&quot;/2021/12/04/what-is-stock-options/#%EB%B2%88%EC%99%B8-%EC%98%B5%EC%85%98option%EA%B3%BC-%EC%84%A0%EB%AC%BCfuture%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C&quot;&gt;Everything Developers Should Know About Stock Options&lt;/a&gt;.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;So if you’ve signed an employment contract worth, say, &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;60&lt;/mn&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;60K a year, there&apos;s an implicit expectation that the financial and non-financial value you&apos;ll generate over that year exceeds &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9463em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ye&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;anim&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;pl&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;tt&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;inan&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ia&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9463em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;inan&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ia&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eyo&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;ll&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ye&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cee&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;60K. Never forget that a company’s top priority is making money — not your happiness or work-life balance.&lt;/p&gt;
&lt;p&gt;Put simply, companies approach hiring as an investment, which means they look at &lt;strong&gt;ROI (Return On Investment).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The expected non-financial value might include things like building organizational culture or improving team capability and morale — but these, too, ultimately serve the purpose of maintaining high productivity to generate profit. If a company goes bankrupt because it prioritized employee happiness over revenue, the employees lose their jobs too. When the company can’t make money, everyone loses.&lt;/p&gt;
&lt;p&gt;This is the essence of our customers — the entities that buy our abilities and labor — and a critical factor we must understand as professionals seeking to satisfy them.&lt;/p&gt;
&lt;p&gt;So ultimately, to sell our labor at a high price, we need to demonstrate that “I can generate value equal to or greater than my salary for the company.”&lt;/p&gt;
&lt;h3 id=&quot;think-about-your-sales-strategy&quot; style=&quot;position:relative;&quot;&gt;Think about your sales strategy&lt;a href=&quot;#think-about-your-sales-strategy&quot; aria-label=&quot;think about your sales strategy permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So how do we demonstrate to our customers that we can generate value exceeding our salary?&lt;/p&gt;
&lt;p&gt;It’s a difficult problem. Human abilities can’t be neatly quantified into numbers like a strategy game character. That’s why purchase decisions in the labor market are driven more by qualitative signals — coffee chats, interviews, reference checks, reputation — than by quantitative data.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1625608a5b50569e606c847c8b9d5e3e/748f4/jojo.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 86.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEBElEQVR42iWUyXLbRhCG+QQ5WC7TVlzWSnMRTYo7CUAECGIhCYIrwAWkSEqyZafiisuxdXDlkpQrl+Scyjl5gDxGXutLSzlMobsx09P/3/1PrOH5NLo+KdUgoVuo/ghrGnKkGahOl2RV5bBYJ1XT2D+vcK6bKBI/qTcptbvUHY+q3SOtmpw2LoglqhqH+SovcmWSNZWsanFSrLF/VmA/leegrPFSM0lrbRJqi6xhc252yMrKScJSZ0C5OxS79+DHDl+kOXqS4GQ/RTGVJp+uiZ3gOJ7i6eOjh43KfE49CGgs5vSWK5ztjmYUoUVLrMtLotUaYzLFWW+JJRN5sgdpjr89xameMTNyHMTjpF+ccfAsQUHgqMsFlekEYxbyaT3D9SW2jmiu15jrFcHiipbQ1I7WAvk4R/llhmrmiD/fj/j3t3d0C6do5ykqGVnCrzKP6F294fb2B36/jnir9ck3dPTZAmu5YbxZYy+W/1dYPMtjN5Ise6f883nG3x/nrKw0Ey9FW5WEvSGKHOy9+Y7Vl698/vEzP4V3mAWLxmQsSXYE2znucvlgx7pOjombZjMx+ON7j3EtxdI+5XaR4aKS5NwSeIsFpYGHfjfj3a9rvn7sY+gKmkBuby7pXu1whMfe7oZYuZxju/nCp7u/uLu55HZYJXvyHLeZwbMy0sE+yjKiEUypbXVa2wI3NyUGqxGGNMfZ7fA3N5jzpSR8Tex9kOOXD6+52v5MoRCw7qlUsjkePU7K9zmKLxwKHOVyiRGt0KXLzWiDuxOIVxHWZsv65pqOdL3/kPCtz1Ukg5or8eiwSKVRR23qPDnOcpw8IS+zVfQnlP0plfGM+nQm3M2ojkKUcCWXbIW7a/T5CnWyJKZMr7HnH3jVHrBXqslSeFxWeSZK2Ks0+eZVlb1zhXj5gqfix2XQ47InLuo5UNukbJ+k5ZGQeT1uOsRaYSDEW5QMi6rpUpZvThRRMhzyoo681qIo6ijfq0NpUrM6VNsdiiLBkuxvCMdneptkXSclioq9tIeUuh79MMSfLNBsD0Pk1B0FtHsj3MEE2xuJH9IR2+mPH/71hgGmN6QzCWl2fEwZr2S1SexEys1bPt5oRlc40uw+mtPHkoOOHAqkAfcX+NM5neEUW+KuxIezFV6woCucuhJ3B2N5QAxiOW9CVSow75ds1uT1cGTDvW9LM3w55A4Cmm7/IXFHkulSkSJIHKlU7wqacShyHJO/sIjp69f0FysGowmd8RxLYPWk0o5AbMsF94n9YIkr/iCMpJqQujSgpLvCryVJbHJKi1cixYysmHv9jtHl7gGOO42wxwscab85mGH4AdZoji3cmoMQW2zTD9HFNuR/WTpcEYrKLWlSyyXXcvgPDLhoz6iBTpsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;jojo&quot; title=&quot;&quot; src=&quot;/static/1625608a5b50569e606c847c8b9d5e3e/6af66/jojo.png&quot; srcset=&quot;/static/1625608a5b50569e606c847c8b9d5e3e/69538/jojo.png 160w,
/static/1625608a5b50569e606c847c8b9d5e3e/72799/jojo.png 320w,
/static/1625608a5b50569e606c847c8b9d5e3e/6af66/jojo.png 640w,
/static/1625608a5b50569e606c847c8b9d5e3e/748f4/jojo.png 656w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;If we could express human abilities as precise numbers like in a strategy game,&lt;br&gt;maybe the interview process wouldn&apos;t even be necessary?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Just like the e-commerce example I mentioned, our customers have to make purchase decisions based only on approximate product information before they can actually use the product. And this is arguably the only point in the labor market where the seller can hold an advantageous position.&lt;/p&gt;
&lt;p&gt;That’s why, as sellers, we need to think very seriously about our sales strategy — how to communicate and brand the information about the product we’re offering to buyers.&lt;/p&gt;
&lt;p&gt;Building such a strategy starts with understanding the value of the product you’re bringing to market. You need to know your product’s strengths and the value those strengths carry before you can figure out what to emphasize and how to position yourself.&lt;/p&gt;
&lt;p&gt;While self-reflection on your strengths and weaknesses is valuable, an even easier method is to just go out into the market and try selling your abilities.&lt;/p&gt;
&lt;p&gt;Quality standards in the market are relative. When demand far outstrips supply, even lower-quality products can fetch high prices. When supply is abundant and demand is scarce, buyers demand higher quality.&lt;/p&gt;
&lt;p&gt;So rather than sitting at home strategizing about how to increase your product’s value, just go into the field, make a sales attempt, and gauge the customer’s reaction and the price you’re offered. You’ll learn much faster what the market currently thinks your product is worth.&lt;/p&gt;
&lt;p&gt;That’s why I often tell people who are thinking about growth: “Meet as many different developers as you can” and “Even if you get rejected, interviewing frequently and often is always beneficial.”&lt;/p&gt;
&lt;p&gt;Interviewing frequently is something I can’t emphasize enough. Through the process, you learn current labor market trends, identify gaps in your product based on questions you couldn’t answer well, and if you pass and receive an offer, you learn the market price for your product.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/e5166/interview.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 52.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwABAv/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHVHlUjk//EABwQAAICAgMAAAAAAAAAAAAAAAECAxMEEhQhMv/aAAgBAQABBQK4IZsldJO3mUcdVFx9f//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB0QAAMAAQUBAAAAAAAAAAAAAAABESECAyJCUmH/2gAIAQEABj8C2r4RxefgxOZiNKnaDP/EABsQAQADAAMBAAAAAAAAAAAAAAEAESExUbGR/9oACAEBAAE/Iai0BHe5zjREtzKIs2ZexX8gaSlUdyeTyf/aAAwDAQACAAMAAAAQ4N//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QkY//xAAXEQEAAwAAAAAAAAAAAAAAAAAAAREh/9oACAECAQE/EJ1b/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBYVFxwf/aAAgBAQABPxCz1QsBQPTqLWd2NAeemNJqJfhB+xaX1/NcJfTaBRprMzurFMHSf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;interview&quot; title=&quot;&quot; src=&quot;/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/c08c5/interview.jpg&quot; srcset=&quot;/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/0913d/interview.jpg 160w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/cb69c/interview.jpg 320w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/c08c5/interview.jpg 640w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/6a068/interview.jpg 960w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/e5166/interview.jpg 1200w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Networking and interviewing are the best forms of market research&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Once you’ve used these methods to understand your product’s value and approximate price, take a look at this table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Low quality&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;High quality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;Sell cheap&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;Low reward / Low cost&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;You just lose out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;Sell expensive&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;Hustler / Cost-efficient&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;High reward / High cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I think every quadrant except “high quality / sell cheap” — which is just a pure loss — is a viable strategy.&lt;/p&gt;
&lt;p&gt;Selling a low-quality product cheaply might look like someone doing the bare minimum without expecting additional rewards (quiet quitting) or someone just starting their career. Selling a high-quality product at a premium represents highly-paid key talent at companies.&lt;/p&gt;
&lt;p&gt;The interesting one is the quadrant where a low-quality product is sold at a high price. This could be someone who lacks substance but has accumulated years and thus a high salary, someone whose branding presents a more impressive image than their actual skills, or someone doing work that’s easy for them but appears costly to others.&lt;/p&gt;
&lt;p&gt;Selling cheap goods at high margins is the basis of business, but in the labor market, the seller can’t be separated from the product. If a defect is discovered, things get awkward fast.&lt;/p&gt;
&lt;p&gt;If the exaggeration is severe, it’ll get exposed during interviews or after joining. And if the inflated branding led to a price far exceeding the product’s actual value, word spreads among companies, and eventually nobody will buy.&lt;/p&gt;
&lt;p&gt;This quadrant also represents the worst ROI for customers, so when cash flow gets tight, these are the first people to face layoffs.&lt;/p&gt;
&lt;p&gt;That’s why I believe that in the labor market, rather than selling low-quality products at high prices, the better long-term strategy is to sell genuinely high-quality products at premium prices and build trust with your market’s customers.&lt;/p&gt;
&lt;h3 id=&quot;it-takes-more-fierce-effort-and-thinking-than-youd-expect&quot; style=&quot;position:relative;&quot;&gt;It takes more fierce effort and thinking than you’d expect&lt;a href=&quot;#it-takes-more-fierce-effort-and-thinking-than-youd-expect&quot; aria-label=&quot;it takes more fierce effort and thinking than youd expect permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So what does “high quality” mean in the labor market?&lt;/p&gt;
&lt;p&gt;There’s no definitive answer. People who command top compensation in the labor market don’t just excel at their hard skills — they stand out across many dimensions: leadership, communication, business insight, persuasion, networking, and organizational savvy.&lt;/p&gt;
&lt;p&gt;If you thought being a developer means you only need to be good at programming, think again. Programming skill is merely the baseline for working as a developer at a reasonable salary. If you want more, you need to develop skills beyond programming.&lt;/p&gt;
&lt;p&gt;Of course, no one can be perfect at everything, so it’s important to clearly identify your strengths and weaknesses and build your own unique character.&lt;/p&gt;
&lt;p&gt;This character can’t be gained through study alone — it’s a conclusion reached through endless deliberation and effort: analyzing market demand for talent, understanding your own characteristics, evaluating the competitiveness of your character itself. That’s why I said there’s no silver bullet.&lt;/p&gt;
&lt;p&gt;The market is already full of people fighting tooth and nail to prove their value. This is especially true in industries where the gap in compensation between the top few and everyone else is enormous — I’ve seen it particularly in sports, arts, and food service.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Here’s what you really need to understand: from the moment you start getting paid, in any world, any field, any profession — there are no amateurs. Once you start getting paid, you’re a professional. So what do you have to do? Act like one.” — Edward Kwon, celebrity chef&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“If you feel nothing after losing an important match, you’re no longer a professional. It has nothing to do with character — for a competitor, the pain of defeat must always be raw and vivid. You can’t always be the winner, but you must never become accustomed to the role of the loser.” — Lee Chang-ho, 9-dan Go player&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“Being a professional is about doing all the things you have to do on the days you don’t want to do them.” — Julius Erving&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“Focus on what we need to do! Every one of you gets paid to play. Win the game! Don’t lose! Don’t tie! Do it right! That’s what I want. Don’t be afraid, don’t be nervous, give it everything you’ve got! Sacrifice yourselves for the team. We’re the Lotte Giants! We need to be the best!” — Jerry Royster, baseball manager&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“In sports, I believe second place is the same as last.” — Sun Dong-yul, legendary Korean baseball pitcher&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The IT industry I work in provides decent compensation even if you’re not number one, so the competition isn’t quite as fierce as in those fields. But if you want more than what you’re currently getting, the truth remains the same — you need that mindset, that level of fierce effort and deliberation.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/57a2f0c10fbf684c1b6233cc9bbf3a34/a8a14/janghoon.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 51.87500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwT/xAAVAQEBAAAAAAAAAAAAAAAAAAACAP/aAAwDAQACEAMQAAAByxYhTAG//8QAGxAAAgEFAAAAAAAAAAAAAAAAAQIDABITMTL/2gAIAQEAAQUCkoouJZQok23CgWf/xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8Bka//xAAWEQEBAQAAAAAAAAAAAAAAAAAAERL/2gAIAQIBAT8BtYf/xAAbEAACAQUAAAAAAAAAAAAAAAAAAREQISJBgf/aAAgBAQAGPwLcCZGXKqx//8QAHBAAAgICAwAAAAAAAAAAAAAAAREAITFhEEFR/9oACAEBAAE/IXT7KcEANoO4glHDyDcKaGPNz//aAAwDAQACAAMAAAAQLz//xAAWEQEBAQAAAAAAAAAAAAAAAAABACH/2gAIAQMBAT8QzYd//8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/ENAZG3//xAAcEAEBAAICAwAAAAAAAAAAAAABEQAhMVFBYdH/2gAIAQEAAT8QEC1m5Z7zkCjY28k8YQHoKHGbG738wAIAjWMCVW0ds//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;janghoon&quot; title=&quot;&quot; src=&quot;/static/57a2f0c10fbf684c1b6233cc9bbf3a34/c08c5/janghoon.jpg&quot; srcset=&quot;/static/57a2f0c10fbf684c1b6233cc9bbf3a34/0913d/janghoon.jpg 160w,
/static/57a2f0c10fbf684c1b6233cc9bbf3a34/cb69c/janghoon.jpg 320w,
/static/57a2f0c10fbf684c1b6233cc9bbf3a34/c08c5/janghoon.jpg 640w,
/static/57a2f0c10fbf684c1b6233cc9bbf3a34/a8a14/janghoon.jpg 885w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;A professional must always evaluate themselves coldly and put in bone-grinding effort to better satisfy their customers.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Once you define yourself not as a mere worker but as a professional selling your abilities and skills on the market, your perspective on countless phenomena happening around you starts to shift.&lt;/p&gt;
&lt;p&gt;If a colleague doing seemingly the same work as you is earning a higher salary, you should compare and analyze their career against yours, check whether they possess capabilities you don’t, and recalibrate your own development direction.&lt;/p&gt;
&lt;p&gt;When it’s time to negotiate salary with your company, don’t passively wait for the company to recognize your achievements. Instead, think about how to present your accomplishments in a persuasive format. Proactively go out into the market to get offers from other companies, learn what the market values your skills at, and consider whether you can use that information as a negotiation tool.&lt;/p&gt;
&lt;p&gt;Not doing any of this is like someone who wants to run a business but just sits in their store without any promotion, waiting for customers to walk in. Whether it’s handing out flyers, developing new menu items, or paying a commission to get on a delivery platform — you have to do something to attract customers. And when customers increase, you can raise your prices per supply and demand, right?&lt;/p&gt;
&lt;p&gt;People envy the star instructor earning $10 million a year but don’t focus on the fierce effort and deliberation behind it.&lt;/p&gt;
&lt;p&gt;But there’s no such thing as a free lunch. No shortcuts either. If you want to succeed, you have to consistently strengthen the marketability of your skills, analyze your buyers’ needs, and go through the process of actually selling yourself — getting knocked around and learning from it.&lt;/p&gt;
&lt;p&gt;Just do it as a professional, not a serf.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Over the past few years, developer compensation has risen rapidly, making it seem like getting a developer job automatically meant great benefits and high salaries. I even heard recently that an acquaintance of mine started studying development — so this perception is still alive and well.&lt;/p&gt;
&lt;p&gt;It’s true that as the IT industry grew, demand for developers gradually increased while supply fell short. Back when I was in college in 2015, the popular engineering majors were the “Big Three” — electrical, chemical, and mechanical engineering — and computer science wasn’t particularly sought after.&lt;/p&gt;
&lt;p&gt;Then a certain company dramatically raised developer salaries and started a war to vacuum up developers from the market. Other companies, well aware that supply was woefully short relative to their demand for good developers, had no choice but to join the chicken game of salary escalation. &lt;small&gt;(I think this was a kind of FOMO phenomenon.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;But as of 2023, things are very different. As developer compensation rose rapidly in recent years, the perception of the developer profession improved, computer science programs gained prestige, bootcamps proliferated as a new business model, and the supply of developers in the market increased.&lt;/p&gt;
&lt;p&gt;Then an economic downturn hit, and suddenly demand isn’t keeping up with supply. It might still look like demand for developers is high, but look closer and it’s not.&lt;/p&gt;
&lt;p&gt;Labor prices have &lt;a href=&quot;https://en.wikipedia.org/wiki/Nominal_rigidity&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;downward rigidity&lt;/a&gt; — once they go up, they don’t easily come back down — so even when demand drops, it’s hard to suddenly lower prices.&lt;/p&gt;
&lt;p&gt;Our customers end up paying above the equilibrium price naturally formed by supply and demand, so they become more selective about high-quality products. This leads to involuntary unemployment — layoffs or inability to find work — and wage polarization among developers.&lt;/p&gt;
&lt;p&gt;Sellers providing high-value labor receive more compensation, while sellers providing low-value labor find no buyers at all or receive even lower offers than before. &lt;small&gt;(It’s easier for a company to spend $100K on one highly capable person than to hire three less capable people at the same total cost.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;These market changes are critically important for developers, especially those just starting their careers.&lt;/p&gt;
&lt;p&gt;Looking at the stock market might make it seem like the economy is recovering, but nothing has actually been resolved — it’s a difficult market for everyone. In this environment, I simply cannot bring myself to say “just work hard and the rewards will follow.” That advice worked when times were good, not now.&lt;/p&gt;
&lt;p&gt;Yet amid these rapidly changing market conditions, there’s plenty of talk about how learning TypeScript, React, and Next.js leads to employment, or how Rust is the latest trend — but hardly anyone talks about these practical realities. I’m not sure why.&lt;/p&gt;
&lt;p&gt;Technology matters, but you need a stable life first before you can enjoy the technologies you love. Learning driven by intellectual curiosity rather than survival is far healthier for your growth.&lt;/p&gt;
&lt;p&gt;I hope many developers never forget that before being a developer, you’re a working professional and a market participant. I hope you develop the cold-eyed market perspective needed to analyze and respond to difficult situations like the current one.&lt;/p&gt;
&lt;p&gt;That wraps up this post on becoming someone who survives the market.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[시장에서 살아남는 사람이 되기]]></title><description><![CDATA[이번 포스팅에서는 시장 경제에 참여하는 한 명의 플레이어로써 필자가 생각해온 고민들에 대해 한번 담담히 풀어보려고 한다. 지금까지 필자는 개인의 성장과 모티베이션 그리고 철학에 대한 이야기를 많이 해왔지만, 이번 포스팅에서는 지금까지와는 조금 다른 현실적인 이야기를 해보려고 한다. 그저 열심히 하다보면 언젠가 잘 될 것이라는 말보다는 정말 현실적으로 도움이 될 만한 고민을 해볼 수 있는 아젠다를 던져본다.]]></description><link>https://evan-moon.github.io/2023/05/07/improve-my-career/</link><guid isPermaLink="false">20230507-improve-my-career</guid><pubDate>Sun, 07 May 2023 01:54:45 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 시장 경제에 참여하는 한 명의 플레이어로써 필자가 생각해온 고민들에 대해 한번 담담히 풀어보려고 한다.&lt;/p&gt;
&lt;p&gt;지금까지 필자는 개인의 성장과 모티베이션 그리고 철학에 대한 이야기를 많이 해왔지만, 이번 포스팅에서는 지금까지와는 조금 다른 현실적인 이야기를 해보려고 한다. 그저 열심히 하다보면 언젠가 잘 될 것이라는 말보다는 정말 현실적으로 도움이 될 만한 고민을 해볼 수 있는 아젠다를 던져본다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;개발자로써 일을 하다보면 의외로 나보다 경험이 적은 개발자들을 도울 수 있는, 혹은 도와야만 하는 기회를 자주 만날 수 있다.&lt;/p&gt;
&lt;p&gt;지금까지 필자가 직접 만났거나 연락을 주고 받았던 주니어 분들은 대부분 성장에 목말라 있었고, 필자는 주로 성장의 모티베이션과 꾸준한 노력, 메타인지와 같이 성장에 대한 고찰을 해볼 수 있는 주제를 주로 전달해드렸었다.&lt;/p&gt;
&lt;p&gt;그리고 보상에 대한 질문을 해주시는 분께는 이런 말을 자주 했었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;성장해서 유능한 개발자가 되면 보상은 자연스럽게 따라와요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 어느 정도는 맞는 말이다. 하지만 일을 잘 한다고 해서 보상이 저절로 생긴다기보다는 좋은 기회가 찾아왔을 때 잡을 수 있는 역량을 보유하는 것에 가깝다. 애초에 일을 잘 하는 것과 돈을 잘 버는 것은 약간은 다른 맥락이다.&lt;/p&gt;
&lt;p&gt;세상에는 꾸준한 노력으로 좋은 실력을 쌓더라도 아무도 알아주지 않아 신입 개발자보다도 적은 보상을 받는 시니어 개발자도 존재하며, 반대로 딱히 프로그래밍 실력이 좋지 않음에도 퍼스널 브랜딩을 통해 높은 보상을 챙겨가는 개발자도 존재한다.&lt;/p&gt;
&lt;p&gt;물론 기본적으로 개발자의 프로그래밍 역량이 좋을수록 좋은 보상을 받을 확률이 높다는 것은 사실이다. 다만 아무리 프로그래밍 역량이 좋다고 해도 가만히 앉아만 있다면 아무도 그 능력을 알아주지 않을 가능성이 높으며, 솔직히 정말 상위 1%의 두각을 나타내는 개발자가 아닌 이상 어느 정도 연차가 차면 프로그래밍 스킬 자체는 도찐개찐인 경우가 대부분이다.&lt;/p&gt;
&lt;p&gt;성실하게 노력하는 사람이 그에 비례하여 보상받는다는 아름다운 스토리는 누군가의 모티베이션이 될 수 있겠지만, 막상 현실을 자세히 들여다보면 슬프게도 그렇지 않은 경우가 더 많다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 이 포스팅에서 성장에 대한 이야기보다는 조금 더 현실적인 시장에 대한 이야기를 하려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;시장이라는-게임에-대한-기본적-이해도를-높히자&quot; style=&quot;position:relative;&quot;&gt;시장이라는 게임에 대한 기본적 이해도를 높히자&lt;a href=&quot;#%EC%8B%9C%EC%9E%A5%EC%9D%B4%EB%9D%BC%EB%8A%94-%EA%B2%8C%EC%9E%84%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B8%B0%EB%B3%B8%EC%A0%81-%EC%9D%B4%ED%95%B4%EB%8F%84%EB%A5%BC-%EB%86%92%ED%9E%88%EC%9E%90&quot; aria-label=&quot;시장이라는 게임에 대한 기본적 이해도를 높히자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;우리가 살고 있는 대한민국은 자본주의체제를 선택한 국가이다. 간단하게 자본주의는 시장 참여자들이 시장 내에서 각자가 가지고 있는 가치들을 교환하며 굴러가는 경제체제라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;즉, 우리 같은 직장인들이 일자리를 구하고 있는 노동시장 또한 기본적으로 노동자가 가진 노동력이라는 재화와 기업이 가진 금전적 재화를 맞바꿈하는 기본원리를 가지고 있다는 것이다.&lt;/p&gt;
&lt;p&gt;어떻게 보면 굉장히 간단하고 명확한 내용이지만, 실제로 우리는 실생활 속에서 이 개념을 자주 잊고는 한다. 우리가 시장이라는 냉정한 게임에서 살아남기 위해 가장 먼저 해야 하는 것은 이 노동시장에 대한 시각 자체를 바꾸는 것이다.&lt;/p&gt;
&lt;p&gt;시장은 구성원들이 각자가 얻을 수 있는 최대의 이익을 위해 의사결정하며 나아가는 게임이다. 시장에서 발생하는 많은 의사결정들을 모델링하고 연구하는 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EA%B2%8C%EC%9E%84%EC%9D%B4%EB%A1%A0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;게임이론&lt;/a&gt;은 많지만 필자는 그 중에서도 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%A3%84%EC%88%98%EC%9D%98_%EB%94%9C%EB%A0%88%EB%A7%88&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;죄수의 딜레마&lt;/a&gt;라는 게임이 현실과 가장 유사한 모습을 가진다고 생각한다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;상대의 자백&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;상대의 침묵&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;나의 자백&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;둘 다 3년형&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;나는 석방, 상대는 10년형&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;나의 침묵&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;나는 10년형, 상대는 석방&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;둘 다 1년형&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;죄수의 딜레마 게임의 특징은 개인에게는 각자 최선이 될 수 있는 선택을 해도 결과적으로는 최선이 아닐 수 있다는 것이다. 나와 상대 모두 침묵을 선택한다면 둘 다 1년형이라는 결과로 이어지겠지만 내가 침묵을 한 상태일 때 상대방이 자백을 하게 되면 나만 10년형을 살게 될 수도 있는 리스크가 존재한다.&lt;/p&gt;
&lt;p&gt;결국은 양 쪽 모두 상대가 어떤 행동을 취하든 자신에게 큰 이득을 주는 자백을 선택하게 되고 함께 사이좋게 3년형을 살게 되는 것이다.&lt;/p&gt;
&lt;p&gt;이는 마치 핵무기가 없는 것이 범지구적으로는 이로운 행위임이 분명함에도 핵무기를 없애는 선택을 쉽사리 하지 못 하는 상황과도 유사하며, 시장에서 발생하는 수 많은 인터랙션도 결국은 전체의 이익보다는 자신의 이익을 위해 움직이게 되는 경향이 크기 때문에 이와 크게 다르지 않다.&lt;/p&gt;
&lt;p&gt;그럼 어려운 이야기는 이제 접어두고 시장에 대한 시각을 바꾸기 위해 많은 직장인의 관심사인 연봉에 대한 이야기를 먼저 해보도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;시장에-절대적-갑과-을은-없다&quot; style=&quot;position:relative;&quot;&gt;시장에 절대적 갑과 을은 없다&lt;a href=&quot;#%EC%8B%9C%EC%9E%A5%EC%97%90-%EC%A0%88%EB%8C%80%EC%A0%81-%EA%B0%91%EA%B3%BC-%EC%9D%84%EC%9D%80-%EC%97%86%EB%8B%A4&quot; aria-label=&quot;시장에 절대적 갑과 을은 없다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;아마 대부분의 직장인들은 자신의 연봉을 높히고 싶다는 생각을 한번 쯤은 해보았을 것이다. 물론 연봉이 높아진다고 바로 자산이 늘어나 부자가 될 수 있는 것은 아니지만, 확실히 연봉이 오를 수록 내 삶의 질은 눈에 띄게 좋아지니 말이다.&lt;/p&gt;
&lt;p&gt;많은 사람들이 연봉이라는 개념을 막연하게 재직 기간이 늘어나거나 이직을 통해 올릴 수 있는 가치라고 생각하고 있지만 사실 연봉이라는 것은 생각보다 냉정한 시장의 평가를 기반으로 결정된다.&lt;/p&gt;
&lt;p&gt;그러니 연봉을 높히기 위해서는 우선 연봉이라는 것이 그저 일을 오래 한다고 해서 오르는 것이 아니라, 시장에서 결정되는 내 능력과 노동력에 대한 가격이라는 것을 명확히 인지하고 인정해야한다. 우리는 능력과 노동력을 판매하는 대신 구매자인 기업으로부터 연봉이라는 가치를 제공받는 일종의 거래를 하고 있는 것이다.&lt;/p&gt;
&lt;p&gt;결국 자본주의 시장 경제에서 발생하는 모든 인터랙션은 가치와 가치를 교환하는 거래에서부터 출발하며, 결국 판매자인 내가 제공하는 기술력과 노동력의 가치가 높다고 판단될수록 구매자인 기업은 나에게 더 높은 금액을 지불한다.&lt;/p&gt;
&lt;p&gt;필자는 자신의 능력이 전혀 성장하지 않았음에도 불구하고 지금보다 더 높은 연봉을 요구하는 상황은 마치 아무런 개선사항도 없는 물건을 팔면서 내 마진을 더 남기기 위해 소비자에게 더 높은 가격을 쳐달라고 하는 것과 별반 다르지 않다고 생각한다. &lt;small&gt;(별다른 정당성 없이 치킨 가격을 올렸을 때 소비자들의 반응이 어땠는지를 생각해보자)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;즉, 시장에서 연봉을 높일 수 있는 가장 기본적인 원칙은 &lt;strong&gt;내가 판매하는 상품인 기술력과 노동력의 가치를 먼저 올린 이후에 딜을 걸어야 한다는 것&lt;/strong&gt;이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7e75357bf1d72f21d3f9cf4fcf4753a2/38a65/market.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 61.24999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB5UlEQVR42q1S2Y7TQBDM//8MLzwgVmh5iAQrJASLNomP+Ai+xzPxFcfHjIvpySbsSiBeGKnkcnuqut3dqwULqnMHfqoh+lrzFmpZcD2L5lJKg5eH4vXQGc1F1xndapQzgirBockQ1oQUOWdgRQHGGOI4huM48DwPaZqCc469u4fjufjZ5kYTaI1/TDDMI1ZyUXj0t3hz9xbv1h/wefMVrc7Wn3qM44hpmlCWJQqd4PpeVRWY4Ai0yf2XNe4+fYSVehjVfKnQ4xF2OrBL9oY/WVvYlm2M8jw3FRKIZxqsYChKBl/EsDIfThHCE9HvCvNOID8JZCeOoheYdBIl1a13SqlXvSRM8/Ss48g6rjnHrCRW+M/nj4ZUzRUvY3/79spQygVF0iKPLiA+z+pZDDOIYRh0bEbf9zcjqVtSJB2YRhETWkitW42DxMEV8C2GwC41P6LIOZhuOk02CAKDKIrMYGhQtm1h82QhDVvsHiO4m8x4DD1NeZiRBDU23wJsv4fIDh3iKEPJSwghzP6RYRiGxpSSNE2jjY/6bov79w94WP9A7FcYz9pwGiVCRxgENtcfGlg7F77vGUNa5izLLiujn2TIOe0lNxr6IwLxgQypJc1xQM3PBsSVWv45Teol3a14r3X9TfcLA1WSOhNpt3QAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;market&quot; title=&quot;&quot; src=&quot;/static/7e75357bf1d72f21d3f9cf4fcf4753a2/6af66/market.png&quot; srcset=&quot;/static/7e75357bf1d72f21d3f9cf4fcf4753a2/69538/market.png 160w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/72799/market.png 320w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/6af66/market.png 640w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/d9199/market.png 960w,
/static/7e75357bf1d72f21d3f9cf4fcf4753a2/38a65/market.png 1075w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;노동시장의 거래도 근본적으로는 카페에서 아메리카노를 사고 파는 것과 크게 다르지 않다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;물론 노동시장에서의 거래는 판매자인 우리의 정보력과 구매자인 기업의 정보력에 차이가 있는 경우가 많기 때문에 아무런 준비가 되어있지 않은 상태라면 기본적으로 판매자가 불리한 위치에서 거래를 진행하여 양질의 노동력을 시세보다 싼 값에 제공하게 되는 상황에 처하기 쉽다.&lt;/p&gt;
&lt;p&gt;하지만 결국 근본적으로는 이 또한 시장에서 발생하는 거래이기 때문에 각자가 보유한 정보력, 판매하는 상품의 상대적 가치, 수요와 공급, 협상 능력, 시장의 상황과 같은 여러가지 요인에 따라 이러한 위치는 얼마든지 뒤바뀔 수도 있다.&lt;/p&gt;
&lt;p&gt;노동시장에서 기업이 무조건 갑이고 노동자가 무조건 을일 것이라고 생각하는 것과 달리, 실제로는 양질의 노동력과 정보력을 가져 기업과의 거래에서 유리한 위치를 점하는 노동자들 또한 분명 존재한다. 단지 이 정도 능력을 가진 노동자의 비율이 현저히 적기 때문에 마치 항상 불리한 위치일 것이라고 보여지는 것 뿐이다.&lt;/p&gt;
&lt;p&gt;애초에 어떤 사람의 연봉이 높다는 것은 그 사람이 제공하는 노동력의 가치가 그만큼 높고 수요도 많지만 그 수요를 충족시킬 정도의 공급은 부족한 상황이라는 것을 의미한다. 이 정도 역량을 지닌 노동자는 기업의 규모와 상관없이 모든 기업이 채용하고 싶을테니 기업들 간에 경쟁이 붙기도 한다.&lt;/p&gt;
&lt;p&gt;이처럼 양질의 노동력을 제공할 수 있는 노동자들은 시장에서 기업보다 유리한 위치를 점하고 있는 경우가 많기 때문에 이력서를 넣고 면접을 보는 과정보다는 기업의 연략을 받고 커피챗이나 풀링 디너를 통해 기업에 대한 정보를 얻고 마음에 드는 회사로 이직하는 과정을 경험하기도 한다. 결국 노동 시장에서의 절대적인 갑과 을은 없는 것이다.&lt;/p&gt;
&lt;p&gt;이는 일반적인 시장에서 발생하는 거래라고 생각해보면 너무나도 당연한 사실들이지만, 앞서 말한 노동시장의 특징과 더불어 대부분의 노동자가 거래에 임할 때 상대적 약자의 위치인 경우가 많다는 사실로 인해 일반적인 시장과는 약간 다른 시각으로 이 시장을 바라보게 되는 것이다.&lt;/p&gt;
&lt;p&gt;시장에서 살아남기 위한 첫 번째 시각 전환은 스스로를 노비처럼 여기는 자조섞인 마인드를 버리고 내가 기업과 상호평등한 관계에서 거래를 할 수 있는 플레이어가 될 수 있다는 것을 인지하여, 스스로를 생산성있는 고민과 전략을 짤 수 있는 상태로 만드는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;시장참여자들은-모두-이기적이다&quot; style=&quot;position:relative;&quot;&gt;시장참여자들은 모두 이기적이다&lt;a href=&quot;#%EC%8B%9C%EC%9E%A5%EC%B0%B8%EC%97%AC%EC%9E%90%EB%93%A4%EC%9D%80-%EB%AA%A8%EB%91%90-%EC%9D%B4%EA%B8%B0%EC%A0%81%EC%9D%B4%EB%8B%A4&quot; aria-label=&quot;시장참여자들은 모두 이기적이다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;간혹 뉴스를 보다보면 기업과 노동자가 마치 적처럼 보여지고는 한다. 기업이 제대로 임금을 쳐주지 않아 노조가 파업을 한다던가, 경영진의 Governance가 건전하지 않아 기업이 어려워졌는데 노동자가 해고를 당해 생존권에 위협을 받는다던가 하는 일들은 그렇게 드문 일이 아니니 말이다.&lt;/p&gt;
&lt;p&gt;물론 우리는 노동자의 입장인 경우가 많으니 상대적으로 공감이 덜 되는 기업의 입장보다는 노동자의 입장에 더 감정 이입이 되는 것을 부정할 수는 없다. 하지만 이런 상황들 또한 냉정하게 바라보면 그저 각자의 이익을 위해서 싸우고 있는 게임 참여자들간의 협력과 배신의 연속이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;애초에 노조라는 개념 자체가 기업과 평등한 위치에서 거래를 진행하여 노동자들의 이익을 얻기 위해 뭉친 집단이며, 당연히 대부분의 의사결정은 기업이 아닌 노동자들의 이익을 위한 방향으로 진행된다. 반대로 기업 입장에서는 노동자보다는 기업에 이익이 되는 방향으로 의사결정을 진행할 것이다.&lt;/p&gt;
&lt;p&gt;서두에서 이야기했듯이 기본적으로 시장은 모든 구성원이 법이 허락하는 선 안에서 자신의 최대 이익을 위해 이기적으로 행동하는 게임이다. 그러니 시장에서 살아남기 위해서는 선과 악이라는 감정적 판단보다는 상황을 냉정하게 분석하고 최선의 의사결정을 할 수 있는 논리적 판단과 중립적인 시각이 필요하다.&lt;/p&gt;
&lt;p&gt;판매자인 우리는 우리가 가진 능력을 비싼 가격에 팔고 싶겠지만 반대로 구매자인 기업은 최대한 싼 가격에 사고 싶어한다. 이런 사실 또한 일반적인 시장 거래라고 생각해보면 너무나도 당연한 것이며, 비싼 가격을 요구하는 노동자에게 양심없다고 할 이유도 없고 싼 가격을 요구하는 기업이 악덕 기업이라고 할 만한 이유도 없다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/28f028c4465567d2f13fa16ff2cc7326/8e1fc/carrot.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 103.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAVABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAe1Nc5dlQ70LkDf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAQIREBITIf/aAAgBAQABBQLwtCskmzmiMYrFWapH/8QAFxEBAAMAAAAAAAAAAAAAAAAAAQAQEf/aAAgBAwEBPwEyN//EABYRAAMAAAAAAAAAAAAAAAAAAAERIP/aAAgBAgEBPwEuP//EABkQAAIDAQAAAAAAAAAAAAAAAAABECExEf/aAAgBAQAGPwLHGo4yynFmH//EABwQAAICAwEBAAAAAAAAAAAAAAABETEhcYEQkf/aAAgBAQABPyFxuwVSxsx5doUwfCGzXRNZ3yFafBUkP//aAAwDAQACAAMAAAAQ7DA//8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERMeH/2gAIAQMBAT8QRtZF4WFZ/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERMeH/2gAIAQIBAT8QZMQrOmkR/8QAHBABAAMBAAMBAAAAAAAAAAAAAQARMSEQQVHR/9oACAEBAAE/EACiLffu77lK3HHBE3dX6RHdFsVw7y5Usm9p+RCUFvHhIg+wRRTeE//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;carrot&quot; title=&quot;&quot; src=&quot;/static/28f028c4465567d2f13fa16ff2cc7326/c08c5/carrot.jpg&quot; srcset=&quot;/static/28f028c4465567d2f13fa16ff2cc7326/0913d/carrot.jpg 160w,
/static/28f028c4465567d2f13fa16ff2cc7326/cb69c/carrot.jpg 320w,
/static/28f028c4465567d2f13fa16ff2cc7326/c08c5/carrot.jpg 640w,
/static/28f028c4465567d2f13fa16ff2cc7326/8e1fc/carrot.jpg 900w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;어차피 말도 안 되는 금액을 제시하면 자연스럽게 거래 자체가 성사되지 않는다&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;분명 정보 불균형 등을 이용하여 양질의 인재를 터무니 없는 가격에 후려치거나 처음 계약했던 내용과 다르게 과다한 업무를 부여하는 등의 공정하지 않은 거래를 조장하는 블랙기업들도 존재한다.&lt;/p&gt;
&lt;p&gt;하지만 반대 입장에서 보면 높은 연봉을 받음에도 불구하고 조용한 퇴직과 같은 행위를 하는 것이나 처음 계약 조건에는 없었던 무리한 복지를 요구하는 것, 인터뷰 때 보여줬던 열정적인 모습과 다르게 입사 후 대충 일을 하는 등의 불공정 거래도 존재하기 마련이다.&lt;/p&gt;
&lt;p&gt;이처럼 거래 상대방에 대한 평가는 상대적이기 때문에 절대적인 선이나 절대적인 악은 없다.&lt;/p&gt;
&lt;p&gt;결국은 기업이든 노동자든 시장에서 서로의 이익을 위해 이기적으로 행동하는 평등한 게임 참여자일 뿐이다. 만약 시장에서 노동자의 기본 포지션이 상대적 약자라면 우리는 이를 인정하고 이 포지션을 뒤집을 수 있는 전략을 떠올리고 실행하면 그만이다.&lt;/p&gt;
&lt;p&gt;시장에서 성공적인 거래를 진행하기 위해서는 내 입장만 생각하는 것이 아니라 거래에 임하는 상대방의 입장과 심리를 이해하고 적절한 조건을 제시하는 전략이 필수적이다. 물론 상대방에게 통수를 한번 맞은 이후에도 굳이 협력할 필요는 없으니, 일종의 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%8C%83%ED%8F%AC%ED%83%AF&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;팃포탯&lt;/a&gt; 전략이라고 생각하는 것이 좋다.&lt;/p&gt;
&lt;p&gt;팃포탯은 첫 번째는 협력으로 시작하되 상대가 배신을 하면 똑같이 갚아주고 협력을 하면 똑같이 협력해주는 전략이다. 노동자와 기업의 딜은 주로 처우 협의 때 발생하니, 첫 처우 협의 때는 어느 정도 협력을 해주되 이후 연봉 협상 때 원하는 결과가 나오지 않는다면 굳이 남아있지 않고 다른 곳으로의 이직을 검토해보는 등의 방식을 생각해볼 수 있다.&lt;/p&gt;
&lt;p&gt;연협이 불발되었을 때 “난 그렇게 헌신했는데 회사가 어떻게 나에게 이럴 수 있냐”라는 등 감정적인 어프로치를 하시는 분들도 있지만, 어차피 내가 원하는 가격을 쳐주지 않는 구매자에게 감정적인 대응을 해봤자 상대방은 절대로 내가 원하는 것을 거저 내어주지 않는다.&lt;/p&gt;
&lt;p&gt;나에게 아메리카노 한 잔을 8만원에 팔려고 하는 카페 사장에게 “커피가 너무 비싸서 안 살래요”라고 이야기했을 때, 사장님이 나에게 “이게 뭐가 비싸요!!”라며 화를 내거나 “제가 가정형편이 어려워서…”라고 동정을 유도해도 내가 그 커피를 사주지 않을 것이라는 걸 생각해보면 된다. 차라리 아메리카노 한 잔에 8만원을 받아야 하는 합리적 근거를 제시하는 편이 더 확률이 높을 것이다.&lt;/p&gt;
&lt;p&gt;결국 우리가 기업에게 노동력을 제공하며 원하는 가격을 받기 위한 효과적인 전략을 만들기 위해서는 시장이라는 게임과 나와 거래하는 상대방인 기업에 대해서 이해하고 서로가 Win-Win할 수 있는 방법에 대해서 고민해야한다.&lt;/p&gt;
&lt;p&gt;시장에서 살아남기 위한 두 번째 시각 전환은 나와 기업 모두 자신의 이익을 최대로 만들기 위한 의사결정을 하는 플레이어 중 하나일 뿐임을 인정하고, 거래 결과에 대한 감정적인 대응보다는 현상 그대로를 바라볼 수 있는 객관적 시각을 길러 상대방이 원하는 것이 무엇인지, 어떻게 접근해야 구매 욕구를 불러일으킬 수 있을지에 대해 냉철하게 판단할 수 있는 상태로 나아가는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;customer-centric&quot; style=&quot;position:relative;&quot;&gt;Customer Centric&lt;a href=&quot;#customer-centric&quot; aria-label=&quot;customer centric permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자는 이 글에서 내가 가진 능력의 가치를 높혀 연봉을 높히는 구체적인 전략을 이야기하지는 않을 것이다. 애초에 개개인의 역량과 처한 상황 자체가 너무나 다르기 때문에, 어느 정도의 요령은 있을 수 있어도 “이렇게만 하면 연봉이 오른다”라고 하는 Silver Bullet 같은 전략은 존재하기 어렵기 때문이다.&lt;/p&gt;
&lt;p&gt;단지 필자는 여러분이 이러한 전략에 대한 고민을 시작할 수 있도록 노동시장을 바라보는 시각과 기본 개념을 바꿀 수 있는 약간의 도움만 드릴 수 있을 뿐이다.&lt;/p&gt;
&lt;p&gt;앞서 이야기했듯이 우리는 노동시장에서 우리의 능력을 기업에게 팔아야 하는 판매자 혹은 생산자의 입장이다. 즉, 우리의 능력을 하나의 상품으로 생각하고 고객들이 내 상품을 구매한다는 결정을 내리기 위해 어떤 정보들이 필요한 지에 대해서 생각해봐야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 이야기하면 어떻게 사람을 상품으로 보고 가격을 매기냐고 생각하시는 분들도 계시겠지만, 이미 우리는 기업에게 노동력을 제공하고 연봉을 받고 있지 않은가? 그게 바로 우리에게 매겨진 가격이다. 더 정확하게 이야기하면 인간 자체가 아닌 인간이 &lt;strong&gt;보유한 능력에 대해 매겨진 가격&lt;/strong&gt;이라고 할 수 있다. &lt;small&gt;(인간 채용이 아니라 재능을 가진 인간을 채용한다는 인재 채용이라는 단어를 사용하는 이유이다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;물론 이 가격이 형성될 때 최저임금제와 같이 기본적인 생존권을 보장하기 위한 팩터가 포함되기는 하지만, 기본적으로는 그저 상품에 대한 수요와 공급에 의해 형성된 가격일 뿐이다.&lt;/p&gt;
&lt;p&gt;사실 노동시장에서 고객들이 우리의 능력을 구매하는 행위는 우리가 쿠팡과 같은 온라인 커머스 플랫폼에서 매우 비싼 상품을 구매하는 상황과 크게 다르지 않다. 예를 들어 로봇 청소기를 하나 장만해야 한다고 생각해보자.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3e1d7d064e044b9f2a9991365283f479/d9ed5/coupang.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAACf0lEQVR42k1Uy27TUBDttyAWqP8CG1iA1AV/hERFV/0AQEJ0W1SQQFSqRFq1Tdu8nDqxndiJ38/r69dh7nXidKQr38e8zpkZ70UJQ1mWEFIr/2B9/gDfWCCIMlSqijzn4FWNJo5RajryokAldF0X5dJE3tCe3rey57oO0jSVh97FOd69eonXb95iZDjyLstyMJZ3BpqmIYqi7hwnFLiqdg5TMuAUVciPs5949vwF9vf3MRzcyztFecRspnUGx8fH6Pf7cs95gf7dkAIkO4dxnBCsNoOcc3w/OcHZz18YDEdwPA/Xt7dQCboQQY1u6PB9f5M9w83dA/wgfOowQpK0EaIwgrm0YJomgiDAPSlrcw0uOWZk7Ns2VqYFy1rJ97Xt0DeETfeMsR3kYgM5MjXoDxcIPRM1kR0uR9Af7xGRckM8rZUr6PoUjPRLzrBWH7ByLBSUedM0rUNB8NZ7kawQuQtUdUtyGDuw3XUX0E9ceL4HYVs3BezlGI69xlPZE3C3HIooNaUmvu2q5ZJvFLRyHDQbw5raiBMVdWu4c5hlGTnZ9BE9FLxEGCa0WqKHgwE+HR2hIr2GeONFiZKC1pRIQlxnPKfipFRxvi1KTMUIuyqyjGM+MzCZTOWdYRj4eHgoW0TCDmK5L6mZDWpsmyB/+foN0+lj6zCkyjpO28RiOv78vcTv8x7cKKYJqDCeKOj1LlvSaV31qDBzXepfX9/g4OA9Tk/POspkldM0a7s+ZViuHGrUWPJaURZMdAHBEbQw+orgCaESwmgsF4uFRNZVWUAuiha/tzBgKWNSZHLcluoAynwCm/gqKIA1HkGdzRFQ4JLO7lyFR1MSUULV5n/wH/vB1RAe8gUlAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;coupang&quot; title=&quot;&quot; src=&quot;/static/3e1d7d064e044b9f2a9991365283f479/6af66/coupang.png&quot; srcset=&quot;/static/3e1d7d064e044b9f2a9991365283f479/69538/coupang.png 160w,
/static/3e1d7d064e044b9f2a9991365283f479/72799/coupang.png 320w,
/static/3e1d7d064e044b9f2a9991365283f479/6af66/coupang.png 640w,
/static/3e1d7d064e044b9f2a9991365283f479/d9199/coupang.png 960w,
/static/3e1d7d064e044b9f2a9991365283f479/21b4d/coupang.png 1280w,
/static/3e1d7d064e044b9f2a9991365283f479/d9ed5/coupang.png 2880w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;로봇 청소기 생각보다 비싸다...&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;온라인을 통해 상품을 구매할 때는 해당 상품을 직접 사용해볼 수 없다는 특징이 있다. 게다가 만약 몇 천원 짜리 상품을 구매한다면 그냥 대충 지를 수 있겠지만, 로봇 청소기와 같은 고가의 제품을 구매할 때는 내 소중한 돈을 엄한 곳에 쓰지 않기 위해 신중해질 수 밖에 없을 것이다.&lt;/p&gt;
&lt;p&gt;그래서 우리는 기본적으로 상품 상세 페이지를 자세히 읽어 보고 다른 구매자들이 작성한 리뷰나 별점도 살펴보고 유튜브와 같은 다른 SNS에 올라온 리뷰까지 확인한 이후 “음, 이 정도면 나쁘지 않은 소비구만”이라는 생각이 들면 구매를 결정하게 된다. &lt;small&gt;&lt;del&gt;(물론 성향따라 그냥 지르시는 분들도 계시긴 하다…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;우리의 능력을 사는 고객들도 마찬가지이다. 노동시장에서의 구매자는 우리의 능력을 직접 경험해보고 구매를 결정할 수 없으며, 기본적으로 우리가 제출한 단순한 상품 소개서(이력서)와 총 2시간 정도의 방문판매영업(인터뷰), 혹은 이 상품을 구매했던 다른 고객들의 리뷰(레퍼런스 체크) 등을 기반으로 구매를 결정하게 된다.&lt;/p&gt;
&lt;p&gt;즉, 이 단계에서는 상품의 실제 스펙보다는 해당 상품을 소개하는 정보들과 타인의 리뷰들을 기반으로 한 판단이 구매 결정에 큰 영향을 끼치게 될 수 밖에 없다는 것이다.&lt;/p&gt;
&lt;p&gt;심지어 인간의 능력이라는 상품은 1년에 몇 천만원에서 몇 억원이나 지불해야 할 정도로 매우 비싼 상품인데다가, 한번 구매하고 나서 3개월이 지나면 환불도 어려워서 구매 의사결정이 실패했을 때의 리스크가 굉장히 크니 매우 신중하게 결정할 수 밖에 없다. &lt;small&gt;(당장 손이 급하다는 이유로 별다른 출구 전략도 없이 인재밀도가 낮은 채용을 해버리는 것을 최대한 피해야 하는 이유이기도 하다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그러니 우리는 생산자로써 내 능력의 판매 확률을 높이기 위해 구매자인 기업이 어떤 문화와 특성을 가지고 있는지, 현재 어떤 인재를 찾고 있는지, 내 능력으로 그 기업이 가진 비즈니스 문제나 기술적 문제를 해결할 수 있는지와 같이 고객들에 대한 다양한 정보를 수집하여, 어떤 방법으로 내가 가진 능력을 해당 기업에 팔아볼 지에 대한 전략을 세우는 과정을 거쳐야 한다.&lt;/p&gt;
&lt;p&gt;결국 노동시장도 시장이다. 결국 우리가 이 시장에서 기업들에게 내 능력을 판매하며 더 많은 보상을 받기 위해서는 “어떻게 하면 좋은 개발자가 될 수 있을까?(좋은 상품을 만들 수 있을까?)”와 같은 고민 뿐만 아니라 “우리 고객들은 어떤 인재를 채용하고 싶을까?(어떤 상품을 구매하고 싶을까?)”와 같은 소비자 중심의 고민들도 함께 해야한다.&lt;/p&gt;
&lt;p&gt;시장에서 살아남기 위한 세 번째 시각 전환은 취업이라는 활동을 단순히 기업이 내는 시험을 보고 합격하여 그 기업의 소속이 되는 행정적 과정이 아니라, 내가 직접 시장에 뛰어들어 내 능력을 홍보하고 고객의 니즈를 맞춰 구매 욕구를 불러일으켜야 하는 일종의 경제 활동으로 바라보는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;프로페셔널의-마음가짐을-가지자&quot; style=&quot;position:relative;&quot;&gt;프로페셔널의 마음가짐을 가지자&lt;a href=&quot;#%ED%94%84%EB%A1%9C%ED%8E%98%EC%85%94%EB%84%90%EC%9D%98-%EB%A7%88%EC%9D%8C%EA%B0%80%EC%A7%90%EC%9D%84-%EA%B0%80%EC%A7%80%EC%9E%90&quot; aria-label=&quot;프로페셔널의 마음가짐을 가지자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;나도 결국 자본과 각자의 이기적인 선택으로 돌아가는 시장 참여자 중의 하나라는 사실을 인지하고 받아들였다면, 이제 어떻게 하면 나의 이익을 가장 크게 만들 수 있는지 고민해봐야 할 차례이다.&lt;/p&gt;
&lt;p&gt;앞서 필자는 다음 세 가지 시각 전환에 대해서 이야기했었다.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;노동자와 기업이 상호평등한 거래를 할 수 있는 플레이어가 될 수 있음을 인지하기&lt;/li&gt;
&lt;li&gt;노동자와 기업이 모두 자신의 이익을 최대로 만들기 위해 움직이는 이기적인 녀석들임을 인지하기&lt;/li&gt;
&lt;li&gt;취업이라는 활동이 내가 누군가에게 내 능력을 판매해야하는 경제 활동임을 인지하기&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;이렇게 서로를 평등한 관계로 정의하고나면 이제 기업은 “고용주”가 아닌 나의 능력을 구매해주는 “고객”이 된다. 애초에 기업은 내 노동력과 기술력을 사준 대상이지 나라는 인간 자체를 산 것이 아니니 주인이라고 할 수도 없다.&lt;/p&gt;
&lt;p&gt;물론 노동시장의 특성 상 판매하는 상품인 노동력과 판매자인 노동자가 분리될 수 없다는 점과 노동력을 제공하고 있는 시간 동안은 구매자인 기업에 의해 내 자유가 억압당할 수 있다는 점으로 인해 스스로를 노비라고 느끼는 분들도 있겠지만, 한번 잘 생각해보자.&lt;/p&gt;
&lt;p&gt;사실 우리가 회사에 취업하는 것이나 유명한 스포츠 스타나 학원 강사가 고액 연봉을 받고 특정 구단이나 학원으로 입단하는 것은 크게 다르지 않다. 어차피 돈 받고 타인에게 내 능력을 제공하는 계약을 체결하고 그 능력을 제공하는 동안은 자유가 억압당한다는 사실은 똑같기 때문이다.&lt;/p&gt;
&lt;p&gt;심지어 스포츠 스타나 학원 강사는 하루 8-10시간 정도 일하면 계약 조건을 만족시키고 퇴근할 자유가 있는 대다수의 직장인에 비해 업무 강도도 높은 편이다.&lt;/p&gt;
&lt;p&gt;하지만 그런 사람들을 보고 우리는 구단주나 학원의 노비가 아닌 프로페셔널이라고 한다. 똑같이 돈을 받고 타인에게 능력을 제공하는데도 직업이 직장인이면 노비이고 스포츠 스타면 프로페셔널이라고 하는 것은 다소 이상한 논리이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/b918a/3hours.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC6ElEQVR42iWSy2tcZRjGD+jCleBSxIW2ohmmycxkMsxkMuNccs6Zc7/NOTNzppncTNLRNp1QrRSzCLaNUFovGEUUwViIdCFaisFesF5Su6h0kVUFQfwDCi50KT+/TBcPfIvv/X3P+3yPFHtZBu1D9KME03KNUrXOVKXKeC7HSCJJInmESpDF6BRoz08xt6agt6pU6hqKbtIwbTozs6wOTtHu9pDils76SpqNY0kCV0UWl6Y1nUKpxNhYmmQ6Q9wtceXSLJfP9tg4E+Evmqi6ixNEOM0WC0vHeP30GRZWXkXS7ADVjpDNiIbtopqGgBpMlsqkUhkBTNPvaNz6ZMDOOz3OnpBZOO5TUyxsL8AVQC9s40cd2kdnkSzP40Cm66LbjgAKhw2dfLFEcjRNenyc9eVFrr73Fl+d73HuNZ1mzxB3LEzbE9AQP+wQtru04hkkw3E5kCZgDcum3tCI/IDAsKhOTnE4keBkM+S78+t8/kZAs1EW7mtoIjvddLHc5tBlIBxGra4AWg669QimGsKd2sAW5w9Pr7IUeOhi4ORKnwtLITvnltn+7CM6YrV8vkRDszCsA5dNvEBAhVNJM2weyRJBm8iqhq5b3Hj3bXbf3+Te3m/sfrvLxRMxP2xf4L9//uXhw7/5dPuLIUzTbSzbxxEPe36EJKv6EKKK3BQhWVFEbWTWYp9rWxe5u3efO7d/5acvP2Z/7xcePPiL/bv73Ln0DV2/K+qjiFlTgK2hpEpNoTatiRXKpFM5JidLFMtVTs2FbHgxX+9c5db122xvbfHjzZ/5/Y8/ufLBZTaf8HDTMoVqhZfLdSpVmVpdRnLCeaKjfUZeGmM8k0MVueSyWYL6FMpEAUcE3+nEhAd9m3tFdHKG2ZTO5lPiM5J1UoUchXxxaCRfLCMFrXmcaI4joyn6x1fZ/f4ma4MBtdERDj33Is8/c5jYDVleFLBpm4nHnqb4+LO8+aSO+UKZkcwYmUyWVHYCZyLD/+qCwmwngweRAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;3hours&quot; title=&quot;&quot; src=&quot;/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/6af66/3hours.png&quot; srcset=&quot;/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/69538/3hours.png 160w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/72799/3hours.png 320w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/6af66/3hours.png 640w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/d9199/3hours.png 960w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/21b4d/3hours.png 1280w,
/static/8e3c67ff3ff3aaa10d73f7e7815e6b13/b918a/3hours.png 2780w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    솔직히 연 130억 버는 이지영 강사의 근무 환경은 왠만한 직장인들보다 훨씬 빡세다.&lt;br&gt;하지만 그 누구도 이 분에게 학원의 노비라고 할 수는 없을 것이다.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;하지만 어차피 우리가 직장인으로 사는 이상 나의 노동력을 타인에게 제공하고 그 대가로 보상을 받는다는 계약을 맺어야 한다는 사실 자체는 변하지 않는다. 다만 똑같은 현상을 보고도 내가 노비라고 생각하면 노비인 것이고, 능력을 갈고 닦아 고객을 만족시켜야 하는 프로페셔널이라고 생각하면 프로페셔널이 된다.&lt;/p&gt;
&lt;p&gt;필자는 &lt;strong&gt;모든 직장인은 자신의 능력을 대가로 보상을 지급받는 프로페셔널&lt;/strong&gt;이며 단 한 사람의 아마추어도 존재하지 않는 것이라고 말하고 싶다.&lt;/p&gt;
&lt;h3 id=&quot;우리의-고객들은-돈에-미쳐있다&quot; style=&quot;position:relative;&quot;&gt;우리의 고객들은 돈에 미쳐있다&lt;a href=&quot;#%EC%9A%B0%EB%A6%AC%EC%9D%98-%EA%B3%A0%EA%B0%9D%EB%93%A4%EC%9D%80-%EB%8F%88%EC%97%90-%EB%AF%B8%EC%B3%90%EC%9E%88%EB%8B%A4&quot; aria-label=&quot;우리의 고객들은 돈에 미쳐있다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;앞서 필자는 우리는 모두 돈을 받고 타인에게 나의 기술과 능력을 제공하는 프로페셔널이자 판매자이며 기업은 우리의 고객이자 구매자라고 이야기했다.&lt;/p&gt;
&lt;p&gt;그러니 가장 먼저 우리는 우리의 고객들인 기업이라는 집단이 무엇을 위해 존재하는 것인지, 이 집단의 목표는 무엇인지에 대해서 명확하게 이해할 필요가 있다.&lt;/p&gt;
&lt;p&gt;자그마한 MVP를 만들 때조차 사용자들의 페르소나와 행동 패턴, 니즈 등을 알아내기 위해서 그렇게 난리 부르스를 치는데 정작 나의 능력을 사주는 중요한 고객들에 대해서는 잘 모른다면 그게 더 이상하지 않을까?&lt;/p&gt;
&lt;p&gt;필자는 기업이 어떤 집단인지에 대해서 딱 한 문장으로 명쾌하게 정리할 수 있다. 기업이라는 집단은 바로…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💰 &lt;strong&gt;돈을 벌기 위한 집단&lt;/strong&gt;이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
&lt;/center&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b59c02f9579a4c68f819893ea391f1db/131f1/of_course.webp&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmgAAABXRUJQVlA4IFwAAABwAwCdASoUAAsAPtFWo0uoJKMhsAgBABoJZwDLLA6txFN1AvAA/tTKt0VjlQLiE/Sva1I/x9Q/Vtoofwt8vNkc8YEfqkw38U9SAkQK5LKmA6lLA1XLFdeZCK0AAA==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;of course&quot; title=&quot;&quot; src=&quot;/static/b59c02f9579a4c68f819893ea391f1db/0ba47/of_course.webp&quot; srcset=&quot;/static/b59c02f9579a4c68f819893ea391f1db/60a22/of_course.webp 160w,
/static/b59c02f9579a4c68f819893ea391f1db/4c812/of_course.webp 320w,
/static/b59c02f9579a4c68f819893ea391f1db/0ba47/of_course.webp 640w,
/static/b59c02f9579a4c68f819893ea391f1db/131f1/of_course.webp 900w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;아니 그걸 누가 모르냐고&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;꽤나 거창하게 이야기했지만 사실 기업이라는 집단이 돈을 벌기 위해 존재한다는 사실은 지나가는 초등학생도 다 아는 사실이다.&lt;/p&gt;
&lt;p&gt;우리 회사에 투자한 투자자들은 추후 이 기업이 지금보다 더 돈을 많이 벌어 더 높은 가치를 가지게 될 것을 기대하고 막대한 금액을 투자한 사람들이며, 자신들의 이익을 위해 투자한 금액이 먼지가 되어버릴 수도 있는 리스크를 안고 판에 뛰어든 사람들이다.&lt;/p&gt;
&lt;p&gt;물론 CEO들 중에서는 기업을 통해 돈보다 자신들의 비전이나 꿈을 실현하는 것을 목표로 삼는 분들도 있지만, 결국 영리 집단을 운영하는 이상 돈을 벌지 않으면 그 꿈을 이룰 수 조차 없다는 사실에는 모두 공감하실 것이다.&lt;/p&gt;
&lt;p&gt;그럼에도 불구하고 굳이 필자가 이렇게 당연한 이야기를 강조하는 이유는 우리가 생각보다 기업이라는 조직이 &lt;strong&gt;돈을 버는 것이 최우선순위인 영리 집단&lt;/strong&gt;이라는 사실을 종종 잊기 때문이다. 바로 이 사실을 이해하고 인정하는 것부터가 우리의 고객을 이해하기 위한 첫 걸음이다.&lt;/p&gt;
&lt;p&gt;왜냐하면 기업은 돈을 벌어야만 하는 집단이기 때문에 돈이 될 것이라고 생각되지 않으면 절대 우리를 채용하지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;결국 기업이 우리와 1년 어치의 연봉을 계약하는 행위는 작게는 몇 천만원 크게는 몇 억원 규모의 선물 투자를 하는 것이나 마찬가지이다. &lt;small&gt;(선물 계약에 대해서 잘 모른다면 &lt;a href=&quot;/2021/12/04/what-is-stock-options/#%EB%B2%88%EC%99%B8-%EC%98%B5%EC%85%98option%EA%B3%BC-%EC%84%A0%EB%AC%BCfuture%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C&quot;&gt;개발자가 알아야 할 스톡옵션의 모든 것 포스팅&lt;/a&gt;을 한번 보고 오자)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그러니 여러분이 어떤 기업과 연봉 8천만원짜리 고용계약을 맺었다면, 당연히 그 이면에는 여러분이 1년 동안 기업에 벌어다 줄 금전적/비금전적 가치가 8천만원 이상일 것이라고 기대하고 있다는 사실이 숨어있다. 애초에 기업은 우리의 행복이나 워라밸보다 돈을 버는 것이 최우선 목표인 집단이라는 사실을 잊지말자.&lt;/p&gt;
&lt;p&gt;쉽게 말해 기업은 사람을 채용할 때 투자의 개념으로 접근하게 된다는 것이며, 이는 결국 투자수익률인 **ROI(Return On Investment)**를 본다는 것이다.&lt;/p&gt;
&lt;p&gt;이때 기대하는 비금전적 가치에는 조직 문화 빌딩이나 조직의 역량/행복도 향상 같은 것들이 포함될 수 있는데, 이 또한 결과적으로는 조직이 지속적으로 높은 생산성을 유지하여 기업의 이익을 만들어내기 위함이다. 만약 기업이 직원들의 행복도만 우선시하여 챙겨주느라 정작 돈도 못 벌고 망해버린다면 직원도 직장을 잃게 되니 결국 기업이 돈을 못 벌면 회사와 직원 모두에게 손해이다.&lt;/p&gt;
&lt;p&gt;이것이 바로 우리의 능력과 노동력을 구매하는 고객들의 본질이며, 우리가 프로페셔널로써 고객들을 만족시키기 위해 반드시 알아둬야 할 팩터이다.&lt;/p&gt;
&lt;p&gt;그러니 결국 우리는 고객들에게 내 노동력을 높은 가격에 팔기 위해서 “나는 내 연봉만큼, 혹은 내 연봉보다 더 큰 이익을 회사에 안겨다 줄 수 있다”라는 사실을 어필해야 하는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;판매-전략을-고민해보자&quot; style=&quot;position:relative;&quot;&gt;판매 전략을 고민해보자&lt;a href=&quot;#%ED%8C%90%EB%A7%A4-%EC%A0%84%EB%9E%B5%EC%9D%84-%EA%B3%A0%EB%AF%BC%ED%95%B4%EB%B3%B4%EC%9E%90&quot; aria-label=&quot;판매 전략을 고민해보자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;그렇다면 우리는 고객인 기업들에게 내 연봉 이상의 돈을 벌어다 줄 수 있다는 사실을 어떻게 어필할 수 있을까?&lt;/p&gt;
&lt;p&gt;사실 굉장히 어려운 문제이다. 왜냐하면 인간의 능력이라는 것이 무슨 삼국지 게임마냥 숫자로 딱 떨어지게 나타내기 굉장히 어렵기 때문이다. 그렇기 때문에 노동시장에서의 구매 결정 과정은 정량적 데이터보다는 주로 커피챗, 면접, 레퍼런스 체크, 인지도와 같은 정성적인 데이터들에 의해 흘러가게 된다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1625608a5b50569e606c847c8b9d5e3e/748f4/jojo.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 86.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEBElEQVR42iWUyXLbRhCG+QQ5WC7TVlzWSnMRTYo7CUAECGIhCYIrwAWkSEqyZafiisuxdXDlkpQrl+Scyjl5gDxGXutLSzlMobsx09P/3/1PrOH5NLo+KdUgoVuo/ghrGnKkGahOl2RV5bBYJ1XT2D+vcK6bKBI/qTcptbvUHY+q3SOtmpw2LoglqhqH+SovcmWSNZWsanFSrLF/VmA/leegrPFSM0lrbRJqi6xhc252yMrKScJSZ0C5OxS79+DHDl+kOXqS4GQ/RTGVJp+uiZ3gOJ7i6eOjh43KfE49CGgs5vSWK5ztjmYUoUVLrMtLotUaYzLFWW+JJRN5sgdpjr89xameMTNyHMTjpF+ccfAsQUHgqMsFlekEYxbyaT3D9SW2jmiu15jrFcHiipbQ1I7WAvk4R/llhmrmiD/fj/j3t3d0C6do5ykqGVnCrzKP6F294fb2B36/jnir9ck3dPTZAmu5YbxZYy+W/1dYPMtjN5Ise6f883nG3x/nrKw0Ey9FW5WEvSGKHOy9+Y7Vl698/vEzP4V3mAWLxmQsSXYE2znucvlgx7pOjombZjMx+ON7j3EtxdI+5XaR4aKS5NwSeIsFpYGHfjfj3a9rvn7sY+gKmkBuby7pXu1whMfe7oZYuZxju/nCp7u/uLu55HZYJXvyHLeZwbMy0sE+yjKiEUypbXVa2wI3NyUGqxGGNMfZ7fA3N5jzpSR8Tex9kOOXD6+52v5MoRCw7qlUsjkePU7K9zmKLxwKHOVyiRGt0KXLzWiDuxOIVxHWZsv65pqOdL3/kPCtz1Ukg5or8eiwSKVRR23qPDnOcpw8IS+zVfQnlP0plfGM+nQm3M2ojkKUcCWXbIW7a/T5CnWyJKZMr7HnH3jVHrBXqslSeFxWeSZK2Ks0+eZVlb1zhXj5gqfix2XQ47InLuo5UNukbJ+k5ZGQeT1uOsRaYSDEW5QMi6rpUpZvThRRMhzyoo681qIo6ijfq0NpUrM6VNsdiiLBkuxvCMdneptkXSclioq9tIeUuh79MMSfLNBsD0Pk1B0FtHsj3MEE2xuJH9IR2+mPH/71hgGmN6QzCWl2fEwZr2S1SexEys1bPt5oRlc40uw+mtPHkoOOHAqkAfcX+NM5neEUW+KuxIezFV6woCucuhJ3B2N5QAxiOW9CVSow75ds1uT1cGTDvW9LM3w55A4Cmm7/IXFHkulSkSJIHKlU7wqacShyHJO/sIjp69f0FysGowmd8RxLYPWk0o5AbMsF94n9YIkr/iCMpJqQujSgpLvCryVJbHJKi1cixYysmHv9jtHl7gGOO42wxwscab85mGH4AdZoji3cmoMQW2zTD9HFNuR/WTpcEYrKLWlSyyXXcvgPDLhoz6iBTpsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;jojo&quot; title=&quot;&quot; src=&quot;/static/1625608a5b50569e606c847c8b9d5e3e/6af66/jojo.png&quot; srcset=&quot;/static/1625608a5b50569e606c847c8b9d5e3e/69538/jojo.png 160w,
/static/1625608a5b50569e606c847c8b9d5e3e/72799/jojo.png 320w,
/static/1625608a5b50569e606c847c8b9d5e3e/6af66/jojo.png 640w,
/static/1625608a5b50569e606c847c8b9d5e3e/748f4/jojo.png 656w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;삼국지 게임처럼 인간의 능력치를 정확한 숫자로 표현할 수 있다면&lt;br&gt;애초에 면접이라는 과정이 필요 없었을 수도 있지 않을까?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;결국 앞서 이야기한 쿠팡의 예시와 같이 우리의 고객들은 상품을 직접 써보기도 전에 대략적인 상품의 정보들만 가지고 구매를 결정해야하는 상황에 놓인다는 것이며, 이것이 바로 노동시장에서 판매자가 거의 유일하게 유리한 위치를 점할 수 있는 지점이라고 봐도 좋다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 판매자인 우리는 구매자들에게 내가 제공할 상품의 정보를 어떻게 알리고 브랜딩할지와 같은 판매 전략에 대해서 정말 많은 고민을 해야 한다.&lt;/p&gt;
&lt;p&gt;이러한 판매 전략을 만들어나가려면 먼저 내가 시장에 제공할 상품의 가치를 파악하는 과정이 필요하다. 일단 내가 가진 상품의 강점과 그 강점이 가진 가치를 알고 있어야 어떤 점을 강조할 지, 어떤 점을 포장할 지와 같은 판매 전략을 짤 수 있을테니 말이다.&lt;/p&gt;
&lt;p&gt;내 상품의 가치를 알기 위해 나의 강점이나 약점이 무엇인지에 대해서 스스로 고민해보는 부분도 필요하겠지만, 사실 그것보다 더 쉬운 방법은 직접 시장에 나가서 그냥 내 능력을 한번 팔아보는 것이다.&lt;/p&gt;
&lt;p&gt;애초에 시장에서 형성되는 품질에 대한 기준은 상대적이다. 수요에 비해 공급이 많이 부족한 상황이라면 낮은 품질의 상품이라도 비싼 값을 주고 살 수도 있으며, 반대로 수요가 별로 없는데 공급은 넘쳐나는 상황이라면 더 높은 품질의 상품을 요구할테니 말이다.&lt;/p&gt;
&lt;p&gt;그러니 집에 가만히 앉아서 내 상품의 가치를 올릴 전략을 고민하는 것보다는 그냥 필드에 나가서 직접 고객에게 판매 시도를 한 이후 고객의 리액션이나 제시받은 가격 등을 보면 더 빠르게 현재 시장에서 바라보는 내 상품의 가치에 대해서 알아낼 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 성장을 고민하는 분들에게 “다양한 개발자를 많이 만나보세요”, “면접은 떨어지더라도 무조건 많이 보고 자주 보는 것이 이득이다”라는 이야기를 해드리고는 한다.&lt;/p&gt;
&lt;p&gt;특히 면접을 자주 보는 것은 여러번 얘기해도 부족하지 않을 정도로 중요한데, 이 과정에서 현재 노동시장의 트렌드도 알 수 있고 면접 때 제대로 답변하지 못 한 것들을 토대로 내 상품의 하자가 무엇인지도 알 수 있으며, 심지어 면접에 통과하여 오퍼를 받게 된다면 시장에서 평가한 내 상품의 가격에 대해서도 알 수 있기 때문이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/e5166/interview.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 52.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwABAv/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHVHlUjk//EABwQAAICAgMAAAAAAAAAAAAAAAECAxMEEhQhMv/aAAgBAQABBQK4IZsldJO3mUcdVFx9f//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB0QAAMAAQUBAAAAAAAAAAAAAAABESECAyJCUmH/2gAIAQEABj8C2r4RxefgxOZiNKnaDP/EABsQAQADAAMBAAAAAAAAAAAAAAEAESExUbGR/9oACAEBAAE/Iai0BHe5zjREtzKIs2ZexX8gaSlUdyeTyf/aAAwDAQACAAMAAAAQ4N//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QkY//xAAXEQEAAwAAAAAAAAAAAAAAAAAAAREh/9oACAECAQE/EJ1b/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBYVFxwf/aAAgBAQABPxCz1QsBQPTqLWd2NAeemNJqJfhB+xaX1/NcJfTaBRprMzurFMHSf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;interview&quot; title=&quot;&quot; src=&quot;/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/c08c5/interview.jpg&quot; srcset=&quot;/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/0913d/interview.jpg 160w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/cb69c/interview.jpg 320w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/c08c5/interview.jpg 640w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/6a068/interview.jpg 960w,
/static/d38dfcd13f8d28ee989c50f5a7fbb9f5/e5166/interview.jpg 1200w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;직접 네트워킹을 하거나 면접에 참여하는 것은 가장 좋은 시장 조사 방법이다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이렇게 다양한 방법을 통해 내 상품의 가치와 대략적인 가격에 대해서 알았다면, 이제 아래 표를 한번 보도록 하자.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;저품질&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;고품질&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;싸게 팜&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;보상 적음 / 비용 적음&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;그냥 나만 손해임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;비싸게 팜&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;양아치 / 비용 효율적&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;보상이 큼 / 비용이 큼&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;필자는 위 표에서 손해만 보는 “고품질/싸게 팜”을 제외한 나머지는 모두 선택 가능한 전략이라고 생각한다.&lt;/p&gt;
&lt;p&gt;저품질인 상품을 싸게 파는 것은 기업에는 최소한의 노동력만 제공하며 추가적인 보상을 바라지도 않는 조용한 퇴직 같은 상황이나 혹은 일을 시작한지 얼마 되지 않은 분들 같은 케이스일테고, 고품질인 상품을 비싸게 파는 것은 기업의 핵심 인재와 같은 고연봉자들의 케이스라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;조금 특이한 점은 저품질인 상품을 비싸게 파는 세그먼트가 존재한다는 것인데, 이는 그 동안 밀도있는 경험을 하지 못 해서 실력은 부족한데 연차로 인해 연봉은 높은 경우나 브랜딩을 통해 자신의 실력보다 더 멋진 모습으로 비춰지는 경우, 혹은 나에게는 쉬운 일인데 다른 이들이 볼 때는 비용이 많이 드는 일을 하는 경우라고도 볼 수 있다.&lt;/p&gt;
&lt;p&gt;사실 이렇게 싼 물건을 비싸게 팔아 마진을 남기는 것이 장사의 기본이기는 하지만, 노동 시장의 특성 상 판매자와 판매한 상품을 떼어놓을 수가 없으니 혹여라도 상품에 하자가 발생했을 경우 꽤나 난감한 상황이 발생할 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;어차피 과장 광고가 심한 수준이라면 어차피 면접을 진행할 때 혹은 입사 후에 다 들통나게 되어있으며, 또한 과장 광고로 인해 상품의 가치에 비해 도를 넘는 가격을 받았다면 기업들끼리도 다 소문이 나서 어느 순간부터는 더 이상 구매 자체가 발생하지 않을 수도 있다.&lt;/p&gt;
&lt;p&gt;또한 이 세그먼트는 고객 입장에서 가장 ROI가 나오지 않는 거래이니 기업들의 현금 흐름이 좋지 않아지는 경우가 발생하면 비용을 줄이기 위해 가장 먼저 해고 당할 수 있는 위험 또한 존재한다.&lt;/p&gt;
&lt;p&gt;그러니 필자는 노동 시장에서만큼은 저품질의 상품을 비싸게 파는 것보다는 최대한 고품질인 상품을 비싸게 파는 전략을 선택하여 시장의 고객들과 신뢰를 쌓아가는 것이 장기적으로 더 좋은 전략이라고 생각한다.&lt;/p&gt;
&lt;h3 id=&quot;생각보다-더-치열한-노력과-고민이-필요하다&quot; style=&quot;position:relative;&quot;&gt;생각보다 더 치열한 노력과 고민이 필요하다&lt;a href=&quot;#%EC%83%9D%EA%B0%81%EB%B3%B4%EB%8B%A4-%EB%8D%94-%EC%B9%98%EC%97%B4%ED%95%9C-%EB%85%B8%EB%A0%A5%EA%B3%BC-%EA%B3%A0%EB%AF%BC%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%98%EB%8B%A4&quot; aria-label=&quot;생각보다 더 치열한 노력과 고민이 필요하다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;그렇다면 노동 시장에서의 “고품질”이라는 것은 무엇을 의미하는 걸까?&lt;/p&gt;
&lt;p&gt;사실 이 부분은 딱히 정답이랄게 없다. 일반적으로 노동시장에서 고액 연봉을 받는 사람들은 단지 자신의 전문 기술인 하드 스킬만 좋은 것이 아니라 리더십, 커뮤니케이션 스킬, 비즈니스 인사이트, 언변술, 사교술, 정치력 등 다양한 부분에서 두각을 나타내기 때문이다.&lt;/p&gt;
&lt;p&gt;개발자라고 해서 프로그래밍만 잘 해도 된다고 생각했다면 큰 오산이다. 개발자가 프로그래밍을 잘 해야하는 것은 그저 개발자라는 직업으로 적당한 연봉을 받으며 일을 하기 위한 기본기에 불과하며, 그 이상을 바란다면 이제는 프로그래밍이 아닌 것들에 대한 수련이 필요하다.&lt;/p&gt;
&lt;p&gt;물론 인간이 이 모든 것을 완벽하게 하기는 어려우니 자신의 강점과 약점을 명확하게 파악하고 나만의 캐릭터를 구축해나가는 과정이 중요하다.&lt;/p&gt;
&lt;p&gt;이런 캐릭터는 공부로 얻을 수 있는 것이 아니라 시장에서 원하는 인재 수요에 대한 분석, 나 자신의 특성, 캐릭터 자체의 경쟁력 등과 같은 수 없이 많은 고민과 노력을 통해 얻어지는 결론에 가깝다. 그래서 필자가 이 포스팅에서 Silver Bullet과 같은 방법은 없다고 이야기한 것이다.&lt;/p&gt;
&lt;p&gt;이미 치열한 시장 경제 속에서 자신의 가치를 증명하기 위해 죽기 살기로 노력하는 사람들은 널리고 널렸다. 특히 상위의 소수 엘리트와 나머지 인원 간의 보상의 갭이 큰 업계일수록 이러한 성향의 사람들이 더욱 많이 나타나는데, 개인적으로는 스포츠, 예술, 요식 등의 업계에서 이런 모습이 자주 보이는 것 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“진짜로 알아야 할 게, 돈을 받고 일하는 순간부터는 어느 세상이든, 어느 세계든, 어느 직업의 장르이건, 아마추어는 존재하지 않아요. 돈을 받기 시작하면 그때부터 프로가 되는 거예요. 그러면 뭘 어떻게 해야 해? 프로답게 해야지.” - &lt;a href=&quot;https://namu.wiki/w/%EC%97%90%EB%93%9C%EC%9B%8C%EB%93%9C%20%EA%B6%8C&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;에드워드 권&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“중요한 승부에서 패하고도 마음이 아무렇지 않다면 그것은 이미 프로가 아니다. 그것은 인품과 무관하며 승부사에게 패배의 아픔은 항상 생생한 날것이어야 한다. 늘 승자가 될 수는 없지만 패자의 역할에 길들여져서는 안 된다.” - &lt;a href=&quot;https://namu.wiki/w/%EC%9D%B4%EC%B0%BD%ED%98%B8&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;이창호 9단&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“프로가 된다는 것은, 당신이 하고 싶은 모든 일을 당신이 하고 싶지 않은 날에 하는 것을 말한다.” - &lt;a href=&quot;https://namu.wiki/w/%EC%A4%84%EB%A6%AC%EC%96%B4%EC%8A%A4%20%EC%96%B4%EB%B9%99&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;줄리어스 어빙&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“우리가 뭘 해야 하는지 집중해! 너희들 모두 돈 받고 운동하는 거잖아. 이기는 경기를 해! 지지도 말고! 비기지도 마! 제대로 하라고! 그게 내가 원하는 거야. 두려워 하거나 긴장하지 말고 최선을 다하라고! 팀을 위해 너희 자신을 희생해. 우린 롯데 자이언츠야! 최고가 돼야 해!” - &lt;a href=&quot;https://namu.wiki/w/%EC%A0%9C%EB%A6%AC%20%EB%A1%9C%EC%9D%B4%EC%8A%A4%ED%84%B0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;제리 로이스터&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“스포츠에서 2등은 꼴찌나 마찬가지라고 생각합니다.” - &lt;a href=&quot;https://namu.wiki/w/%EC%84%A0%EB%8F%99%EC%97%B4&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;선동열&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 필자가 몸 담고 있는 IT 업계는 업계 1위가 아니더라도 그럭저럭 먹고 살만한 보상이 주어지는 업계이니 저 사람들이 있는 업계만큼 치열한 경쟁이 있지는 않겠지만, 만약 현재 받고 있는 것 이상의 보상을 바란다면 저런 마인드를 가지고 치열하게 노력하고 고민해야 한다는 사실은 변하지 않는다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/57a2f0c10fbf684c1b6233cc9bbf3a34/a8a14/janghoon.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 51.87500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwT/xAAVAQEBAAAAAAAAAAAAAAAAAAACAP/aAAwDAQACEAMQAAAByxYhTAG//8QAGxAAAgEFAAAAAAAAAAAAAAAAAQIDABITMTL/2gAIAQEAAQUCkoouJZQok23CgWf/xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8Bka//xAAWEQEBAQAAAAAAAAAAAAAAAAAAERL/2gAIAQIBAT8BtYf/xAAbEAACAQUAAAAAAAAAAAAAAAAAAREQISJBgf/aAAgBAQAGPwLcCZGXKqx//8QAHBAAAgICAwAAAAAAAAAAAAAAAREAITFhEEFR/9oACAEBAAE/IXT7KcEANoO4glHDyDcKaGPNz//aAAwDAQACAAMAAAAQLz//xAAWEQEBAQAAAAAAAAAAAAAAAAABACH/2gAIAQMBAT8QzYd//8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/ENAZG3//xAAcEAEBAAICAwAAAAAAAAAAAAABEQAhMVFBYdH/2gAIAQEAAT8QEC1m5Z7zkCjY28k8YQHoKHGbG738wAIAjWMCVW0ds//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;janghoon&quot; title=&quot;&quot; src=&quot;/static/57a2f0c10fbf684c1b6233cc9bbf3a34/c08c5/janghoon.jpg&quot; srcset=&quot;/static/57a2f0c10fbf684c1b6233cc9bbf3a34/0913d/janghoon.jpg 160w,
/static/57a2f0c10fbf684c1b6233cc9bbf3a34/cb69c/janghoon.jpg 320w,
/static/57a2f0c10fbf684c1b6233cc9bbf3a34/c08c5/janghoon.jpg 640w,
/static/57a2f0c10fbf684c1b6233cc9bbf3a34/a8a14/janghoon.jpg 885w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;프로페셔널은 항상 냉정하게 자신을 평가하고, 내 고객들을 더 만족시킬 수 있도록 뼈를 깎는 노력을 해야한다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;나 스스로를 단순한 노동자가 아닌, 내 능력과 기술을 시장에 팔아먹는 프로페셔널로 정의하고나면 내 주변에서 발생하고 있던 수 많은 현상들에 대한 시각도 조금씩 변하기 마련이다.&lt;/p&gt;
&lt;p&gt;주변을 돌아보았을 때 나와 같은 일을 하고 있는 것 같은 동료가 나보다 더 높은 연봉을 받고 있는 것 같다면 그 동료의 커리어와 내 커리어를 비교 분석하거나 혹시 그 동료가 내가 모르는 역량을 보유하고 있지는 않은지 확인해서 나의 발전 방향을 다시 검토해야 한다.&lt;/p&gt;
&lt;p&gt;회사와 연봉 협상을 해야한다면 수동적으로 회사가 내 성과를 알아주기를 기대하는 것이 아니라, 어떻게 하면 타인을 설득하기 쉬운 형태로 내 성과를 표현할지를 고민하거나 적극적으로 시장에 나가 다른 회사의 오퍼도 받아보면서 시장에서 평가받는 내 몸 값이 어느 정도인지도 알아보고 이 정보들을 협상의 무기로 쓸 수 있을지에 대한 고민을 해야 한다.&lt;/p&gt;
&lt;p&gt;이러한 행위를 하지 않는다는 것은 시장에서 장사를 하겠다는 사람이 아무런 홍보 활동도 벌이지 않고 가만히 가게에만 앉아서 손님이 오기를 기다리는 것과 다를 바가 없다. 전단지를 돌리든 새로운 메뉴 개발을 하든 수수료를 지불하고 배달 플랫폼에 들어가든 뭐라도 해봐야 우리 가게를 찾는 손님이 늘 것이고, 손님이 늘어나야 수요/공급의 법칙에 따라 음식 가격을 더 올릴 수 있지 않겠는가?&lt;/p&gt;
&lt;p&gt;사람들은 연 130억을 버는 학원 강사를 부러워하면서도, 생각보다 그 이면에 있는 치열한 노력과 고민에는 초점을 맞추지 않는다.&lt;/p&gt;
&lt;p&gt;하지만 세상에 공짜는 없는 법이다. 지름길도 없다. 성공하고 싶다면 그저 꾸준히 내 역량이라는 상품성을 강화하고 구매자들의 니즈를 분석하고 직접 팔아보면서 부딫히고 깨져보는 과정을 겪어야 한다.&lt;/p&gt;
&lt;p&gt;단, 노비가 아닌 프로페셔널로써 말이다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;최근 몇 년간 개발자들의 몸 값이 빠른 속도로 오르기 시작하면서 마치 개발자로 취업만 성공하면 대부분 좋은 복지를 누리면서 높은 연봉도 받을 수 있는 좋은 직업인 것처럼 보여졌었다. 심지어는 최근에도 필자의 지인 중 한 분이 개발 공부를 시작했다는 소식을 들었으니 이런 현상은 아직도 현재진행형인 듯 싶다.&lt;/p&gt;
&lt;p&gt;물론 IT업계가 발전하며 개발자들에 대한 수요가 조금씩 높아지고 있었고 그에 비해 공급이 부족했던 것은 맞다. 필자가 대학생이던 2015년도만 해도 공대의 꽃은 이른바 전화기&lt;small&gt;(전자전기공학/화학공학/기계공학)&lt;/small&gt;였으며 컴퓨터공학과는 딱히 인기가 없었기 때문이다.&lt;/p&gt;
&lt;p&gt;이런 상황에서 특정 기업이 개발자의 연봉을 높여버리며 시장의 개발자들을 대량으로 빨아들이는 전쟁을 시작해버렸고, 당연히 다른 기업들도 좋은 개발자를 데려오고 싶다는 수요에 비해 공급이 턱없이 부족하다는 상황은 알고 있었을테니 그에 맞게 연봉을 높이는 치킨게임에 참여할 수 밖에 없었을 것이다. &lt;small&gt;
(필자는 이것도 일종의 FOMO 현상이었다고 생각한다.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;하지만 2023년 현재는 상황이 많이 다르다. 최근 몇 년간 개발자들의 몸 값이 빠르게 오르며 개발자라는 직업에 대한 인식이 좋아졌으니 자연스럽게 과거에 비해 컴퓨터공학과의 위상도 많이 올라가고 부트캠프와 같은 새로운 비즈니스 모델까지 우후죽순 생겨나게 되며 시장에는 개발자 공급이 늘어났다.&lt;/p&gt;
&lt;p&gt;이런 상황에서 갑자기 경기 침체가 와버리니 이번에는 공급에 비해 수요가 부족한 상황이 되어가고 있다. 아직은 개발자에 대한 수요가 많아 보일 수 있지만 자세히 보면 아니다.&lt;/p&gt;
&lt;p&gt;노동력에 대한 가격은 한번 오르고 나면 잘 내려가지 않는 &lt;a href=&quot;https://www.moef.go.kr/sisa/dictionary/detail?idx=2081&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;하방 경직성&lt;/a&gt;을 가지고 있기 때문에 수요가 줄었다고 해서 갑자기 가격을 낮추기 어렵다.&lt;/p&gt;
&lt;p&gt;결국 우리의 노동력을 구매하는 고객들은 수요와 공급에 의해 자연스레 형성되는 적정 가격보다 비싼 가격을 지불하는 것이니, 그만큼 높은 품질의 가치를 지닌 상품들을 선별하게 될 수 밖에 없으며 이 과정에서 해고나 직장을 아예 구하지 못하는 상황과 같은 비자발적 실업이 발생하거나 개발자들의 임금이 양극화 되는 것이다.&lt;/p&gt;
&lt;p&gt;높은 가치의 노동력을 제공하는 판매자는 더 많은 보상을 받지만, 낮은 가치의 노동력을 제공하는 판매자는 아예 구매자가 나타나지 않거나 혹은 기존보다 더 낮은 가격을 제시받는다는 의미이다. &lt;small&gt;(1억원으로 역량이 낮은 인원 3명을 고용하느니, 차라리 역량이 높은 1명을 고용하며 1억원을 몰아주는 것을 선택하기 쉽다는 것이다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이러한 시장의 변화는 개발자들, 특히 그 중에서도 이제 막 커리어를 시작하려는 분들에게는 굉장히 중요한 포인트이다.&lt;/p&gt;
&lt;p&gt;주식 시장만 보면 마치 경기가 살아나고 있는 것 같지만 아직 해결된 것은 아무것도 없으며, 모두가 힘들고 어려운 시장 상황이다. 필자는 이런 상황에서 “성실하게 노력하면 보상은 자연스레 따라올거야”라는 말을 도저히 할 수 없을 것 같다. 이건 경기가 좋았을 때나 먹히는 말이지 지금은 아니다.&lt;/p&gt;
&lt;p&gt;하지만 이렇게 급변하는 시장 상황 속에서도 TypeScript, React, Next를 공부하면 취업이 잘 된다거나, 요즘에는 Rust가 대세라는 등의 이야기는 많지만 정작 이런 현실적인 이야기를 해주는 사람은 별로 없는 것 같다. 왜 그런지는 잘 모르겠다.&lt;/p&gt;
&lt;p&gt;필자는 물론 기술도 중요하지만 일단 안정적인 삶을 갖춰야 우리가 좋아하는 기술도 즐길 수 있다고 생각한다. 생존을 위한 학습이 아니라 내 지적 만족감이나 호기심 충족을 위한 학습을 하는 것이 스스로에게도 더 건강한 성장이 될테니 말이다.&lt;/p&gt;
&lt;p&gt;필자는 많은 개발자들이 스스로 개발자이기 이전에 한 명의 직장인이고 시장 참여자라는 사실을 잊지 말고, 노동시장을 바라보는 냉철한 시각을 통해 요즘과 같은 어려운 상황에서도 나름의 분석과 대처를 할 수 있는 능력을 갖추길 바란다.&lt;/p&gt;
&lt;p&gt;이상으로 시장에서 살아남는 사람이 되기 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[What Is Abstraction, Really?]]></title><description><![CDATA[In this post, I want to talk about abstraction. Abstraction occupies an important place not just in application design but across all of computer science. Yet the concept of abstraction is itself so abstract that many developers who are just starting out find themselves deeply confused by it. Abstraction shines especially when you need to build something with a complex structure, making it an essential concept when designing large, complex applications.]]></description><link>https://evan-moon.github.io/2023/01/15/what-is-abstract/en/</link><guid isPermaLink="false">20230115-what-is-abstract-en</guid><pubDate>Sun, 15 Jan 2023 12:39:39 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I want to talk about abstraction. Abstraction occupies an important place not just in application design but across all of computer science. Yet the concept of abstraction is itself so abstract that many developers who are just starting out find themselves deeply confused by it.&lt;/p&gt;
&lt;p&gt;Abstraction shines especially when you need to build something with a complex structure, making it an essential concept when designing large, complex applications.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;I briefly mentioned abstraction in my earlier posts &lt;a href=&quot;/2019/08/24/what-is-object-oriented-programming/#%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5%EC%9D%B4%EB%9D%BC%EB%8A%94-%EA%B2%83%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EC%9D%98%EB%AF%B8%ED%95%98%EB%82%98%EC%9A%94&quot;&gt;A Fun Look at Object-Oriented Programming&lt;/a&gt; and &lt;a href=&quot;/2019/12/15/about-functional-thinking/&quot;&gt;Functional Thinking That Breaks Conventional Mindsets&lt;/a&gt;, but since abstraction isn’t a concept limited to OOP and wasn’t the main topic of those posts, I didn’t go deep into it.&lt;/p&gt;
&lt;p&gt;Many people understand abstraction only as “extracting common elements.” Strictly speaking, this isn’t wrong — but it’s just one specific technique for defining something abstract. It doesn’t explain what abstraction fundamentally is.&lt;/p&gt;
&lt;p&gt;If you try to understand abstraction from this angle, when someone asks “Why is abstraction needed in programming?”, you’ll only be able to give a narrow answer like “You can extract common parts to improve reusability.” &lt;del&gt;&lt;em&gt;(This is actually a question I frequently ask in interviews.)&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;To properly understand abstraction, you need to step away from programming’s definition and think from the ground up about what abstraction fundamentally is and why we need it.&lt;/p&gt;
&lt;h2 id=&quot;expressing-complex-things-simply&quot; style=&quot;position:relative;&quot;&gt;Expressing Complex Things Simply&lt;a href=&quot;#expressing-complex-things-simply&quot; aria-label=&quot;expressing complex things simply permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s start from the most fundamental question: what exactly is abstraction?&lt;/p&gt;
&lt;p&gt;As you know, the term “abstraction” isn’t exclusive to programming. It’s used in mathematics and programming, but also in art and architecture. The most famous abstract painter is, of course, Picasso.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 560px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d79c5756053bcba4a159e4af28a84bb6/9342c/optimize.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB6tTmYZBgo//EABoQAAIDAQEAAAAAAAAAAAAAAAECAwQTABL/2gAIAQEAAQUCrhcfKddAE8Mi46r1pg8v/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHRAAAQQCAwAAAAAAAAAAAAAAAAECESEyUTGRof/aAAgBAQAGPwJktTjRg3opIoakmXhKaP/EABwQAQACAQUAAAAAAAAAAAAAAAEAETFBUWGR8f/aAAgBAQABPyG3JdwngJUCFcEIoiGozjdpeWyk/9oADAMBAAIAAwAAABDEP//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxCYr//EABcRAAMBAAAAAAAAAAAAAAAAAAABETH/2gAIAQIBAT8QdosP/8QAHRABAAICAgMAAAAAAAAAAAAAAQARUYEhMUFh8P/aAAgBAQABPxB7mC1C7i4/dqBrEKIL5xK0AUV59RI51w6iAukzmf/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;optimize&quot; title=&quot;&quot; src=&quot;/static/d79c5756053bcba4a159e4af28a84bb6/9342c/optimize.jpg&quot; srcset=&quot;/static/d79c5756053bcba4a159e4af28a84bb6/0913d/optimize.jpg 160w,
/static/d79c5756053bcba4a159e4af28a84bb6/cb69c/optimize.jpg 320w,
/static/d79c5756053bcba4a159e4af28a84bb6/9342c/optimize.jpg 560w&quot; sizes=&quot;(max-width: 560px) 100vw, 560px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Picasso&apos;s drawing that removes all complexity from a bull and leaves only its most essential features&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;As you can see, an abstracted subject emphasizes the features that represent the subject’s essence. In simpler terms, individual details are stripped away and the characteristics that define the subject itself are strengthened.&lt;/p&gt;
&lt;p&gt;Picasso’s bull drawing can correspond to anything that has the essence of “bull.” Whether it’s a dairy cow, a Korean hanwoo, or a charging bull — none deviate far from that form. In reality these bulls all look different, but they don’t stray from the essential form of what a bull is: four legs and horns on the head.&lt;/p&gt;
&lt;p&gt;It’s like how every individual human has a different face, voice, and personality, but fundamentally we all have two arms, two legs, and one head. That’s the essence of the subject.&lt;/p&gt;
&lt;p&gt;When you express only the essence and remove the details, the expression inevitably becomes simple. Something that expresses only 10 core features is naturally simpler than something expressing 100 granular ones.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 394px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7a4c375ac990f976ecd9ebcade7cc3b3/cc097/zolaman.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 108.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAAsTAAALEwEAmpwYAAABAElEQVR42s2V2QqEMAxF/f+/89EPcF/rjluGW4gMjG1t9WECwVDhcJutHhnsOI7LWGUevWxa4L7vVNc1JUlCaZrKGGdOwHVdKYoi6rpOXhXetq0827bNHghF4zj+5K7ve8rz3A4IBQCqioIUqAp0CZznmYqiUFbdGgiL4/jMFQrBAMT4Z53Dpmkuc5VlmSyOqi+1bcNQOFIAF0I860Mo8n2fgiCQsWlatEAoQoGqqpJftFFZlu5AVgPwMAzvjB4MqqZpurUgbilEm/BVHwFZJeY3DEPjYtACWQmUYX7hPD06lVqFy7KcM80LA2fOV8bofa8qrDTnfWh6Dv7jCXABfgBbGs0YyiN/PwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;zolaman&quot; title=&quot;&quot; src=&quot;/static/7a4c375ac990f976ecd9ebcade7cc3b3/cc097/zolaman.png&quot; srcset=&quot;/static/7a4c375ac990f976ecd9ebcade7cc3b3/69538/zolaman.png 160w,
/static/7a4c375ac990f976ecd9ebcade7cc3b3/72799/zolaman.png 320w,
/static/7a4c375ac990f976ecd9ebcade7cc3b3/cc097/zolaman.png 394w&quot; sizes=&quot;(max-width: 394px) 100vw, 394px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    Expressed with just a circle and five lines, yet no one would mistake this for a dog or cat.&lt;br&gt;
    This is an abstracted representation that captures the subject&apos;s essence.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Ultimately, an abstracted subject is “a simplification that retains only the core features of something complex and removes the rest.” Like the paintings of abstract artists who use simple shapes to express complex things — emotions, animals, objects — simplifying them and emphasizing only what’s essential.&lt;/p&gt;
&lt;p&gt;And these generalized core features inevitably become what these entities have in common. That’s why OOP guides you to extract common features from objects and define classes.&lt;/p&gt;
&lt;p&gt;If I removed the circle from my stick figure drawing, you wouldn’t know if it was a rocket, an arrow, or a headless human. Because any living human is generally expected to have a head in that position. The position and shape of the head is a defining commonality that all humans share.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ce0b65b1961f895989162cd9111bf383/eea4a/headless.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 91.25000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAMCBAH/xAAXAQEBAQEAAAAAAAAAAAAAAAACAQAD/9oADAMBAAIQAxAAAAG855O0oC5Og5r0S//EABsQAAICAwEAAAAAAAAAAAAAAAABERIDEBMx/9oACAEBAAEFArDyQ+hYoQLxa//EABYRAQEBAAAAAAAAAAAAAAAAABIAEP/aAAgBAwEBPwEQ3//EABcRAAMBAAAAAAAAAAAAAAAAAAABExD/2gAIAQIBAT8BqVY8/8QAGBAAAwEBAAAAAAAAAAAAAAAAARARACH/2gAIAQEABj8C0jpPWF//xAAdEAACAgEFAAAAAAAAAAAAAAAAAREhMUFRYXGh/9oACAEBAAE/IYb+FZZuJOrOJZuwEkUYhmNWf//aAAwDAQACAAMAAAAQLCdA/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEQETH/2gAIAQMBAT8QRqLY/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREg/9oACAECAQE/EGDG/8QAHBABAAIDAQEBAAAAAAAAAAAAAQAhETFBcVHR/9oACAEBAAE/EDgj1fkJtwvMewCZWz0GZtXyRVYABujnkKDTybn2Yl2273Mux3P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;headless&quot; title=&quot;&quot; src=&quot;/static/ce0b65b1961f895989162cd9111bf383/c08c5/headless.jpg&quot; srcset=&quot;/static/ce0b65b1961f895989162cd9111bf383/0913d/headless.jpg 160w,
/static/ce0b65b1961f895989162cd9111bf383/cb69c/headless.jpg 320w,
/static/ce0b65b1961f895989162cd9111bf383/c08c5/headless.jpg 640w,
/static/ce0b65b1961f895989162cd9111bf383/6a068/headless.jpg 960w,
/static/ce0b65b1961f895989162cd9111bf383/eea4a/headless.jpg 1280w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Nobody would look at this photo and think it looks natural&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Stripping away everything except the core features of a complex subject and expressing it simply. That is the essence of abstraction.&lt;/p&gt;
&lt;h2 id=&quot;why-does-programming-need-abstraction&quot; style=&quot;position:relative;&quot;&gt;Why Does Programming Need Abstraction?&lt;a href=&quot;#why-does-programming-need-abstraction&quot; aria-label=&quot;why does programming need abstraction permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I described abstraction as the act of stripping away everything except the core features of a complex subject and expressing it simply.&lt;/p&gt;
&lt;p&gt;So why do we need this in programming? We’re not artists like Picasso, grasping the essence of objects and expressing them artistically.&lt;/p&gt;
&lt;p&gt;The answer is actually very simple:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;To build more complex and difficult things.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;abstraction-enables-building-more-complex-things&quot; style=&quot;position:relative;&quot;&gt;Abstraction Enables Building More Complex Things&lt;a href=&quot;#abstraction-enables-building-more-complex-things&quot; aria-label=&quot;abstraction enables building more complex things permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As I mentioned, an abstracted subject takes on a very simple form because it expresses only the most essential features from its original characteristics. The key point here is “expressing something that’s actually complex in a simple way.”&lt;/p&gt;
&lt;p&gt;One difference between artistic and industrial abstraction: in art, abstraction &lt;em&gt;removes&lt;/em&gt; the complex parts, while in industry, abstraction &lt;em&gt;hides&lt;/em&gt; them.&lt;/p&gt;
&lt;p&gt;In other words, by hiding concrete, complex implementation behind a simple form, you enable users of your module, component, or product to utilize its functionality without needing to understand the underlying principles.&lt;/p&gt;
&lt;p&gt;Take the computers we use in daily life. Very few people understand the principles down to the semiconductor level, and even elementary school students who don’t know what a CPU is can use a computer. We can abstract “computer” as “a device you operate with a keyboard and mouse to see results on a monitor or speaker” — and that’s sufficient for use. There’s no need or reason to understand every detail of how a computer works.&lt;/p&gt;
&lt;p&gt;A person using Photoshop to edit photos just needs to focus on how to use Photoshop. They don’t need to know how the program works internally or how the OS allocates resources to its process.&lt;/p&gt;
&lt;p&gt;If a Photoshop user had to worry about all of that, wouldn’t “editing a photo in Photoshop” become prohibitively difficult and complex?&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/164a4e620bcf57d8857f4541b3fbe14b/6a068/photoshop.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAf/EABQBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAY6INFwoT//EABsQAAICAwEAAAAAAAAAAAAAAAABAhEDEiFB/9oACAEBAAEFAoSWrUVi6VR4f//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPwERf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAMAAwAAAAAAAAAAAAAAAAEQEQAhMf/aAAgBAQAGPwI3uE3ccX//xAAbEAADAQEAAwAAAAAAAAAAAAABESEAMUFRsf/aAAgBAQABPyEutTEs8PsOdxqfMGN514Ga+zv/2gAMAwEAAgADAAAAEIfP/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAEDAQE/EFDc/8QAFxEBAAMAAAAAAAAAAAAAAAAAARARIf/aAAgBAgEBPxBG8j//xAAeEAEAAgIBBQAAAAAAAAAAAAABESEAQdExUWFxkf/aAAgBAQABPxA3K1IRuaxL352LEa84x1I9eMVp0VYwXaBaWLmvmSubP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;photoshop&quot; title=&quot;&quot; src=&quot;/static/164a4e620bcf57d8857f4541b3fbe14b/c08c5/photoshop.jpg&quot; srcset=&quot;/static/164a4e620bcf57d8857f4541b3fbe14b/0913d/photoshop.jpg 160w,
/static/164a4e620bcf57d8857f4541b3fbe14b/cb69c/photoshop.jpg 320w,
/static/164a4e620bcf57d8857f4541b3fbe14b/c08c5/photoshop.jpg 640w,
/static/164a4e620bcf57d8857f4541b3fbe14b/6a068/photoshop.jpg 960w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    If editing photos in Photoshop required understanding all the principles of image processing,&lt;br&gt;
    the task would become far too difficult for a single person&apos;s capacity.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The fundamental concept of abstraction is already at work in cars, smartphones, urban infrastructure, administrative systems, and more. Many things we take for granted are the result of complex logic and infrastructure being abstracted away.&lt;/p&gt;
&lt;p&gt;Thanks to abstraction, we can leverage the systems of complex modern society without needing encyclopedic knowledge across every field.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Turn the faucet and clean water comes out → The city’s water supply system is abstracted&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to the municipal office and you can register your residence → The government’s administrative system is divided and abstracted&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Press the accelerator and the car moves forward → The ECU and engine logic handling intake/compression/combustion/exhaust is abstracted&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;The world we live in today is built on layers of abstract concepts. Thanks to this concept of expressing complex things simply, people can focus only on what they’re responsible for, enabling division of labor and the creation of things more complex than ever before.&lt;/p&gt;
&lt;p&gt;The semiconductor manufacturer focuses only on semiconductors. The computer assembler focuses on computers. The Photoshop developer focuses on image processing and programming. The artist focuses on using Photoshop. Because specialists in each field come together, they can build things more vast and complex than any individual could. If one person had to understand all of it to produce a product, even a lifetime of knowledge-building wouldn’t be enough to produce complex products at high quality.&lt;/p&gt;
&lt;p&gt;These benefits of abstraction apply equally to our experience of programming. The software we build is, like products in other industries, an assembly of many small modules contributed by countless people around the world.&lt;/p&gt;
&lt;p&gt;Frontend developers like me mostly use libraries and frameworks like React or Vue to build web applications. Combining these small programs to create complex applications is nothing unusual.&lt;/p&gt;
&lt;p&gt;Honestly, even without knowing the detailed inner workings of a JavaScript engine, knowing the general syntax of JavaScript and how to use the React library is enough to build applications.&lt;/p&gt;
&lt;p&gt;In the past, developers routinely configured Webpack themselves to bundle applications. Now, CLIs like CRA or frameworks like Next.js generate Webpack configurations automatically — and even hide them behind abstractions. Some developers who started recently have never touched Webpack directly. &lt;em&gt;(In practice, you can build typical applications these days without any Webpack knowledge.)&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eefb5d1a1b23c4fc1c4b4275d203c295/6fa81/webpack.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 87.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAABYlAAAWJQFJUiTwAAACOUlEQVR42p1U2XLbMAzM//9c+5Zp4vi2JEsiKYmnzi0Ax249E7uHZ3ZIQxKIxS74Ep1HnyIWADFGhBAwTROe/aZpRt/3GMYZqZ8wzsvt2UurFHzX0XaBMQZKaUk6zzN9MGIk8AHjb/thGOA9F5IQfJSkt4TXzbIsKJoBzic459ARHFUfY6JqBlmv++v7XNc882HDr4T8gJ/w2lKlzlmEyIku1DnO1cp7f/G7VThTH05Hg+2mprXBbttgvzP4WNV4f6so1uJcBNQ1oQpIafzyoDvKZalxPmscj2fsDwUOhxynU4ksqyhRC607NK2jPjew1BLvgxTyZULm3feRkKjJkfrSS2/GaSDqw79TZivstjVRPGNF2KxrgqaYxuq9oriiyi31luwyjKI0q/6QMpee5xXRLIhuhv0+E6pZVqIoaqLZCtW2s0K3s1bc8LSH3tOLnRWDMxIZPiZe0/+pnGcdKXtRV7BvcCCsP0iswhL4wCi9ZcqMpxUqRZOijVCxZGprvSjJe441bUcxTnpZGWydhwmNYa/VaBqLltFSn2ySpDH04G//xPxO5cNB4+1HKQqv19Wn0oq8qGRf5FZGk2edxzKE+LzCpjHQRgmM0WRkRTENQ3H250De5JUThngR62FCFkVrKxNRljQVyiH6kT7iq4pMnxZZU5yf0r6jvNmUpKzC9287vL6eiH5Gc5yL0XnGt5uK/hefo8c97kTpB6MH+ODklnHeXuA6uXl4JJdlFjBFvrL4JvrqcvgJBd93ox0YT8EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;webpack&quot; title=&quot;&quot; src=&quot;/static/eefb5d1a1b23c4fc1c4b4275d203c295/6af66/webpack.png&quot; srcset=&quot;/static/eefb5d1a1b23c4fc1c4b4275d203c295/69538/webpack.png 160w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/72799/webpack.png 320w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/6af66/webpack.png 640w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/d9199/webpack.png 960w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/21b4d/webpack.png 1280w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/6fa81/webpack.png 1856w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    Search &quot;webpack eject&quot; on Google and you&apos;ll see&lt;br&gt;
    just how many people try to avoid breaking the abstraction and touching Webpack directly.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Thanks to these abstractions, today’s frontend developers are freed from complex concepts like manually syncing state with UI rendering or bundling projects themselves, allowing them to focus on higher-level concerns. This has enabled the development of increasingly large and complex web client applications.&lt;/p&gt;
&lt;p&gt;This is exactly what abstraction in programming — and in industry more broadly — gives us.&lt;/p&gt;
&lt;h2 id=&quot;moving-beyond-extract-common-features&quot; style=&quot;position:relative;&quot;&gt;Moving Beyond “Extract Common Features”&lt;a href=&quot;#moving-beyond-extract-common-features&quot; aria-label=&quot;moving beyond extract common features permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we’ve established that abstraction is a general concept not limited to programming and why the programming world needs it, let’s look at something more specific.&lt;/p&gt;
&lt;p&gt;I said earlier that OOP’s guideline of “extract common features from concrete things to define abstract things” doesn’t fully explain the essence of abstraction. It’s just one approach to abstracting something complex into something simple.&lt;/p&gt;
&lt;p&gt;I’m not saying this approach is wrong, but I personally don’t recommend trying to understand abstraction from this guideline. It’s simply “one way to approach a subject for abstraction.” Getting too attached to this method can actually limit your imagination about how the application might evolve, leading to designs that aren’t open to change.&lt;/p&gt;
&lt;p&gt;Let’s look at a simple class example.&lt;/p&gt;
&lt;h3 id=&quot;design-that-too-faithfully-reflects-current-requirements&quot; style=&quot;position:relative;&quot;&gt;Design That Too Faithfully Reflects Current Requirements&lt;a href=&quot;#design-that-too-faithfully-reflects-current-requirements&quot; aria-label=&quot;design that too faithfully reflects current requirements permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2dbad5fcbddeaeca5e18e36c521d345b/010c2/class.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.12500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABVklEQVR42p1T207CQBDd//8XH33zwQRioggViUBBikFDoYWWS/dCS3vc2QJpKwZxXrYzZ+bMzOkuwwVLIgnhBogjgb8YOxvNDmRiB9ey4dQtuK2B9lUJv4Iwr4jXHE7Nwv3NLUb6jFdRCb+aUEQcXneMZWeM+ZsDwcU/J9SmlALnHOk+RegtdI/U+BS/oGGWT1ToKqU0xfmw2enbTC2EwUt6FyRg1fGrBVXCY0PKOzthpleKudSr7cF1UnUlim+DlVn9hyQ6n3Cqzw44C4ef8KwhfC2+ErL0U9Jkj2Awgf8yRGBPjF/Ed1Jh0fsw9cRDpMxt9NGvNeE+9yEX69OaZrVgY+LtuwfM9T2Uywq+3GDWtGHXWyZPhVswv+Ng+tSD134vXNy8IJE7eK8jfD124euT/CIh5RM+bfTgdzSuYrCEay3mvz8t0ofPQo3L83hEeADiIQ2/Aaowpk7ljaFxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;class&quot; title=&quot;&quot; src=&quot;/static/2dbad5fcbddeaeca5e18e36c521d345b/6af66/class.png&quot; srcset=&quot;/static/2dbad5fcbddeaeca5e18e36c521d345b/69538/class.png 160w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/72799/class.png 320w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/6af66/class.png 640w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/d9199/class.png 960w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/21b4d/class.png 1280w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/010c2/class.png 1425w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;The requirements include objects A, B, and C.&lt;/li&gt;
&lt;li&gt;Their commonality is that they’re all pink circles; the difference is the letter in the center.&lt;/li&gt;
&lt;li&gt;Define a class: pink circle shape + injectable center letter.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;This class can cover all cases in the current requirements, so it looks well-abstracted. And indeed, this design faithfully satisfies the current business requirements — no problems.&lt;/p&gt;
&lt;p&gt;But problems always arise when changes beyond the current spec come in.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/cd8cf2080c160b648d0b3581bbd6019e/add4c/class_2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABa0lEQVR42qWSTU/CQBCG+/+PHLjzGzjoRb34FSSKKJIANSAVLdCWj3a33W73dWdpCcUgJE4y6aTzzjOzO2vhBBMshuAJpOdBpemfWutgRm0+bL7A7HkAvzNENP4+2tw6Jgj6Dhr1C+NLe/IPYD5hMHbhNN60d7Bw3P9NyDkHYwwsWCHUR2ecIYqiE4A0jVKlBIGSJDFxqhfBNJwsjmOTU7t6itWBCbMsQxiGEEJs/xGQ50CzdZ2jSUlbvia1AWZSQiZCC6QRpntPY8kE/BXLa9S2SQGlWqUZZsKUC3jdEWatAYLhBDLvWpzInjLU7lzUbl28z3gpR1pf10x1LTFkLGBFXx4+7l8xuH7E/MU23Xa3XG8HqJz1UDnvmXjXZJJi3rYxuHmCoxnEspJVBLfVx+ShC1+/ueJIxRTN4RrVSwfVKwfN0bqUI23QH+NTPytiEMvcIQVsGpiO+5ZKhZ7LjFP8a4m6hmqJQXf4A3G5pEjyiHUqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;class 2&quot; title=&quot;&quot; src=&quot;/static/cd8cf2080c160b648d0b3581bbd6019e/6af66/class_2.png&quot; srcset=&quot;/static/cd8cf2080c160b648d0b3581bbd6019e/69538/class_2.png 160w,
/static/cd8cf2080c160b648d0b3581bbd6019e/72799/class_2.png 320w,
/static/cd8cf2080c160b648d0b3581bbd6019e/6af66/class_2.png 640w,
/static/cd8cf2080c160b648d0b3581bbd6019e/d9199/class_2.png 960w,
/static/cd8cf2080c160b648d0b3581bbd6019e/21b4d/class_2.png 1280w,
/static/cd8cf2080c160b648d0b3581bbd6019e/add4c/class_2.png 1452w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;&quot;PO/PD: Can you make object B&apos;s color changeable?&quot;&lt;/small&gt;
&lt;/center&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6d3c70bfde81787ab2b3a9eef6094d9d/7cc5e/sudden.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 77.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQAE/8QAFAEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABQNXzjgh5P//EABsQAQACAgMAAAAAAAAAAAAAAAECAwATBBES/9oACAEBAAEFAru9W+cD1xsQYtNVgjGX/8QAFREBAQAAAAAAAAAAAAAAAAAAEEH/2gAIAQMBAT8Bh//EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAECAQE/Aaf/xAAdEAACAQQDAAAAAAAAAAAAAAAAAQIREiFRIjFC/9oACAEBAAY/Anb2WuSq/TOc5SezJRrOxrR//8QAGxABAAIDAQEAAAAAAAAAAAAAAQARMVFxIUH/2gAIAQEAAT8hps1tqAefNBBPVeaMrRXk53fsjhyqn//aAAwDAQACAAMAAAAQwM//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREx/9oACAEDAQE/EE8FP//EABcRAAMBAAAAAAAAAAAAAAAAAAABITH/2gAIAQIBAT8Qa0Q//8QAHBAAAgIDAQEAAAAAAAAAAAAAAREAQTFRcSGh/9oACAEBAAE/EFjErRZicsQPyDZ1AOeRAvgFTbgOkDHUTFcMZ4YIEMn7YKn/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;sudden&quot; title=&quot;&quot; src=&quot;/static/6d3c70bfde81787ab2b3a9eef6094d9d/7cc5e/sudden.jpg&quot; srcset=&quot;/static/6d3c70bfde81787ab2b3a9eef6094d9d/0913d/sudden.jpg 160w,
/static/6d3c70bfde81787ab2b3a9eef6094d9d/cb69c/sudden.jpg 320w,
/static/6d3c70bfde81787ab2b3a9eef6094d9d/7cc5e/sudden.jpg 480w&quot; sizes=&quot;(max-width: 480px) 100vw, 480px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;My face when I hear the requirement.jpg&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;I’m sure many of you have experienced this. In fast-moving business environments, specs changing is completely natural — and this happens regardless of whether you use OOP or FP.&lt;/p&gt;
&lt;p&gt;In the example above, making the object color changeable is a simple change, so it might not seem like a big deal. But you know better than anyone that real-world changes are far more severe than this. &lt;del&gt;&lt;em&gt;(Move the building 1cm to the right…mmph)&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;There are many conditions that define “good code,” but a representative one is code that’s “open to change” — code that can be extended without modifying the existing design, even when requirements change. Business requirements inevitably shift with market conditions, and if the code can’t keep up, you can’t deliver real business impact.&lt;/p&gt;
&lt;p&gt;But the code in our example couldn’t handle future changes, creating a situation where the class must be modified. And since classes, being abstract representations, are likely reused in many places, fixing just the class won’t be the end of it.&lt;/p&gt;
&lt;h3 id=&quot;why-did-this-happen&quot; style=&quot;position:relative;&quot;&gt;Why Did This Happen?&lt;a href=&quot;#why-did-this-happen&quot; aria-label=&quot;why did this happen permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Why wasn’t this class designed to be open to change? There are many possible reasons, but I think it’s “because the design was too faithful to current requirements.”&lt;/p&gt;
&lt;p&gt;Of course, we develop products to match business requirements, so designing for current requirements is natural. But every developer wants future-proof designs — extensible, open to change, maximizing code reuse no matter what new features come along.&lt;/p&gt;
&lt;p&gt;But if you abstract by extracting commonalities from your current specs, even the abstracted concept is likely to be designed reflecting only “the present requirements.”&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b87aa75de4c1a353973fc1d2e9704b94/7a18f/bottom-up.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAACe0lEQVR42oVT3WvSURh2uVkU25JGBUGEEIHQutiQ7oW6iwi86yK82F9Q7KpFN0EE0W3QhZtzo+HSWcsPRJ0Oh7ChE92cqPN7M+a3F+V2PD3vL3/DuYsOvJzzfj3nvO95H0m1Wu0cHR2xcrksSKVSYQcHByyRSLC9vT0WDodZNBpl+/v7bHd3l0UiEZbP54U4MQf5J61Wi29tbf2ScKxOp8N791wux5HIY7EYX15e5jabjQOYezwebjKZeCqVOhPPGBN2ypGUSiU9bpzDq2YRuBgMBr8fHh7qoM/hdrLPwbaKGH2hUBB0iqU4iqcz5QPHEAgEPkn61iXIze55oMd+q0cX9+uQy/0AVPIACZ01Go1MoVCMdu1SyCCJWq2+hl3W1S+QX6VSjWi12uGujXwyt9s9eAZ8ampqSATse+HVPp3WMOTiuRe6XK4Jn89nW19ft2xsbPwwm80/l5aWlOTzer3vNjc3V9fW1r7BZ8WHvBTzpqenbxsMhvdGo/GD3W5/7XQ6Z3Q63TiVdsXhcDxEgx80Gg1lPB5XAkToDcZkEvojq9X6BOfH+OX7IiDKG8PHvAqFQjO48K3f73+zsrIyLvpHIEN9jz/tLZa8v989PqlcLhfahMqk5wB7k/7TQ3ERyOiphjnSJ5PJhUwmo4csoJeTZLdYLGNgyhfMnh5lLxaLxXmw5zPKukF+9H0C7PmKGZwlP+ZwHnP4UdJsNjlAOcBOaNqR9IIStre379XrdV6r1Xg2m+1A6HwMegl9SqfTzykew39MzAH9/jEF6MTRNmj2hxxIeEYJ+NU7sDeJzzs7O23wuYOYCj7mLvnxcU8BSvT8DV8bOBzV5f8C3ToeMjy/hT4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;bottom up&quot; title=&quot;&quot; src=&quot;/static/b87aa75de4c1a353973fc1d2e9704b94/6af66/bottom-up.png&quot; srcset=&quot;/static/b87aa75de4c1a353973fc1d2e9704b94/69538/bottom-up.png 160w,
/static/b87aa75de4c1a353973fc1d2e9704b94/72799/bottom-up.png 320w,
/static/b87aa75de4c1a353973fc1d2e9704b94/6af66/bottom-up.png 640w,
/static/b87aa75de4c1a353973fc1d2e9704b94/d9199/bottom-up.png 960w,
/static/b87aa75de4c1a353973fc1d2e9704b94/21b4d/bottom-up.png 1280w,
/static/b87aa75de4c1a353973fc1d2e9704b94/7a18f/bottom-up.png 1284w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Since you&apos;re abstracting from the requirements you&apos;ve been given,&lt;br&gt;the abstracted concept naturally tends to reflect only current requirements&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;You can certainly create designs open to change even when abstracting from details. Design patterns commonly discussed in OOP — SOLID principles, and more specifically &lt;a href=&quot;https://en.wikipedia.org/wiki/Inversion_of_control&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;IoC&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_injection&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;DI&lt;/a&gt; — are methods for achieving exactly that.&lt;/p&gt;
&lt;p&gt;But to create designs open to change through this thinking process, you inevitably need the developer’s experience-based ability to predict the future and business domain knowledge. You need a sense for which parts are likely to change frequently so you can design those parts flexibly.&lt;/p&gt;
&lt;p&gt;Moreover, the common instruction “extract objects’ commonalities” says nothing about these design patterns, so developers have to learn them on their own and apply them appropriately.&lt;/p&gt;
&lt;p&gt;Experienced developers might think “just do it, what’s the big deal?” — but for beginners, looking at current requirements and thinking “this part is likely to change later, so I should design it to accept injected functionality from outside” is really not easy.&lt;/p&gt;
&lt;p&gt;So the direction I want to suggest is not defining abstract things from concrete things, but the reverse: &lt;strong&gt;try thinking of the abstract things first.&lt;/strong&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8900a6f2bd640ee40e97b7504d380a91/10d53/top-down.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 46.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbklEQVR42pVSy2rCQBSNVjdtqVqKgnTT0j/wL/oLrvsJXWfVjSshIohrN0qQtoEY20BbcBGCAcXsxPiKjwR02dCH0zNpAilIbS/cTOaec8/MvXeY8Xi8mc1mZDQaEcMwyGKxIKZpkul0uqH/k8nklef5U47j0vP5/I1ygW8o3+O5q2VZpNPpfDKDwUBAogRCAy4CfECShJi4XC6bELytVqvHxWIxAeweok2IiMPhUAJGuQ1wG7ZtS71e747ZYvvwPWa3hT3uTyOEhHyn+0wmEyuVSieCICTq9XqcZdlwkIsl5AumUqmDbRpBMlMuly9UVc1pmpaTZfmmUCgcergrjEMugecVRcnXarWrnXV4J0XhkWw2e4T+BcsP4cZp9O+s2+2et1qtJPNPi8EjgX0UHvfF/3I7tyxM8dpxnBdM+YlOst/vi7qui5joI40Be6acYKt+FVyv1xXybe+r1cp9o+12myBOYx/0g3glmOPbF2EDKjvl+1EUAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;top down&quot; title=&quot;&quot; src=&quot;/static/8900a6f2bd640ee40e97b7504d380a91/6af66/top-down.png&quot; srcset=&quot;/static/8900a6f2bd640ee40e97b7504d380a91/69538/top-down.png 160w,
/static/8900a6f2bd640ee40e97b7504d380a91/72799/top-down.png 320w,
/static/8900a6f2bd640ee40e97b7504d380a91/6af66/top-down.png 640w,
/static/8900a6f2bd640ee40e97b7504d380a91/d9199/top-down.png 960w,
/static/8900a6f2bd640ee40e97b7504d380a91/21b4d/top-down.png 1280w,
/static/8900a6f2bd640ee40e97b7504d380a91/10d53/top-down.png 1724w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Think about what components are needed to achieve the concrete requirements&lt;/small&gt;
&lt;/center&gt;
&lt;h3 id=&quot;composing-abstract-things-to-build-concrete-things&quot; style=&quot;position:relative;&quot;&gt;Composing Abstract Things to Build Concrete Things&lt;a href=&quot;#composing-abstract-things-to-build-concrete-things&quot; aria-label=&quot;composing abstract things to build concrete things permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you’re accustomed to the conventional abstraction approach, “define abstract things before concrete things” might feel unfamiliar. But this concept is neither new nor strange.&lt;/p&gt;
&lt;p&gt;Earlier, I explained that abstraction hides complex things to make them appear simple, and that thanks to this, we can live in modern society without knowing all the knowledge that constitutes it.&lt;/p&gt;
&lt;p&gt;Application design is the same. Instead of asking “what are the commonalities of these concrete implementations and how do I abstract them?”, you should ask “which parts of the concrete implementation should I package as separate components, and how should I let developers assemble these components so they can comfortably use my code without knowing more context than necessary?”&lt;/p&gt;
&lt;p&gt;The result may be similar — common aspects of concrete concepts end up being abstracted — but the direction of thinking is the exact opposite of extracting commonalities.&lt;/p&gt;
&lt;p&gt;Let’s say we need to build an iPhone. Approaching it by extracting commonalities from objects, the thinking flow would go something like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;All iPhone models have a way to go home (commonality)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iPhones can be divided into those with and without a home button (difference)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then maybe I add a parameter to show or hide the home button? (implementing the difference)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  showHomeButton&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;IPhone&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; showHomeButton &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHomeScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;showHomeButton &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeGesture&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSwipeUp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;small&gt;
    I wrote this using React&apos;s function declaration pattern, which I&apos;m more familiar with.&lt;br /&gt;
    The concept of composing abstract things to build concrete things remains the same regardless.
  &lt;/small&gt;
  &lt;br /&gt;
  &lt;br /&gt;
&lt;/center&gt;
&lt;p&gt;Something like this, roughly. At first glance, it handles the current requirements well. iPhones do come in older models with a home button and newer models without one.&lt;/p&gt;
&lt;p&gt;But what if later &lt;del&gt;(unlikely as it may be)&lt;/del&gt; Apple releases an iPhone with a dial-style home button? This iPhone has no concept of tapping or pressing — you can only rotate it.&lt;/p&gt;
&lt;p&gt;Naturally, our function wasn’t written with that in mind, so now we’d need to add a &lt;code class=&quot;language-text&quot;&gt;homeUIType&lt;/code&gt; parameter and remove the now-meaningless &lt;code class=&quot;language-text&quot;&gt;showHomeButton&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IPhoneHomeButtonType&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;dial&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;gesture&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  homeUIType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPhoneHomeButtonType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;IPhone&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; homeUIType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onMoveHome &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHomeScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;homeUIType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;gesture&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeGesture&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSwipeUp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;dial&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeDial&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just adding one more type of trigger for going home required changing the function’s parameters and internal logic entirely. And since the parameters changed, every place that uses this function needs to be updated too.&lt;/p&gt;
&lt;p&gt;Many developers reading this might be thinking:&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 393px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/40dbc4952056f4f9a119e783e1850333/02e12/what.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAIB/9oADAMBAAIQAxAAAAFLEWm55eMf/8QAGhABAAIDAQAAAAAAAAAAAAAAAQACERMhEv/aAAgBAQABBQI6aZqSFzNXvuo//8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAREv/aAAgBAwEBPwHRbq//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQIBAT8BBsv/xAAZEAADAQEBAAAAAAAAAAAAAAAAAREhAoH/2gAIAQEABj8C0k9pvSRBoeI//8QAGhABAAMBAQEAAAAAAAAAAAAAAQARMUFRIf/aAAgBAQABPyG9awqATN2DWvfIMaFpfJeTjPuLL6T/2gAMAwEAAgADAAAAELz/AP/EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8Q4Egcy//EABYRAQEBAAAAAAAAAAAAAAAAAAERAP/aAAgBAgEBPxABXDS3f//EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQWFx/9oACAEBAAE/EE4gEBoxtySv3RgG+X55AA9LvsI5BCRxfIBpFC1sPkRbNjcuDyf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;what&quot; title=&quot;&quot; src=&quot;/static/40dbc4952056f4f9a119e783e1850333/02e12/what.jpg&quot; srcset=&quot;/static/40dbc4952056f4f9a119e783e1850333/0913d/what.jpg 160w,
/static/40dbc4952056f4f9a119e783e1850333/cb69c/what.jpg 320w,
/static/40dbc4952056f4f9a119e783e1850333/02e12/what.jpg 393w&quot; sizes=&quot;(max-width: 393px) 100vw, 393px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Just use IoC and inject from outside for flexibility from the start — who codes it like that!&lt;/small&gt;
&lt;/center&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; ReactNode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;IPhone&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; renderHomeUI &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHomeScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// By composing with IoC from outside,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// you can use various Home UIs without changing any logic inside the IPhone component.&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IPhone&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IPhone&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeGesture&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSwipeUp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IPhone&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeDialog&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I agree. The “go home” feature is an abstract capability that has little to do with the “home button” itself. The home button — the entity that triggers the go-home event — is highly likely to change depending on the phone’s design.&lt;/p&gt;
&lt;p&gt;But as I mentioned, developers unfamiliar with this approach can easily get trapped by their existing knowledge of iPhone features or the current requirements, failing to recognize that the home button is highly change-prone. They might conflate the stable “go home” function with the volatile “home button” as a single concept, producing a tightly coupled design.&lt;/p&gt;
&lt;p&gt;Those who immediately thought “this should be injected from outside” probably developed that insight through past painful experiences, building an intuition for which parts change frequently. In a word: experience.&lt;/p&gt;
&lt;p&gt;But beginners lacking this insight will formulaically extract commonalities from concrete things to abstract, then ad-hoc their way through design extensions as the business evolves. It’s too easy to fall into this pattern.&lt;/p&gt;
&lt;p&gt;Concepts like IoC and DI are things you naturally learn through study after suffering through these mistakes a few times — very few people start development with these concepts already in hand.&lt;/p&gt;
&lt;p&gt;That’s why I recommend approaching abstraction not by extracting commonalities from concrete things, but by first thinking about what small components your concept is made of, then composing those components to build the concrete concept.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;An iPhone is composed of a microphone, speaker, display, home button, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How should each component be assembled?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Speakers and microphones probably don’t change position much across different smartphones.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Home buttons differ by smartphone, right? Some don’t even have one nowadays. So how should this be assembled?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;This bottom-up thinking naturally makes it easier to create designs that can cover not just the concept of “iPhone” but even the broader concept of “smartphone.”&lt;/p&gt;
&lt;p&gt;Since concrete concepts tend to reflect only the current business situation, extracting commonalities from them makes it hard to account for future changes. But when you think in terms of composing abstract concepts to build concrete ones, you naturally — almost without conscious effort — end up with designs where abstract components can be swapped in and out.&lt;/p&gt;
&lt;h2 id=&quot;things-worth-considering-for-good-abstraction&quot; style=&quot;position:relative;&quot;&gt;Things Worth Considering for Good Abstraction&lt;a href=&quot;#things-worth-considering-for-good-abstraction&quot; aria-label=&quot;things worth considering for good abstraction permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Having covered the macro aspects — what abstraction is and how to approach it — let me now discuss some actionable considerations for when you actually perform abstraction.&lt;/p&gt;
&lt;p&gt;I suggested using bottom-up thinking to consider what abstracted components you need to achieve concrete requirements. When abstracting this way, new questions arise: “what granularity should each component be?” and “how should I express each component’s functionality?”&lt;/p&gt;
&lt;p&gt;You could separate concerns so each component handles a single small responsibility, but splitting too finely can create over-abstraction that makes it hard to grasp context. You might also create components whose functionality is poorly expressed, making them difficult to compose with others.&lt;/p&gt;
&lt;p&gt;So in this section, I’ll share a few considerations I keep in mind when abstracting.&lt;/p&gt;
&lt;h3 id=&quot;dont-force-excessive-context-on-developers&quot; style=&quot;position:relative;&quot;&gt;Don’t Force Excessive Context on Developers&lt;a href=&quot;#dont-force-excessive-context-on-developers&quot; aria-label=&quot;dont force excessive context on developers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When people talk about the benefits of abstraction, they usually mention reusability. But as I’ve said repeatedly, the greatest benefit of abstraction is making complex things appear simple.&lt;/p&gt;
&lt;p&gt;This benefit can be found in classes, functions, and components alike. Here’s a rough example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Prepend “I am ” to each value in the array.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Evan&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Daniel&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Martin&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  newArr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;I am &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newArr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&apos;I am Evan&apos;, &apos;I am Daniel&apos;, &apos;I am Martin&apos;];&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Few people write imperative code like this nowadays, but I’ve exaggerated for illustration. This code uses a &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop to manually iterate the array, accessing each element by index to reassign values.&lt;/p&gt;
&lt;p&gt;A developer reading this code would naturally pick up on these contexts:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop will repeatedly execute the inner code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A variable &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt; initialized to &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt; will increment by &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; after each iteration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt; is used as an array index to access each element.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Template strings prepend &lt;code class=&quot;language-text&quot;&gt;I am&lt;/code&gt; to each element’s value.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;This code actually carries a lot of context. Because all a developer needs to know is whether the code properly prepends “I am” to each array value. They don’t need to know anything about indices or &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops.&lt;/p&gt;
&lt;p&gt;What if we abstract this operation at various levels?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Abstract only the array iteration and new array creation&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;I am &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;v&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Also abstract the string concatenation with template strings&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addPrefix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;I am&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Also abstract the fact that map is used&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addPrefixToItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;I am&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Abstract even the &quot;I am&quot; string concatenation&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addIamToItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These code samples show progressively higher levels of abstraction from top to bottom.&lt;/p&gt;
&lt;p&gt;The top code abstracts away the &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop and new array creation, so the developer no longer needs the context of manually initializing and managing an &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt; variable or declaring a new array. They just need to know how &lt;code class=&quot;language-text&quot;&gt;Array.prototype.map&lt;/code&gt; works — that it iterates an array and creates a new array from transformed elements. Code abstracted this way focuses more on the developer’s intended behavior than on the step-by-step instructions for the computer, which is why it’s also called &lt;a href=&quot;https://en.wikipedia.org/wiki/Declarative_programming&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;declarative programming&lt;/a&gt;. &lt;em&gt;(Focusing on what to do rather than how to do it.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let’s look at a more everyday example. You’re probably already writing code like this using various libraries:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; css &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@emotion/css&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; format &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;date-fns/format&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Abstracts: creating a Date object and initializing it to today&apos;s date&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; now &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Abstracts: generating the desired string from a Date object&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formattedDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;now&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;yyyy-MM-dd&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Abstracts: creating VDOM objects with React.createElement&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      css&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        font-size: 1.8rem;
        font-weight: 800;
      &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Abstracts: wrapping CSS in a style tag, inserting into &amp;lt;head&gt;, generating a class name&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      Today is &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;formattedDate&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// And all of the above behavior is abstracted into:&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Foo&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; component does something incredibly simple — displaying today’s date in a format like &lt;code class=&quot;language-text&quot;&gt;2023-03-02&lt;/code&gt;. But even a component this small has an enormous amount abstracted away when you examine each operation.&lt;/p&gt;
&lt;p&gt;If you had to read and understand all this code — or write it from scratch — to create this one component, it would no longer be a “simple” component. Abstraction makes it &lt;em&gt;look&lt;/em&gt; simple; it’s actually not simple at all. &lt;em&gt;(Just implementing React in vanilla JS is already a significant undertaking…)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But because all those behaviors described in the comments are abstracted into libraries like &lt;code class=&quot;language-text&quot;&gt;emotion&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;date-fns&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;react&lt;/code&gt;, we can ignore these complex operations and focus solely on “rendering the current time.”&lt;/p&gt;
&lt;p&gt;To emphasize once more: the value of industrial abstraction is making complex things appear simple, so that individual people can focus on their area of expertise and collaborate to build things more sophisticated and complex. This essential value of abstraction is exactly what we experience in our daily programming lives.&lt;/p&gt;
&lt;p&gt;When people discuss code readability, they often talk about the number of lines. But this is less about having many lines and more about “the amount of code you need to read and analyze to understand a module’s behavior.”&lt;/p&gt;
&lt;p&gt;Simply imagine what it would be like if all the contents of the &lt;code class=&quot;language-text&quot;&gt;emotion&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;date-fns&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;react&lt;/code&gt; libraries were declared in the same module as the &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; component.&lt;/p&gt;
&lt;p&gt;Opening that module with no prior knowledge, you’d struggle to figure out where to start reading, what you can safely ignore, and where in all that code a bug might be. The context forced upon the developer would be excessive.&lt;/p&gt;
&lt;p&gt;The same logic explains why frequently used modules in an organization are published as separate packages to a registry rather than just separated within the application. Both approaches separate the code from business logic, but a package blocks or discourages developers from peeking at the source code, thereby limiting their exposure to the separated module’s context. &lt;em&gt;(Of course, dependency management and cross-application reusability are also benefits of internal libraries.)&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Clearly looks like following the reference would lead to @quotalab/utils.d.ts&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// So people rarely try to peek at the source&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; uniq &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@quotalab/utils&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// This path makes it feel like you could immediately see the source&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// When something seems off, people jump right to the source -&gt; context is exposed&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; uniq &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utils/array&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;small&gt;
    If you make it inconvenient for developers to peek at source code, the risk of exposing them to unnecessary context also decreases.
  &lt;/small&gt;
  &lt;br /&gt;
  &lt;br /&gt;
&lt;/center&gt;
&lt;p&gt;Ultimately, the fundamental reason we abstract is to create context scopes — so that other developers reading our code (or our future selves) aren’t exposed to excessive context when trying to understand behavior. Just as you don’t need to understand semiconductors to use a computer.&lt;/p&gt;
&lt;p&gt;So the person performing abstraction needs to think deeply about what parts others need to know to understand and use the code, and what parts they don’t need to know at all.&lt;/p&gt;
&lt;h3 id=&quot;thinking-about-expression&quot; style=&quot;position:relative;&quot;&gt;Thinking About Expression&lt;a href=&quot;#thinking-about-expression&quot; aria-label=&quot;thinking about expression permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If good abstraction means hiding detailed code so that developers can understand behavior without looking inside, then the next question is: how do we express a module’s internals to the outside world so that developers using it can reasonably infer its behavior without peeking at the source?&lt;/p&gt;
&lt;p&gt;There’s a common joke about people not reading product manuals. The reason this meme works is that products are designed so users can roughly predict how to use them without reading the manual cover to cover. Paradoxically, the fact that you can use a product without reading the manual means it has a UX pattern that’s familiar to everyone.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e76956dc70409588a90016bfaa880d8c/d2602/paper.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEA//EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGpp0lqMQf/xAAaEAACAgMAAAAAAAAAAAAAAAAAEQEQEiEi/9oACAEBAAEFAoNUzHpn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxABAAMAAAAAAAAAAAAAAAAAEAARYf/aAAgBAQAGPwKa2f/EABoQAAMBAAMAAAAAAAAAAAAAAAABESExUXH/2gAIAQEAAT8hXPCzrnSieEMaLRkLk//aAAwDAQACAAMAAAAQOM//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPxBGf//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EBJ//8QAGRABAQEBAQEAAAAAAAAAAAAAAREAITFh/9oACAEBAAE/ECWysEsxQBB8XEhymNvxmKdq2WzJwXZd/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;paper&quot; title=&quot;&quot; src=&quot;/static/e76956dc70409588a90016bfaa880d8c/c08c5/paper.jpg&quot; srcset=&quot;/static/e76956dc70409588a90016bfaa880d8c/0913d/paper.jpg 160w,
/static/e76956dc70409588a90016bfaa880d8c/cb69c/paper.jpg 320w,
/static/e76956dc70409588a90016bfaa880d8c/c08c5/paper.jpg 640w,
/static/e76956dc70409588a90016bfaa880d8c/6a068/paper.jpg 960w,
/static/e76956dc70409588a90016bfaa880d8c/eea4a/paper.jpg 1280w,
/static/e76956dc70409588a90016bfaa880d8c/d2602/paper.jpg 4032w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;I&apos;m the first to admit I don&apos;t read manuals for simple devices.&lt;br&gt;I just now learned there&apos;s a warranty card in there.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Most products can be figured out by pressing a few visible buttons and tinkering. I never even opened the manual for a monitor I bought three years ago, yet I had no trouble connecting and using it.&lt;/p&gt;
&lt;p&gt;If anything, a product whose usage and behavior can’t be inferred at all without reading the manual — wouldn’t consumers reject it for being too difficult and unintuitive?&lt;/p&gt;
&lt;p&gt;The modules we build should be the same. Think of the manual as the source code. The developer performing abstraction should clearly express the module’s behavior, inputs, and outputs so that users can infer how to use it without reading the source.&lt;/p&gt;
&lt;p&gt;Two primary tools for expressing internal behavior to the outside world:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Names of variables and modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If it’s a function or class: input and output types&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addDays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is the definition of &lt;a href=&quot;https://date-fns.org/v2.29.3/docs/addDays&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;addDays&lt;/a&gt;, a function from the &lt;code class=&quot;language-text&quot;&gt;date-fns&lt;/code&gt; library. The name alone tells you it adds “days” to something. It takes a &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; as input and returns a &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; — so you can infer it returns a new &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; object with &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt; days added.&lt;/p&gt;
&lt;p&gt;I don’t know exactly what happens inside when I call this function. I can guess it probably uses &lt;code class=&quot;language-text&quot;&gt;Date.prototype.getDate&lt;/code&gt; to get the day and add &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt;, but I don’t need to know any of that to use it.&lt;/p&gt;
&lt;p&gt;All I need to know is: “this function gives me a new &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; object with the desired number of days added.” And I can infer that from the function’s name and input/output types.&lt;/p&gt;
&lt;p&gt;But what if the name and types looked like this instead?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 301px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/61f22ae5a2042768a1b9ea04e05fc12e/e8ddc/mental.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 125.62499999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAZABQDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAIEAwUG/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3hr2OYSB6ZNIRBA//8QAHRAAAgMAAgMAAAAAAAAAAAAAAQMAAhEEEhQzQf/aAAgBAQABBQLyFx+GMcanjq6gYynJrUO+HMZWhtB6p//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EACEQAAECBQUBAAAAAAAAAAAAAAEAIQIQERJhAxMjMoGR/9oACAEBAAY/Am1IfiughIBxRdrmVPVyPRHbDYlhMTIy/8QAHRABAAIDAAMBAAAAAAAAAAAAAQARITFBEFFx8f/aAAgBAQABPyHHoXr8RM1AsMje4bMjZblCByZagSDJVvYAAVICqep211mWJGNnY6fD4fJ//9oADAMBAAIAAwAAABCTxTz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAdEAEBAAICAwEAAAAAAAAAAAABEQAhMVFBYbGh/9oACAEBAAE/ECqLiaIdTB4OoAQhvDuXzibAguK+NczNsBZomzQ9kwx5R6g3T6Zz7uEkMKpZvALl2fuFpvKgUdc5O4gYbd5+Bz7/AKY4P//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;mental&quot; title=&quot;&quot; src=&quot;/static/61f22ae5a2042768a1b9ea04e05fc12e/e8ddc/mental.jpg&quot; srcset=&quot;/static/61f22ae5a2042768a1b9ea04e05fc12e/0913d/mental.jpg 160w,
/static/61f22ae5a2042768a1b9ea04e05fc12e/e8ddc/mental.jpg 301w&quot; sizes=&quot;(max-width: 301px) 100vw, 301px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;No way to tell what this thing does...!!!&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The name &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; suggests it adds something, but I can’t tell what it adds or what it returns. Because this function isn’t faithfully expressing its internal behavior through its types or parameter names.&lt;/p&gt;
&lt;p&gt;Would you trust this function and use it? Setting trust aside, you might not even be able to figure out what it does — and just skip it entirely.&lt;/p&gt;
&lt;p&gt;Even if you do use it somehow, you’d have to read the source code to understand the function’s behavior, losing the very benefit of abstraction: hiding complex context.&lt;/p&gt;
&lt;p&gt;Beyond this example, things like having too many parameters, or a function name that expresses context unrelated to its actual behavior, can also prevent developers from easily inferring the function’s role.&lt;/p&gt;
&lt;p&gt;The importance of expression applies universally to anything exposed outside a module — classes, variables, and more. It’s the foundation of design that shows consideration for other developers who will use your code, or your future self.&lt;/p&gt;
&lt;h3 id=&quot;controlling-input-freedom-for-good-dx&quot; style=&quot;position:relative;&quot;&gt;Controlling Input Freedom for Good DX&lt;a href=&quot;#controlling-input-freedom-for-good-dx&quot; aria-label=&quot;controlling input freedom for good dx permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you’re comfortable with expressing an abstracted module’s behavior to the outside world, it’s time to think deeply about the DX (Developer Experience) for users of your module.&lt;/p&gt;
&lt;p&gt;Many factors contribute to DX, but one I care most about is: “how much functionality should I expose?” This decision affects the effort users need to invest, the amount of context they must absorb, and the potential for human error.&lt;/p&gt;
&lt;p&gt;For example, imagine building a simple button component:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropsWithChildren&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This component doesn’t expose much functionality — it’s what you’d call a “closed” component. Since it only provides the ability to inject &lt;code class=&quot;language-text&quot;&gt;children&lt;/code&gt;, users have very limited freedom.&lt;/p&gt;
&lt;p&gt;While &lt;code class=&quot;language-text&quot;&gt;children&lt;/code&gt; can be freely injected through composition, changing the button’s &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt;, adding a click event handler, or anything else is simply not possible.&lt;/p&gt;
&lt;p&gt;But because the provided functionality is so limited, users barely need to think about how to use this component.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ComponentProps&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This component, on the other hand, accepts all the properties that React’s &lt;code class=&quot;language-text&quot;&gt;button&lt;/code&gt; component natively provides. Users can use any &lt;code class=&quot;language-text&quot;&gt;button&lt;/code&gt; property they want, giving them high development freedom.&lt;/p&gt;
&lt;p&gt;But because the component provides so many properties, users are continuously exposed to contexts that may not align with their purpose. I often describe this as “the component forcing decisions on the developer.”&lt;/p&gt;
&lt;p&gt;From the creator’s perspective, you can’t predict every way users might use your module, which increases the risk of bugs or use cases that deviate from the design intent.&lt;/p&gt;
&lt;p&gt;In other words, by controlling the module’s input range, the developer who creates the abstracted module can also somewhat control how users interact with it. So input design directly impacts the DX of developers using the module.&lt;/p&gt;
&lt;p&gt;This type of consideration mainly arises when building internal libraries that many developers share. Design systems add even more complexity because you need to incorporate the designer’s intent when designing interfaces. &lt;em&gt;(The more the code properties align with those defined in Figma or Framer, the lower the communication cost between developers and designers.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There’s no correct answer for whether to open up or restrict a module’s inputs. It depends on the users’ expertise, the module’s purpose, and whether it targets a general audience (like open source) or a limited group (like an internal library).&lt;/p&gt;
&lt;p&gt;The concept of shaping user experience by controlling the scope of provided functionality isn’t limited to code — it’s everywhere in daily life.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6754c9f5811dfe2b0eeedef280d18fc0/12609/synth2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 49.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAFkNwEFkP/EABwQAAAGAwAAAAAAAAAAAAAAAAABAgMSEwQQEf/aAAgBAQABBQJ1b103xjyriQ4Wv//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAQACAgMAAAAAAAAAAAAAAAEAAhExECIy/9oACAEBAAY/ArlLOBnpndyzRNcf/8QAHBABAAEEAwAAAAAAAAAAAAAAAQARITFhQVGR/9oACAEBAAE/IcIAU6hHT5g3l1bzqa3kAMFJ/9oADAMBAAIAAwAAABD0D//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB0QAQEAAgEFAAAAAAAAAAAAAAERADEhQVGB0fH/2gAIAQEAAT8QUDEIk4DNYk0eD1htaNXUvGO0BVirny2EwB2CZ//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;synth2&quot; title=&quot;&quot; src=&quot;/static/6754c9f5811dfe2b0eeedef280d18fc0/c08c5/synth2.jpg&quot; srcset=&quot;/static/6754c9f5811dfe2b0eeedef280d18fc0/0913d/synth2.jpg 160w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/cb69c/synth2.jpg 320w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/c08c5/synth2.jpg 640w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/6a068/synth2.jpg 960w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/eea4a/synth2.jpg 1280w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/12609/synth2.jpg 3000w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 498px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a9317f4f11dd17948f8a328924b4d7d/4e442/piano.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 67.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAADBv/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAV5CGdNHj//EABwQAAMAAQUAAAAAAAAAAAAAAAECAwAEERIUMf/aAAgBAQABBQJtau/YocnfkqIAlLk5Pz//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAeEAACAQMFAAAAAAAAAAAAAAAAASEikbECAxFBUf/aAAgBAQAGPwKi5GCVK8HudI400othH//EABwQAAICAwEBAAAAAAAAAAAAAAERADEhQYFRcf/aAAgBAQABPyHEAx6jWroWPJqMiLMQnOAzA5E21Z+mDlF//9oADAMBAAIAAwAAABAkD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB4QAQACAwACAwAAAAAAAAAAAAEAESExcUFhobHw/9oACAEBAAE/ELogc3huIwrZIHhtX65bX4TGaHCdltPnQb+hwdywJWqV/KP1DV1iT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;piano&quot; title=&quot;&quot; src=&quot;/static/5a9317f4f11dd17948f8a328924b4d7d/4e442/piano.jpg&quot; srcset=&quot;/static/5a9317f4f11dd17948f8a328924b4d7d/0913d/piano.jpg 160w,
/static/5a9317f4f11dd17948f8a328924b4d7d/cb69c/piano.jpg 320w,
/static/5a9317f4f11dd17948f8a328924b4d7d/4e442/piano.jpg 498w&quot; sizes=&quot;(max-width: 498px) 100vw, 498px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;People with professional audio knowledge can leverage a synthesizer&apos;s vast features in the right contexts,&lt;br&gt;but without that knowledge, a digital piano with limited features may be more appropriate for the purpose.
  &lt;small&gt;
&lt;/small&gt;&lt;/small&gt;&lt;/center&gt;
&lt;p&gt;A synthesizer lets you directly manipulate audio waveforms to create any sound you want, offering infinite freedom. But hand one to someone without professional audio knowledge and they’ll probably give up and sell it on the secondhand market.&lt;/p&gt;
&lt;p&gt;Moreover, such complex equipment is sometimes sensitive to voltage — careless use could damage it.&lt;/p&gt;
&lt;p&gt;For someone without professional knowledge or who simply doesn’t need that much freedom, a digital piano — with limited features but accessible to non-experts for producing beautiful sounds — may be the better fit.&lt;/p&gt;
&lt;p&gt;This isn’t about exposing more features just because experts know more. It depends on the context in which the tool is used and whether the user needs to understand its inner workings. Someone who just wants to play piano has no need for a complex, feature-rich synthesizer.&lt;/p&gt;
&lt;p&gt;Beyond instruments, examples of this concept abound: manual vs. automatic transmission, cellphones vs. HAM radio transceivers, C vs. JavaScript — tools with similar capabilities but different ranges of exposed functionality based on purpose and user persona.&lt;/p&gt;
&lt;p&gt;We must be careful not to implement a wide range of inputs that force unnecessary decisions on users who don’t need to understand the tool’s inner workings — or conversely, not to implement too narrow a range of inputs that limits use cases for users who need to understand the principles and reuse the tool across various situations.&lt;/p&gt;
&lt;p&gt;As I mentioned, this requires considering the business context, organizational situation, tool purpose, and user needs — there’s no single right answer. But if you’re ever in a position to build an abstracted module that other developers will use, it’s well worth thinking about.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every developer on Earth today exists in a close collaborative relationship with other developers. Some may work alone as freelancers or in early-stage startups, but ultimately they can’t avoid using tools that others conceived and developed. And since you’re not taking your code to the grave, the day will inevitably come when another developer inherits it.&lt;/p&gt;
&lt;p&gt;Since the moment when someone else must read and understand the code you wrote today is unavoidable, we have no choice but to put effort into writing code that humans can understand. Even if you truly are the only person who will ever touch it — there’s no guarantee your future self will remember how every piece works.&lt;/p&gt;
&lt;p&gt;Ultimately, abstraction in programming is the process of making things with complex underlying principles — or things easily understood by computers but hard for humans, easier for humans to understand. The methods and know-how for good abstraction may vary from person to person, but the fundamental essence of abstraction doesn’t change.&lt;/p&gt;
&lt;p&gt;Personally, I don’t think the specific methods or know-how of abstraction are that important. As I mentioned, patterns and methods for creating designs open to change are already abundant on the internet, and many concepts are already cleanly organized. Reading them and using them a few times should be enough to pick them up.&lt;/p&gt;
&lt;p&gt;But without understanding the fundamental value that the gift of abstraction brings us, it becomes difficult to even judge whether the information you’ve studied is truly useful or not.&lt;/p&gt;
&lt;p&gt;Developers frequently invoke “No Silver Bullet” — the idea that no universal solution exists for all problems. As this phrase implies, not all information we encounter brings only benefits; sometimes a technical decision we make costs us something in return.&lt;/p&gt;
&lt;p&gt;In such circumstances, developers must always coolly weigh the benefits of their decisions against the losses, and what helps with these decisions is an understanding of the fundamental value that the technology provides.&lt;/p&gt;
&lt;p&gt;Of course, what I’ve written in this post isn’t the definitive answer. These are simply the thoughts I’ve developed while working as a developer, and I imagine tens of millions of developers worldwide each have their own definitions arrived at through their own deliberation.&lt;/p&gt;
&lt;p&gt;I hope these reflections contribute even a little to the definition of abstraction you’ve arrived at, or will arrive at in the future. This concludes my post: What Is Abstraction, Really?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[추상이란 무엇일까]]></title><description><![CDATA[이번 포스팅에서는 추상(Abstraction)에 대한 이야기를 한번 해보려고 한다. 추상화는 비단 어플리케이션 설계 뿐만 아니라 컴퓨터 공학 전체에서 굉장히 중요한 자리를 차지하고 있는 개념이지만, 애초에 추상이라는 개념 자체도 워낙 추상적이라 이제 갓 개발을 시작한 많은 개발자들은 이 개념을 이해하는데 많은 혼란을 겪고는 한다. 이 추상이라는 개념은 복잡한 구조의 무언가를 만들어야 할 때 특히 빛을 발하는 개념이기 때문에, 거대하고 복잡한 어플리케이션을 설계할 때는 반드시 알고 있어야하는 개념이기도 하다.]]></description><link>https://evan-moon.github.io/2023/01/15/what-is-abstract/</link><guid isPermaLink="false">20230115-what-is-abstract</guid><pubDate>Sun, 15 Jan 2023 12:39:39 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 추상(Abstraction)에 대한 이야기를 한번 해보려고 한다. 추상화는 비단 어플리케이션 설계 뿐만 아니라 컴퓨터 공학 전체에서 굉장히 중요한 자리를 차지하고 있는 개념이지만, 애초에 추상이라는 개념 자체도 워낙 추상적이라 이제 갓 개발을 시작한 많은 개발자들은 이 개념을 이해하는데 많은 혼란을 겪고는 한다.&lt;/p&gt;
&lt;p&gt;이 추상이라는 개념은 복잡한 구조의 무언가를 만들어야 할 때 특히 빛을 발하는 개념이기 때문에, 거대하고 복잡한 어플리케이션을 설계할 때는 반드시 알고 있어야하는 개념이기도 하다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;필자가 예전에 작성했던 &lt;a href=&quot;/2019/08/24/what-is-object-oriented-programming/#%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5%EC%9D%B4%EB%9D%BC%EB%8A%94-%EA%B2%83%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EC%9D%98%EB%AF%B8%ED%95%98%EB%82%98%EC%9A%94&quot;&gt;알고 보면 재밌는 객체 지향 프로그래밍, OOP 흝어보기&lt;/a&gt; 포스팅과 &lt;a href=&quot;/2019/12/15/about-functional-thinking/&quot;&gt;기존의 사고 방식을 깨부수는 함수형 사고&lt;/a&gt; 포스팅에서 간단하게 추상화에 대해 언급하기는 했지만, 추상이라는 개념이 꼭 OOP에만 국한된 개념이 아니기도 하고 포스팅의 메인 주제와는 다른 주제라 해당 포스팅들에서는 추상 자체에 대해 자세히 이야기하지 못 했던 것 같다.&lt;/p&gt;
&lt;p&gt;많은 분들이 추상화를 “공통된 부분을 추려내는 것”이라고만 인지하고 있는 경우가 많다. 물론 엄밀히 이야기하면 틀린 말은 아니지만, 사실 이건 추상적인 무언가를 정의하기 위해 수행하는 구체적인 추상화 스킬 중 하나일 뿐이지 추상이라는 것의 본질이 무엇인지를 설명해주는 것은 아니다.&lt;/p&gt;
&lt;p&gt;만약 이런 개념으로부터 추상을 이해하려고 한다면, 누군가가 여러분에게 “프로그래밍에서 추상화가 왜 필요해요?”와 같은 질문을 했을 때, “공통적인 부분을 뽑아내서 재사용성을 높힐 수 있습니다”와 같이 지엽적인 답변을 할 수 밖에 없게 되는 것이다. &lt;small&gt;&lt;del&gt;(사실 필자가 면접 때 자주 물어본다)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;즉, 추상이라는 개념을 제대로 이해하기 위해서는 우선 프로그래밍에서 설명하는 추상화의 개념에서 벗어나, 본질적으로 추상이라는 것이 무엇인지, 그리고 이런 개념이 왜 필요한지에 대한 고민을 밑바닥부터 해보는 것이 중요하다.&lt;/p&gt;
&lt;h2 id=&quot;복잡한-것을-단순하게-표현하자&quot; style=&quot;position:relative;&quot;&gt;복잡한 것을 단순하게 표현하자&lt;a href=&quot;#%EB%B3%B5%EC%9E%A1%ED%95%9C-%EA%B2%83%EC%9D%84-%EB%8B%A8%EC%88%9C%ED%95%98%EA%B2%8C-%ED%91%9C%ED%98%84%ED%95%98%EC%9E%90&quot; aria-label=&quot;복잡한 것을 단순하게 표현하자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자, 그렇다면 가장 근본적인 것부터 한번 고민해보도록 하자. 추상이라는 것은 도대체 무엇일까?&lt;/p&gt;
&lt;p&gt;여러분도 아시다시피 추상이라는 용어 자체는 프로그래밍의 세계에서만 사용되는 것은 아니다. 사실 이 용어는 프로그래밍이나 수학에서도 사용되기는 하지만, 미술이나 건축에서도 많이 사용되는 용어이며, 대표적인 추상파 화가로는 그 유명한 피카소 형이 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 560px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d79c5756053bcba4a159e4af28a84bb6/9342c/optimize.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB6tTmYZBgo//EABoQAAIDAQEAAAAAAAAAAAAAAAECAwQTABL/2gAIAQEAAQUCrhcfKddAE8Mi46r1pg8v/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHRAAAQQCAwAAAAAAAAAAAAAAAAECESEyUTGRof/aAAgBAQAGPwJktTjRg3opIoakmXhKaP/EABwQAQACAQUAAAAAAAAAAAAAAAEAETFBUWGR8f/aAAgBAQABPyG3JdwngJUCFcEIoiGozjdpeWyk/9oADAMBAAIAAwAAABDEP//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxCYr//EABcRAAMBAAAAAAAAAAAAAAAAAAABETH/2gAIAQIBAT8QdosP/8QAHRABAAICAgMAAAAAAAAAAAAAAQARUYEhMUFh8P/aAAgBAQABPxB7mC1C7i4/dqBrEKIL5xK0AUV59RI51w6iAukzmf/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;optimize&quot; title=&quot;&quot; src=&quot;/static/d79c5756053bcba4a159e4af28a84bb6/9342c/optimize.jpg&quot; srcset=&quot;/static/d79c5756053bcba4a159e4af28a84bb6/0913d/optimize.jpg 160w,
/static/d79c5756053bcba4a159e4af28a84bb6/cb69c/optimize.jpg 320w,
/static/d79c5756053bcba4a159e4af28a84bb6/9342c/optimize.jpg 560w&quot; sizes=&quot;(max-width: 560px) 100vw, 560px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;소의 복잡한 부분을 전부 제거하고 가장 핵심적인 특징만을 나타낸 피카소의 그림&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이런 모습에서도 알 수 있듯이 추상화가 된 대상은 현실의 대상보다 그 대상의 본질, 조금 더 쉽게 이야기하면 각각의 디테일한 특징이 배제되어 대상 자체를 표현하는 특징들이 강화된다.&lt;/p&gt;
&lt;p&gt;피카소가 그린 소 그림은 “소”라는 본질만 가지고 있다면, 모두 대응이 가능한 표현이다. 젖소든, 한우든, 황소든 간에 저 형태에서 크게 벗어나는 소는 없다는 이야기이다. 현실에서 이 소들은 각각 다른 모습을 가지고 있지만, 다리가 4개 달리고 머리에 뿔이 있다는, 소라는 것이 가지는 본질적인 형태에서는 크게 벗어나지 않는다.&lt;/p&gt;
&lt;p&gt;마치 인간 개개인의 생김새, 목소리, 성격 등은 모두 다르지만, 결국 기본적으로 팔 2개, 다리 2개, 머리가 1개 달린 형태라는 것은 변하지 않는 것처럼 말이다. 이것이 바로 그 대상이 가지는 본질이다.&lt;/p&gt;
&lt;p&gt;또한 이렇게 대상의 본질만을 표현하고 디테일한 요소들을 배제하면 표현이 단순해질 수 밖에 없다. 100개의 세세한 특징을 표현한 것보다 10개의 핵심적인 특징만을 표현한 것이 더 단순한 것은 당연하다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 394px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7a4c375ac990f976ecd9ebcade7cc3b3/cc097/zolaman.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 108.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAAsTAAALEwEAmpwYAAABAElEQVR42s2V2QqEMAxF/f+/89EPcF/rjluGW4gMjG1t9WECwVDhcJutHhnsOI7LWGUevWxa4L7vVNc1JUlCaZrKGGdOwHVdKYoi6rpOXhXetq0827bNHghF4zj+5K7ve8rz3A4IBQCqioIUqAp0CZznmYqiUFbdGgiL4/jMFQrBAMT4Z53Dpmkuc5VlmSyOqi+1bcNQOFIAF0I860Mo8n2fgiCQsWlatEAoQoGqqpJftFFZlu5AVgPwMAzvjB4MqqZpurUgbilEm/BVHwFZJeY3DEPjYtACWQmUYX7hPD06lVqFy7KcM80LA2fOV8bofa8qrDTnfWh6Dv7jCXABfgBbGs0YyiN/PwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;zolaman&quot; title=&quot;&quot; src=&quot;/static/7a4c375ac990f976ecd9ebcade7cc3b3/cc097/zolaman.png&quot; srcset=&quot;/static/7a4c375ac990f976ecd9ebcade7cc3b3/69538/zolaman.png 160w,
/static/7a4c375ac990f976ecd9ebcade7cc3b3/72799/zolaman.png 320w,
/static/7a4c375ac990f976ecd9ebcade7cc3b3/cc097/zolaman.png 394w&quot; sizes=&quot;(max-width: 394px) 100vw, 394px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    간단한 원 하나와 직선 5개로 표현했지만, 아무도 이걸 개나 고양이라고 생각하지는 않는다.&lt;br&gt;
    이것이 바로 대상의 본질을 뽑아내어 표현한, 추상화된 대상인 것이다.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;결국 추상화가 된 대상은 “어떤 복잡한 대상의 핵심적인 특징만 남기고 나머지는 제거하여 단순화시킨 것”이라고 볼 수 있다. 마치 감정, 동물, 사물과 같은 복잡한 덩어리와 의미를 가진 것들을 단순한 도형들로 구성하여 단순화시키고 핵심적인 부분만을 강조한 추상파 화가들의 그림들처럼 말이다.&lt;/p&gt;
&lt;p&gt;그리고 이렇게 일반화된 핵심적인 특징들은 이러한 개체, 물체들의 공통적인 부분이 될 수 밖에 없다. 그래서 OOP에서 객체들의 공통점을 뽑아내어 클래스를 정의하라고 가이드하는 것이다.&lt;/p&gt;
&lt;p&gt;만약 필자가 그린 인간 그림에서 원이 없어진다면, 여러분은 이 그림이 로켓인지, 화살표인지, 머리가 없는 인간인지 알기 어려울 것이다. 왜냐면 살아있는 인간이라면 누구나 저 위치에 머리가 있어야 하는 것이 일반적이기 때문이다. 즉, 머리의 위치와 형태는 인간이라면 누구나 다 가지고 있는 대표적인 공통점인 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ce0b65b1961f895989162cd9111bf383/eea4a/headless.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 91.25000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAMCBAH/xAAXAQEBAQEAAAAAAAAAAAAAAAACAQAD/9oADAMBAAIQAxAAAAG855O0oC5Og5r0S//EABsQAAICAwEAAAAAAAAAAAAAAAABERIDEBMx/9oACAEBAAEFArDyQ+hYoQLxa//EABYRAQEBAAAAAAAAAAAAAAAAABIAEP/aAAgBAwEBPwEQ3//EABcRAAMBAAAAAAAAAAAAAAAAAAABExD/2gAIAQIBAT8BqVY8/8QAGBAAAwEBAAAAAAAAAAAAAAAAARARACH/2gAIAQEABj8C0jpPWF//xAAdEAACAgEFAAAAAAAAAAAAAAAAAREhMUFRYXGh/9oACAEBAAE/IYb+FZZuJOrOJZuwEkUYhmNWf//aAAwDAQACAAMAAAAQLCdA/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEQETH/2gAIAQMBAT8QRqLY/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREg/9oACAECAQE/EGDG/8QAHBABAAIDAQEBAAAAAAAAAAAAAQAhETFBcVHR/9oACAEBAAE/EDgj1fkJtwvMewCZWz0GZtXyRVYABujnkKDTybn2Yl2273Mux3P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;headless&quot; title=&quot;&quot; src=&quot;/static/ce0b65b1961f895989162cd9111bf383/c08c5/headless.jpg&quot; srcset=&quot;/static/ce0b65b1961f895989162cd9111bf383/0913d/headless.jpg 160w,
/static/ce0b65b1961f895989162cd9111bf383/cb69c/headless.jpg 320w,
/static/ce0b65b1961f895989162cd9111bf383/c08c5/headless.jpg 640w,
/static/ce0b65b1961f895989162cd9111bf383/6a068/headless.jpg 960w,
/static/ce0b65b1961f895989162cd9111bf383/eea4a/headless.jpg 1280w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이 사진을 보고 자연스럽다고 생각하는 사람은 아마 아무도 없을 것이다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이렇게 복잡한 특성을 가진 대상이 가진 핵심적인 특징을 제외한 나머지 자잘한 것들은 모두 쳐내 단순하게 표현하는 것, 이것이 바로 추상화의 본질이다.&lt;/p&gt;
&lt;h2 id=&quot;왜-프로그래밍에-추상화가-필요할까&quot; style=&quot;position:relative;&quot;&gt;왜 프로그래밍에 추상화가 필요할까?&lt;a href=&quot;#%EC%99%9C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%97%90-%EC%B6%94%EC%83%81%ED%99%94%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C&quot; aria-label=&quot;왜 프로그래밍에 추상화가 필요할까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자는 추상화라는 것이 복잡한 특성을 가진 대상이 가진 핵심적인 특징을 제외한 나머지 자잘한 것들은 모두 쳐내 단순하게 표현하는 행위라고 설명했다.&lt;/p&gt;
&lt;p&gt;그럼 이런 행위가 프로그래밍을 할 때 도대체 왜 필요한 것일까? 우리는 피카소처럼 사물의 본질을 파악하여 예술적으로 표현하는 그런 사람들도 아닌데 말이다.&lt;/p&gt;
&lt;p&gt;사실 이 질문에 대한 답은 매우 간단하다. 바로…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;더 복잡하고 어려운 것&lt;/strong&gt;을 만들기 위해서이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;추상화는-더-복잡한-것을-만들-수-있게-해준다&quot; style=&quot;position:relative;&quot;&gt;추상화는 더 복잡한 것을 만들 수 있게 해준다&lt;a href=&quot;#%EC%B6%94%EC%83%81%ED%99%94%EB%8A%94-%EB%8D%94-%EB%B3%B5%EC%9E%A1%ED%95%9C-%EA%B2%83%EC%9D%84-%EB%A7%8C%EB%93%A4-%EC%88%98-%EC%9E%88%EA%B2%8C-%ED%95%B4%EC%A4%80%EB%8B%A4&quot; aria-label=&quot;추상화는 더 복잡한 것을 만들 수 있게 해준다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;앞서 이야기했듯 추상화를 당한 대상은 본래 자신이 가지고 있던 특징들 중 가장 핵심적인 특징만을 표현하게 되기 때문에, 매우 단순한 형태를 가지게 된다. 여기서 중요한 점은 “실제로는 복잡한 것을 단순하게 표현한다는 것”이다.&lt;/p&gt;
&lt;p&gt;다만 미술에서 사용하는 추상적 표현은 대상의 복잡한 부분을 제거하여 추상화를 진행하지만, 산업에서의 추상적 표현은 복잡한 부분을 감춤으로써 추상화를 진행한다는 차이점이 존재한다.&lt;/p&gt;
&lt;p&gt;즉, 구체적이고 복잡한 구현을 감추어 단순한 형태로 표현함으로써, 내가 만든 모듈이나 부품, 혹은 제품을 사용하는 사용자가 근본적인 원리를 알지 못 하더라도 대상의 기능을 활용할 수 있도록 만들어주는 것이다.&lt;/p&gt;
&lt;p&gt;우리가 일상 속에서 사용하는 컴퓨터만 해도, 가장 기본이 되는 부품인 반도체의 원리까지 모두 이해하고 사용하는 사람은 그리 많지 않으며, 심지어는 CPU가 뭔지도 모르는 초등학생조차도 컴퓨터를 사용할 수 있다. 우리는 그냥 컴퓨터라는 개념을 “키보드, 마우스로 조작하여 모니터나 스피커를 통해 뭔가 결과를 볼 수 있는 장치” 정도로 추상화하여 이해해도 사용에는 아무 문제가 없으니, 굳이 컴퓨터의 디테일한 원리까지 모두 알 필요도, 이유도 없는 것이다.&lt;/p&gt;
&lt;p&gt;또한 포토샵을 사용하여 사진을 보정하는 사람은 그냥 포토샵의 사용 방법 자체에만 집중하면 되지, 포토샵이라는 프로그램이 어떤 원리로 작동하는지, OS가 이 프로그램을 굴리기 위해 프로세스에 자원을 어떻게 할당하는지와 같은 내용은 전혀 몰라도 된다.&lt;/p&gt;
&lt;p&gt;만약 포토샵을 사용하는 사람이 이런 것까지 모두 신경써야 한다면 “포토샵으로 사진을 편집한다”라는 행위 자체가 너무 어렵고 복잡해지지는 않을까?&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/164a4e620bcf57d8857f4541b3fbe14b/6a068/photoshop.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAf/EABQBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAY6INFwoT//EABsQAAICAwEAAAAAAAAAAAAAAAABAhEDEiFB/9oACAEBAAEFAoSWrUVi6VR4f//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPwERf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAMAAwAAAAAAAAAAAAAAAAEQEQAhMf/aAAgBAQAGPwI3uE3ccX//xAAbEAADAQEAAwAAAAAAAAAAAAABESEAMUFRsf/aAAgBAQABPyEutTEs8PsOdxqfMGN514Ga+zv/2gAMAwEAAgADAAAAEIfP/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAEDAQE/EFDc/8QAFxEBAAMAAAAAAAAAAAAAAAAAARARIf/aAAgBAgEBPxBG8j//xAAeEAEAAgIBBQAAAAAAAAAAAAABESEAQdExUWFxkf/aAAgBAQABPxA3K1IRuaxL352LEa84x1I9eMVp0VYwXaBaWLmvmSubP//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;photoshop&quot; title=&quot;&quot; src=&quot;/static/164a4e620bcf57d8857f4541b3fbe14b/c08c5/photoshop.jpg&quot; srcset=&quot;/static/164a4e620bcf57d8857f4541b3fbe14b/0913d/photoshop.jpg 160w,
/static/164a4e620bcf57d8857f4541b3fbe14b/cb69c/photoshop.jpg 320w,
/static/164a4e620bcf57d8857f4541b3fbe14b/c08c5/photoshop.jpg 640w,
/static/164a4e620bcf57d8857f4541b3fbe14b/6a068/photoshop.jpg 960w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    만약 포토샵으로 사진을 편집할 때 이미지 프로세싱의 모든 원리를 알고 활용해야 한다면&lt;br&gt;
    인간 한 명의 리소스만으로는 너무 어려운 작업이 되어버릴 것이다.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이미 추상화의 근본적 개념은 자동차, 스마트폰, 도시 인프라 시스템, 행정처리 시스템 등 다양한 부분에서 활용되고 있으며, 평소 우리가 당연하다고 생각하고 누리고 있는 많은 것들이 내부적으로 굉장히 복잡한 로직과 인프라가 추상화된 결과물이다.&lt;/p&gt;
&lt;p&gt;우리는 이러한 추상화 덕분에 모든 분야에 대한 방대한 지식을 쌓지 않아도 복잡한 현대 사회의 시스템을 활용할 수 있게 되었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;수도꼭지를 돌리면 깨끗한 물이 나온다 👉 도시의 상수도 시스템이 추상화됨&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;동사무소에 가면 주민등록을 할 수 있다 👉 국가의 행정처리 시스템이 분업화되어 추상화됨&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;자동차의 액셀러레이터를 밟으면 차가 앞으로 전진한다 👉 흡기/압축/폭발/배기 과정을 다루는 ECU와 엔진의 로직이 추상화됨&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;이렇듯 현재 우리가 살아가는 세상은 다양한 추상 개념 위에 쌓아올려진 것이며, 복잡한 것을 단순하게 표현하는 이 개념 덕분에 사람들은 자신이 담당하는 것에만 집중하며 작업을 할 수 있게 되어 분업이 가능해지고, 기존보다 더욱 더 복잡한 것들을 만들 수 있게 된다.&lt;/p&gt;
&lt;p&gt;반도체를 생산하는 사람은 반도체라는 개념에만, 컴퓨터를 조립하는 사람은 컴퓨터라는 개념에만, 포토샵을 개발하는 사람은 이미지 프로세싱과 프로그래밍에만, 작품을 만드는 사람은 포토샵을 활용하는 것에만 집중하면되니, 각 분야에 대한 전문성을 가진 여러 사람이 모여 기존보다 더 거대하고 복잡한 것들을 만들 수 있게 되는 것이다. 만약 이 모든 것을 한 사람이 이해해야 제품을 생산할 수 있다면, 평생에 걸쳐서 지식을 쌓아도 복잡한 제품을 높은 퀄리티로 생산해내기 쉽지 않을 것이다.&lt;/p&gt;
&lt;p&gt;이런 추상화의 이점은 우리가 경험하는 프로그래밍에도 동일하게 적용되고 있다. 내가 만드는 소프트웨어 또한 다른 산업과 마찬가지로 전 세계의 수 많은 사람들이 기여한 여러가지 작은 모듈들의 조립품이기 때문이다.&lt;/p&gt;
&lt;p&gt;필자와 같은 프론트엔드 개발자들은 대부분 React나 Vue같은 라이브러리/프레임워크들을 사용하여 웹 어플리케이션을 개발하는데, 이렇게 작은 프로그램들인 라이브러리나 프레임워크를 조합하여 복잡한 어플리케이션을 만드는 것은 그리 어색한 일이 아니다.&lt;/p&gt;
&lt;p&gt;솔직히 JavaScript 엔진에 대한 자세한 동작 원리는 모르더라도, JavaScript에 대한 대략의 문법과 React라는 라이브러리에 대한 사용법만 알아도 어플리케이션을 개발하는 것이 불가능하지는 않다.&lt;/p&gt;
&lt;p&gt;또한 예전에는 Webpack을 개발자가 직접 세팅하여 어플리케이션을 번들링하는 것이 일상적이었지만, 이제는 CRA같은 Cli나 Next.js 같은 프레임워크가 자체적으로 Webpack Configuration을 만들어주고, 심지어 이를 감춰서 추상화해버리기 때문에 최근 개발을 시작하시는 분들은 Webpack을 직접 다뤄보지 않은 분들도 계신다. &lt;small&gt;(실제로 최근에는 Webpack에 대한 지식이 없어도 일반적인 어플리케이션을 개발하는 자체에는 큰 지장이 없다)&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eefb5d1a1b23c4fc1c4b4275d203c295/6fa81/webpack.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 87.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAABYlAAAWJQFJUiTwAAACOUlEQVR42p1U2XLbMAzM//9c+5Zp4vi2JEsiKYmnzi0Ax249E7uHZ3ZIQxKIxS74Ep1HnyIWADFGhBAwTROe/aZpRt/3GMYZqZ8wzsvt2UurFHzX0XaBMQZKaUk6zzN9MGIk8AHjb/thGOA9F5IQfJSkt4TXzbIsKJoBzic459ARHFUfY6JqBlmv++v7XNc882HDr4T8gJ/w2lKlzlmEyIku1DnO1cp7f/G7VThTH05Hg+2mprXBbttgvzP4WNV4f6so1uJcBNQ1oQpIafzyoDvKZalxPmscj2fsDwUOhxynU4ksqyhRC607NK2jPjew1BLvgxTyZULm3feRkKjJkfrSS2/GaSDqw79TZivstjVRPGNF2KxrgqaYxuq9oriiyi31luwyjKI0q/6QMpee5xXRLIhuhv0+E6pZVqIoaqLZCtW2s0K3s1bc8LSH3tOLnRWDMxIZPiZe0/+pnGcdKXtRV7BvcCCsP0iswhL4wCi9ZcqMpxUqRZOijVCxZGprvSjJe441bUcxTnpZGWydhwmNYa/VaBqLltFSn2ySpDH04G//xPxO5cNB4+1HKQqv19Wn0oq8qGRf5FZGk2edxzKE+LzCpjHQRgmM0WRkRTENQ3H250De5JUThngR62FCFkVrKxNRljQVyiH6kT7iq4pMnxZZU5yf0r6jvNmUpKzC9287vL6eiH5Gc5yL0XnGt5uK/hefo8c97kTpB6MH+ODklnHeXuA6uXl4JJdlFjBFvrL4JvrqcvgJBd93ox0YT8EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;webpack&quot; title=&quot;&quot; src=&quot;/static/eefb5d1a1b23c4fc1c4b4275d203c295/6af66/webpack.png&quot; srcset=&quot;/static/eefb5d1a1b23c4fc1c4b4275d203c295/69538/webpack.png 160w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/72799/webpack.png 320w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/6af66/webpack.png 640w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/d9199/webpack.png 960w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/21b4d/webpack.png 1280w,
/static/eefb5d1a1b23c4fc1c4b4275d203c295/6fa81/webpack.png 1856w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    구글에 &quot;webpack eject&quot;로 검색해보면&lt;br&gt;
    얼마나 많은 사람들이 추상화를 깨고 webpack을 직접 건드리는 것을 피하려고 하는지 알 수 있다.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이러한 추상화 덕분에 오늘날의 프론트엔드 개발자들은 상태와 UI를 연동하여 렌더링하고, 프로젝트를 직접 번들링하는 등의 복잡한 개념에서 해방되어 조금 더 고차원적인 부분들에 집중할 수 있게 되었고, 그로 인해 예전보다 점점 더 거대하고 복잡한 웹 클라이언트 어플리케이션을 개발할 수 있게 된 것이다.&lt;/p&gt;
&lt;p&gt;바로 이것이 프로그래밍, 더 나아가서는 산업에서의 추상화가 우리에게 가져다주는 이점이다.&lt;/p&gt;
&lt;h2 id=&quot;공통점을-뽑아내는-추상화-방법에서-벗어나보자&quot; style=&quot;position:relative;&quot;&gt;공통점을 뽑아내는 추상화 방법에서 벗어나보자&lt;a href=&quot;#%EA%B3%B5%ED%86%B5%EC%A0%90%EC%9D%84-%EB%BD%91%EC%95%84%EB%82%B4%EB%8A%94-%EC%B6%94%EC%83%81%ED%99%94-%EB%B0%A9%EB%B2%95%EC%97%90%EC%84%9C-%EB%B2%97%EC%96%B4%EB%82%98%EB%B3%B4%EC%9E%90&quot; aria-label=&quot;공통점을 뽑아내는 추상화 방법에서 벗어나보자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;지금까지는 추상이라는 개념이 프로그래밍에 국한되지 않은 일반적인 개념이라는 것과 프로그래밍의 세계에 추상화라는 개념이 필요한 이유에 대해서 살펴봤다면, 이제는 조금 더 국지적인 부분을 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;앞서 필자는 OOP에서 이야기하는 “구체적인 것들의 공통점을 뽑아내어 추상적인 것을 정의한다”라는 추상화의 가이드라인이 추상화의 본질을 제대로 설명하지 못 한다고 이야기했다. 이는 복잡한 무언가를 단순한 것으로 추상화를 하는 접근 방법 중 하나일 뿐이기 때문이다.&lt;/p&gt;
&lt;p&gt;물론 이 방법이 틀렸다는 것은 아니지만, 개인적으로 필자는 이 가이드라인으로부터 추상화를 이해하려는 것을 추천하지는 않는다. 이것은 그냥 “추상화를 하기 위해 대상에 접근하는 방법 중 하나일 뿐”이며, 오히려 너무 이 방법에 얽매이게 되면 추후 어플리케이션이 진화할 방향성에 대한 상상을 제한하게 되어 변경에 열려있지 않은 설계를 만들어낼 수도 있다.&lt;/p&gt;
&lt;p&gt;간단한 클래스를 한번 예로 들어보자.&lt;/p&gt;
&lt;h3 id=&quot;현재의-요구사항을-너무-충실하게-반영하는-설계&quot; style=&quot;position:relative;&quot;&gt;현재의 요구사항을 너무 충실하게 반영하는 설계&lt;a href=&quot;#%ED%98%84%EC%9E%AC%EC%9D%98-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD%EC%9D%84-%EB%84%88%EB%AC%B4-%EC%B6%A9%EC%8B%A4%ED%95%98%EA%B2%8C-%EB%B0%98%EC%98%81%ED%95%98%EB%8A%94-%EC%84%A4%EA%B3%84&quot; aria-label=&quot;현재의 요구사항을 너무 충실하게 반영하는 설계 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2dbad5fcbddeaeca5e18e36c521d345b/010c2/class.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.12500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABVklEQVR42p1T207CQBDd//8XH33zwQRioggViUBBikFDoYWWS/dCS3vc2QJpKwZxXrYzZ+bMzOkuwwVLIgnhBogjgb8YOxvNDmRiB9ey4dQtuK2B9lUJv4Iwr4jXHE7Nwv3NLUb6jFdRCb+aUEQcXneMZWeM+ZsDwcU/J9SmlALnHOk+RegtdI/U+BS/oGGWT1ToKqU0xfmw2enbTC2EwUt6FyRg1fGrBVXCY0PKOzthpleKudSr7cF1UnUlim+DlVn9hyQ6n3Cqzw44C4ef8KwhfC2+ErL0U9Jkj2Awgf8yRGBPjF/Ed1Jh0fsw9cRDpMxt9NGvNeE+9yEX69OaZrVgY+LtuwfM9T2Uywq+3GDWtGHXWyZPhVswv+Ng+tSD134vXNy8IJE7eK8jfD124euT/CIh5RM+bfTgdzSuYrCEay3mvz8t0ofPQo3L83hEeADiIQ2/Aaowpk7ljaFxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;class&quot; title=&quot;&quot; src=&quot;/static/2dbad5fcbddeaeca5e18e36c521d345b/6af66/class.png&quot; srcset=&quot;/static/2dbad5fcbddeaeca5e18e36c521d345b/69538/class.png 160w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/72799/class.png 320w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/6af66/class.png 640w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/d9199/class.png 960w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/21b4d/class.png 1280w,
/static/2dbad5fcbddeaeca5e18e36c521d345b/010c2/class.png 1425w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li&gt;요구사항에는 A, B, C라는 객체가 존재한다.&lt;/li&gt;
&lt;li&gt;A, B, C 객체의 공통점은 분홍색의 동그라미 모양이라는 것이고, 차이점은 가운데 들어가는 글자가 다르다는 것이다.&lt;/li&gt;
&lt;li&gt;분홍색 동그라미 모양 + 가운데 글자를 주입할 수 있는 클래스를 정의한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;이렇게 정의된 클래스는 현재 제시된 요구사항의 모든 케이스를 커버할 수 있기 때문에 추상화가 잘 된 것처럼 보인다. 실제로 이 설계는 현재의 비즈니스 요구사항을 충실하게 만족시키고 있기 때문에 별다른 문제가 없다.&lt;/p&gt;
&lt;p&gt;하지만 항상 문제는 현재의 스펙을 벗어난 추가적인 변경사항이 들어왔을 때 발생한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/cd8cf2080c160b648d0b3581bbd6019e/add4c/class_2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABa0lEQVR42qWSTU/CQBCG+/+PHLjzGzjoRb34FSSKKJIANSAVLdCWj3a33W73dWdpCcUgJE4y6aTzzjOzO2vhBBMshuAJpOdBpemfWutgRm0+bL7A7HkAvzNENP4+2tw6Jgj6Dhr1C+NLe/IPYD5hMHbhNN60d7Bw3P9NyDkHYwwsWCHUR2ecIYqiE4A0jVKlBIGSJDFxqhfBNJwsjmOTU7t6itWBCbMsQxiGEEJs/xGQ50CzdZ2jSUlbvia1AWZSQiZCC6QRpntPY8kE/BXLa9S2SQGlWqUZZsKUC3jdEWatAYLhBDLvWpzInjLU7lzUbl28z3gpR1pf10x1LTFkLGBFXx4+7l8xuH7E/MU23Xa3XG8HqJz1UDnvmXjXZJJi3rYxuHmCoxnEspJVBLfVx+ShC1+/ueJIxRTN4RrVSwfVKwfN0bqUI23QH+NTPytiEMvcIQVsGpiO+5ZKhZ7LjFP8a4m6hmqJQXf4A3G5pEjyiHUqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;class 2&quot; title=&quot;&quot; src=&quot;/static/cd8cf2080c160b648d0b3581bbd6019e/6af66/class_2.png&quot; srcset=&quot;/static/cd8cf2080c160b648d0b3581bbd6019e/69538/class_2.png 160w,
/static/cd8cf2080c160b648d0b3581bbd6019e/72799/class_2.png 320w,
/static/cd8cf2080c160b648d0b3581bbd6019e/6af66/class_2.png 640w,
/static/cd8cf2080c160b648d0b3581bbd6019e/d9199/class_2.png 960w,
/static/cd8cf2080c160b648d0b3581bbd6019e/21b4d/class_2.png 1280w,
/static/cd8cf2080c160b648d0b3581bbd6019e/add4c/class_2.png 1452w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;&quot;PO/PD: 동욱님 B객체의 색을 바꿀 수 있게 해주세요&quot;&lt;/small&gt;
&lt;/center&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6d3c70bfde81787ab2b3a9eef6094d9d/7cc5e/sudden.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 77.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQAE/8QAFAEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABQNXzjgh5P//EABsQAQACAgMAAAAAAAAAAAAAAAECAwATBBES/9oACAEBAAEFAru9W+cD1xsQYtNVgjGX/8QAFREBAQAAAAAAAAAAAAAAAAAAEEH/2gAIAQMBAT8Bh//EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAECAQE/Aaf/xAAdEAACAQQDAAAAAAAAAAAAAAAAAQIREiFRIjFC/9oACAEBAAY/Anb2WuSq/TOc5SezJRrOxrR//8QAGxABAAIDAQEAAAAAAAAAAAAAAQARMVFxIUH/2gAIAQEAAT8hps1tqAefNBBPVeaMrRXk53fsjhyqn//aAAwDAQACAAMAAAAQwM//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREx/9oACAEDAQE/EE8FP//EABcRAAMBAAAAAAAAAAAAAAAAAAABITH/2gAIAQIBAT8Qa0Q//8QAHBAAAgIDAQEAAAAAAAAAAAAAAREAQTFRcSGh/9oACAEBAAE/EFjErRZicsQPyDZ1AOeRAvgFTbgOkDHUTFcMZ4YIEMn7YKn/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;sudden&quot; title=&quot;&quot; src=&quot;/static/6d3c70bfde81787ab2b3a9eef6094d9d/7cc5e/sudden.jpg&quot; srcset=&quot;/static/6d3c70bfde81787ab2b3a9eef6094d9d/0913d/sudden.jpg 160w,
/static/6d3c70bfde81787ab2b3a9eef6094d9d/cb69c/sudden.jpg 320w,
/static/6d3c70bfde81787ab2b3a9eef6094d9d/7cc5e/sudden.jpg 480w&quot; sizes=&quot;(max-width: 480px) 100vw, 480px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;요구사항을 들은 나의 심정.jpg&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;아마 독자 여러분도 이런 경험이 많이 있을 것이라고 생각한다. 이처럼 빠르게 변화하는 비즈니스 상황 속에서 내가 개발하고 있던 어플리케이션의 스펙이 이에 따라 변경되는 것은 너무나도 자연스러운 일이며, 이런 상황은 내가 OOP를 사용하던 FP를 사용하던 패러다임과는 무관하게 항상 발생하게 된다.&lt;/p&gt;
&lt;p&gt;사실 위 예시의 설계에서 객체의 색을 변경할 수 있게 만들어주는 것은 간단한 작업이라 크게 문제가 없어보일 수도 있지만, 현실 세계에서 우리에게 들어오는 변경사항이 이 정도 수준이 아니라는 것은 다른 누구보다 독자 여러분이 더 잘 아실거라고 생각한다. &lt;small&gt;&lt;del&gt;(빌딩을 1cm만 오른쪽으로 옮겨주…읍읍)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;좋은 코드라는 것을 정의할 수 있는 조건은 여러 개가 있지만, 그 중 대표적인 조건 중 하나는 요구사항이 변경되더라도 기존의 설계를 최대한 건드리지 않고 확장할 수 있는 “변경에 열린 코드”이다. 비즈니스 요구사항은 시장의 상황에 따라 변화무쌍하게 변할 수 밖에 없는데, 코드가 이 속도를 따라가지 못 한다면 결국 제대로 된 비즈니스 임팩트를 낼 수 없기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 위 예시의 코드는 미래의 변경사항을 대처하지 못 했고, 결국 클래스에 수정을 가해야 하는 상황을 만들어냈다. 또한 추상 표현을 담당하는 클래스라는 개념의 특성 상 여기저기서 재사용되고 있을 가능성도 높으니, 이 클래스만 수정해서 끝날 일도 아닐 것이다.&lt;/p&gt;
&lt;h3 id=&quot;왜-이렇게-되었을까&quot; style=&quot;position:relative;&quot;&gt;왜 이렇게 되었을까?&lt;a href=&quot;#%EC%99%9C-%EC%9D%B4%EB%A0%87%EA%B2%8C-%EB%90%98%EC%97%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;왜 이렇게 되었을까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;왜 이 클래스는 변경에 열린 설계가 되지 못 했을까? 여러가지 이유가 있겠지만, 필자는 “현재의 요구사항에 충실한 설계를 했기 때문”이라고 생각한다.&lt;/p&gt;
&lt;p&gt;물론 우리는 비즈니스 요구사항에 맞춰 제품을 개발하는 사람들이니 현재의 요구사항에 맞춰 설계를 하는 것은 당연한 일이겠지만, 개발자라면 누구든 미래지향적인 설계, 추후 새로운 기능이 얼마나 붙든 기존 코드를 최대한 재사용할 수 있는 확장성있고 변경에 열린 설계를 하고 싶어한다.&lt;/p&gt;
&lt;p&gt;하지만 현재 나에게 주어진 기능의 스펙에서부터 공통점을 추려내는 방식으로 추상화를 진행하게된다면, 추상화된 대상 조차도 “당장 현재의 요구사항”만을 투영하고 있도록 설계될 가능성이 높아진다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b87aa75de4c1a353973fc1d2e9704b94/7a18f/bottom-up.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAACe0lEQVR42oVT3WvSURh2uVkU25JGBUGEEIHQutiQ7oW6iwi86yK82F9Q7KpFN0EE0W3QhZtzo+HSWcsPRJ0Oh7ChE92cqPN7M+a3F+V2PD3vL3/DuYsOvJzzfj3nvO95H0m1Wu0cHR2xcrksSKVSYQcHByyRSLC9vT0WDodZNBpl+/v7bHd3l0UiEZbP54U4MQf5J61Wi29tbf2ScKxOp8N791wux5HIY7EYX15e5jabjQOYezwebjKZeCqVOhPPGBN2ypGUSiU9bpzDq2YRuBgMBr8fHh7qoM/hdrLPwbaKGH2hUBB0iqU4iqcz5QPHEAgEPkn61iXIze55oMd+q0cX9+uQy/0AVPIACZ01Go1MoVCMdu1SyCCJWq2+hl3W1S+QX6VSjWi12uGujXwyt9s9eAZ8ampqSATse+HVPp3WMOTiuRe6XK4Jn89nW19ft2xsbPwwm80/l5aWlOTzer3vNjc3V9fW1r7BZ8WHvBTzpqenbxsMhvdGo/GD3W5/7XQ6Z3Q63TiVdsXhcDxEgx80Gg1lPB5XAkToDcZkEvojq9X6BOfH+OX7IiDKG8PHvAqFQjO48K3f73+zsrIyLvpHIEN9jz/tLZa8v989PqlcLhfahMqk5wB7k/7TQ3ERyOiphjnSJ5PJhUwmo4csoJeTZLdYLGNgyhfMnh5lLxaLxXmw5zPKukF+9H0C7PmKGZwlP+ZwHnP4UdJsNjlAOcBOaNqR9IIStre379XrdV6r1Xg2m+1A6HwMegl9SqfTzykew39MzAH9/jEF6MTRNmj2hxxIeEYJ+NU7sDeJzzs7O23wuYOYCj7mLvnxcU8BSvT8DV8bOBzV5f8C3ToeMjy/hT4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;bottom up&quot; title=&quot;&quot; src=&quot;/static/b87aa75de4c1a353973fc1d2e9704b94/6af66/bottom-up.png&quot; srcset=&quot;/static/b87aa75de4c1a353973fc1d2e9704b94/69538/bottom-up.png 160w,
/static/b87aa75de4c1a353973fc1d2e9704b94/72799/bottom-up.png 320w,
/static/b87aa75de4c1a353973fc1d2e9704b94/6af66/bottom-up.png 640w,
/static/b87aa75de4c1a353973fc1d2e9704b94/d9199/bottom-up.png 960w,
/static/b87aa75de4c1a353973fc1d2e9704b94/21b4d/bottom-up.png 1280w,
/static/b87aa75de4c1a353973fc1d2e9704b94/7a18f/bottom-up.png 1284w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;애초에 나에게 주어진 재료인 요구사항을 기반으로 추상화를 하게 되니,&lt;br&gt;추상화된 개념도 자연스레 현재의 요구사항만을 반영하게 되기 쉽다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;물론 디테일에서부터 추상화를 진행해도 얼마든지 변경에 열린 설계를 만들어낼 수는 있다. 흔히 객체지향에서 이야기하는 SOLID 원칙, 더 구체적으로는 &lt;a href=&quot;https://en.wikipedia.org/wiki/Inversion_of_control&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;IoC&lt;/a&gt;, &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9D%98%EC%A1%B4%EC%84%B1_%EC%A3%BC%EC%9E%85&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;DI&lt;/a&gt; 같은 디자인 패턴들이 바로 그런 설계를 하기 위한 방법이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;그러나 이런 사고 과정을 통해 추상화를 하는 상황에서 변경에 열린 설계를 하려면, 개발자의 짬바에 의존한 미래 예측력과 비즈니스 도메인 지식이 필요할 수 밖에 없다. 왜냐하면 어디가 얼마나 자주 바뀔 것 같은지에 대한 감이 있어야 그 부분을 유연하게 설계해놓을 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;심지어 일반적으로 추상화에 대한 설명을 할 때 따라오는 “객체들의 공통점을 뽑아라”이라는 문장에는 이런 디자인 패턴에 대한 이야기가 담겨있지 않으니, 개발자가 이런 원칙들을 알아서 공부하고 적재적소에 사용해야한다.&lt;/p&gt;
&lt;p&gt;물론 짬바가 어느 정도 찬 개발자들은 “그냥 하면 되는거 아님?”이라고 생각할 수 있지만, 처음 개발을 접한 초보자 입장에서는 현재의 요구사항만 보고 “여기는 나중에 변경되기 쉬운 부분이니까 원하는 기능을 외부에서 주입할 수 있도록 설계해놔야겠다”라는 생각을 하기가 참 쉽지 않다.&lt;/p&gt;
&lt;p&gt;그래서 필자가 제안하고 싶은 방향은 구체적인 것에서 추상적인 것을 정의하는 방향이 아닌, 반대로 추상적인 것을 먼저 떠올려 보는 방법이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8900a6f2bd640ee40e97b7504d380a91/10d53/top-down.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 46.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbklEQVR42pVSy2rCQBSNVjdtqVqKgnTT0j/wL/oLrvsJXWfVjSshIohrN0qQtoEY20BbcBGCAcXsxPiKjwR02dCH0zNpAilIbS/cTOaec8/MvXeY8Xi8mc1mZDQaEcMwyGKxIKZpkul0uqH/k8nklef5U47j0vP5/I1ygW8o3+O5q2VZpNPpfDKDwUBAogRCAy4CfECShJi4XC6bELytVqvHxWIxAeweok2IiMPhUAJGuQ1wG7ZtS71e747ZYvvwPWa3hT3uTyOEhHyn+0wmEyuVSieCICTq9XqcZdlwkIsl5AumUqmDbRpBMlMuly9UVc1pmpaTZfmmUCgcergrjEMugecVRcnXarWrnXV4J0XhkWw2e4T+BcsP4cZp9O+s2+2et1qtJPNPi8EjgX0UHvfF/3I7tyxM8dpxnBdM+YlOst/vi7qui5joI40Be6acYKt+FVyv1xXybe+r1cp9o+12myBOYx/0g3glmOPbF2EDKjvl+1EUAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;top down&quot; title=&quot;&quot; src=&quot;/static/8900a6f2bd640ee40e97b7504d380a91/6af66/top-down.png&quot; srcset=&quot;/static/8900a6f2bd640ee40e97b7504d380a91/69538/top-down.png 160w,
/static/8900a6f2bd640ee40e97b7504d380a91/72799/top-down.png 320w,
/static/8900a6f2bd640ee40e97b7504d380a91/6af66/top-down.png 640w,
/static/8900a6f2bd640ee40e97b7504d380a91/d9199/top-down.png 960w,
/static/8900a6f2bd640ee40e97b7504d380a91/21b4d/top-down.png 1280w,
/static/8900a6f2bd640ee40e97b7504d380a91/10d53/top-down.png 1724w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;구체적인 요구사항을 달성하기 위해 필요한 재료가 무엇인지를 고민해보자&lt;/small&gt;
&lt;/center&gt;
&lt;h3 id=&quot;추상적인-것들을-합성하여-구체적인-것을-만들기&quot; style=&quot;position:relative;&quot;&gt;추상적인 것들을 합성하여 구체적인 것을 만들기&lt;a href=&quot;#%EC%B6%94%EC%83%81%EC%A0%81%EC%9D%B8-%EA%B2%83%EB%93%A4%EC%9D%84-%ED%95%A9%EC%84%B1%ED%95%98%EC%97%AC-%EA%B5%AC%EC%B2%B4%EC%A0%81%EC%9D%B8-%EA%B2%83%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;추상적인 것들을 합성하여 구체적인 것을 만들기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;기존의 추상화 방법에 익숙한 분이라면, 구체적인 것보다 추상적인 것을 먼저 정의해보자고 했을 때 감이 잘 안 오실 수도 있지만, 사실 이 개념은 그렇게 새로운 것도 아니고 이상한 것도 아니다.&lt;/p&gt;
&lt;p&gt;앞서 필자는 추상이라는 개념을 사용하면 복잡한 것들을 감추어 단순하게 보이도록 만들 수 있고, 이런 추상의 효과 덕분에 우리가 복잡한 현대 사회를 구성하는 모든 지식을 알지 못 하더라도 현대 사회의 문물들을 충분히 이용하면서 살아갈 수 있다고 이야기했다.&lt;/p&gt;
&lt;p&gt;어플리케이션 설계 또한 마찬가지이다. 즉, 구체적인 객체 또는 구현체들의 공통점이 무엇이고 이런 공통점을 어떻게 추상화할지에 대한 고민보다는, 구체적인 구현 중에서 어떤 부분을 부품처럼 따로 나누어 포장하고, 또 이 부품들을 어떤 방식으로 조립하게 만들어줘야 내 코드를 사용하는 개발자들이 필요 이상의 맥락을 몰라도 내 코드를 편하게 사용할 수 있을 지에 대해 고민해야하는 것이다.&lt;/p&gt;
&lt;p&gt;물론 이런 접근 방식을 사용해도 결과적으로는 구체적인 개념들의 공통적인 부분이 추상화되는 결과가 나올테니 어떻게 보면 비슷하다고 느낄 수 있지만, 공통점을 뽑아내는 방법과는 사고의 방향이 정반대라는 차이가 있다.&lt;/p&gt;
&lt;p&gt;자, 만약 우리가 아이폰을 만들어야 하는 상황이라고 생각해보자. 객체들의 공통점을 뽑아내어 추상 개념을 정의하는 방식으로 접근하면 대략 이런 사고 흐름을 타게 될 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;아이폰의 모든 기종에는 홈으로 이동할 수 있는 기능이 존재한다 (공통점)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;아이폰은 홈 버튼이 있는 놈이랑 없는 놈으로 나눌 수 있지 않나? (차이점)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;그럼 함수에 홈 버튼을 보이게 하거나, 안 보이게 하는 인자를 하나 추가하면 되려나? (차이점의 구현)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  showHomeButton&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;IPhone&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; showHomeButton &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHomeScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;showHomeButton &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeGesture&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSwipeUp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;small&gt;
    필자에게 더 익숙한 React의 함수 선언 패턴으로 작성해보았다.&lt;br /&gt;
    어차피 추상적인 무언가를 조합해서 복잡하고 구체적인 것을 만든다는 개념 자체는 변하지 않는다.
  &lt;/small&gt;
  &lt;br /&gt;
  &lt;br /&gt;
&lt;/center&gt;
&lt;p&gt;뭐 대충 이런 모양이 되지 않을까? 얼핏 보면 현재의 요구 사항을 잘 맞추긴 했다. 아이폰은 기종에 따라 홈 버튼이 존재하는 구형 기종과 홈 버튼이 없는 신형 기종이 존재하기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 만약 나중에 &lt;small&gt;&lt;del&gt;(그럴리 없겠지만)&lt;/del&gt;&lt;/small&gt; 홈 버튼을 다이얼로 만든 아이폰이 출시된다면 어떻게 될까? 이 아이폰은 홈 버튼을 터치하거나 누른다는 개념이 없고 그저 돌릴 수만 있다.&lt;/p&gt;
&lt;p&gt;당연히 현재 우리의 함수는 그런 개념까지 생각하지 못 한 상태로 작성되었으니, 이제 이 함수에 &lt;code class=&quot;language-text&quot;&gt;homeUIType&lt;/code&gt;이라는 새로운 인자를 추가하고, 의미가 없어진 &lt;code class=&quot;language-text&quot;&gt;showHomeButton&lt;/code&gt; 인자는 제거해야 할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IPhoneHomeButtonType&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;dial&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;gesture&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  homeUIType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPhoneHomeButtonType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;IPhone&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; homeUIType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onMoveHome &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHomeScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;homeUIType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;gesture&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeGesture&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSwipeUp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;dial&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeDial&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;단지 홈으로 이동하는 동작의 트리거 종류가 하나 추가되었을 뿐인데도 함수의 인자와 내부 로직이 전부 변경되었다. 게다가 함수의 인자가 변경되었으니 기존에 이 함수를 사용하고 있던 모든 곳에도 이 변경사항에 맞춰 수정을 해줘야 할 것이다.&lt;/p&gt;
&lt;p&gt;여기까지 보신 많은 개발자 분들은 이렇게 생각하실 수도 있겠다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 393px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/40dbc4952056f4f9a119e783e1850333/02e12/what.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAIB/9oADAMBAAIQAxAAAAFLEWm55eMf/8QAGhABAAIDAQAAAAAAAAAAAAAAAQACERMhEv/aAAgBAQABBQI6aZqSFzNXvuo//8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAREv/aAAgBAwEBPwHRbq//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQIBAT8BBsv/xAAZEAADAQEBAAAAAAAAAAAAAAAAAREhAoH/2gAIAQEABj8C0k9pvSRBoeI//8QAGhABAAMBAQEAAAAAAAAAAAAAAQARMUFRIf/aAAgBAQABPyG9awqATN2DWvfIMaFpfJeTjPuLL6T/2gAMAwEAAgADAAAAELz/AP/EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8Q4Egcy//EABYRAQEBAAAAAAAAAAAAAAAAAAERAP/aAAgBAgEBPxABXDS3f//EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQWFx/9oACAEBAAE/EE4gEBoxtySv3RgG+X55AA9LvsI5BCRxfIBpFC1sPkRbNjcuDyf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;what&quot; title=&quot;&quot; src=&quot;/static/40dbc4952056f4f9a119e783e1850333/02e12/what.jpg&quot; srcset=&quot;/static/40dbc4952056f4f9a119e783e1850333/0913d/what.jpg 160w,
/static/40dbc4952056f4f9a119e783e1850333/cb69c/what.jpg 320w,
/static/40dbc4952056f4f9a119e783e1850333/02e12/what.jpg 393w&quot; sizes=&quot;(max-width: 393px) 100vw, 393px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;아니 처음부터 IoC로 외부에서 주입하도록 유연하게 설계하면 되는데, 누가 저렇게 개발하냐!&lt;/small&gt;
&lt;/center&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; ReactNode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;IPhone&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; renderHomeUI &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setHomeScreen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;moveHome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHomeScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 애초에 외부에서 IoC 패턴으로 합성해놓으면,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// IPhone 컴포넌트 내부의 로직을 아예 변경하지 않고도 다양한 Home UI를 사용할 수 있도록 설게할 수 있다.&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IPhone&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeButton&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IPhone&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeGesture&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onSwipeUp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IPhone&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;renderHomeUI&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeDialog&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;moveHome&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;물론 필자도 그렇게 생각한다. 사실 홈으로 이동하는 기능은 “홈 버튼”과는 크게 관련이 없는 추상적인 기능이니, 홈으로 이동하는 이벤트를 호출하는 주체인 홈 버튼이라는 녀석은 스마트폰의 설계에 따라 변경될 가능성이 농후하기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 이야기했듯이 이러한 설계에 익숙하지 않은 개발자라면 이미 자신이 알고 있는 아이폰의 기능이나 현재 주어진 요구사항이라는 개념에 매몰되어 홈 버튼이라는 녀석이 굉장히 변경되기 쉬운 녀석이라는 사실을 인지하기 어려울 수도 있고, 변경될 가능성이 낮은 홈으로 이동하는 기능과 변경될 가능성이 높은 홈 버튼이 마치 하나의 개념인 것처럼 오인식하여 결합도가 높은 설계를 하게 되기가 쉽다.&lt;/p&gt;
&lt;p&gt;아마 처음부터 “엥 이건 외부에서 주입해야 할 것 같은데…?”라고 생각하신 분들은 과거에 직접 경험했던 여러 삽질을 통해서 해당 부분이 자주 변경될 것 같다는 인사이트를 쌓으셨기 때문에 문제의식을 가지게 되셨을거라고 생각한다. 쉽게 말해 짬바다.&lt;/p&gt;
&lt;p&gt;그러나 이런 인사이트가 부족한 초보 개발자들은 일종의 공식처럼 구체적인 것들의 공통점을 뽑아내어 추상화를 진행할 수 밖에 없고, 이후 비즈니스가 변화함에 따라 발생하는 이슈들을 대응할 때 주먹구구식으로 설계를 확장하게 되기 너무 쉬운 것이다.&lt;/p&gt;
&lt;p&gt;솔직히 IoC, DI 같은 개념들은 이런 삽질을 통해 몇 번 고생을 해보다 보면 자연스럽게 공부를 통해 알게 되는 것이지, 처음부터 이런 개념을 가지고 개발을 시작하는 사람은 그리 많지 않다고 생각한다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 추상적인 설계를 하기 위해서는 구체적인 것들로부터 공통점을 뽑아내는 것보다는 내가 구현해야하는 이 개념이 어떤 작은 부품들로 이루어져 있는지부터 고민해보고, 이 부품들을 어떤 방식으로 조립(합성)해가며 구체적인 개념을 만들어가는 방식으로 접근하는 것을 추천하는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;아이폰이라는 것은 마이크, 스피커, 디스플레이, 홈버튼 등으로 이루어져있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;각각의 부품들은 어떤 방식으로 조립되어야 할까?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;아마 스피커나 마이크 같은 애들은 다른 스마트폰이라도 위치가 크게 변하지 않을거야.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;홈 버튼은 스마트폰마다 모양도 다르지 않나? 요즘에는 심지어 없는 것도 있던데, 그럼 이걸 어떻게 조립해야할까?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;이렇게 Bottom-Up 사고 방식으로 설계를 하게되면 자연스럽게, 아이폰이라는 개념과, 더 나아가서는 스마트폰이라는 개념까지도 포괄할 수 있는 설계를 만들기 쉬워진다.&lt;/p&gt;
&lt;p&gt;아무래도 구체적인 개념은 당장 현재의 비즈니스 상황만을 반영하게 되기 때문에, 구체적인 개념에서 공통점을 뽑아내어 추상적인 개념을 정의할 때는 미래의 변경 가능성까지 고려하기 어렵지만, 추상적인 개념들을 조립하여 구체적인 개념을 만들어내는 과정으로 사고하게 되면 내가 딱히 의식하지 않아도 어느 정도는 자연스럽게 추상적인 개념들을 갈아끼울 수 있게 만드는 설계를 하기 쉬워진다.&lt;/p&gt;
&lt;h2 id=&quot;좋은-추상화를-위해-고민해볼만한-것들&quot; style=&quot;position:relative;&quot;&gt;좋은 추상화를 위해 고민해볼만한 것들&lt;a href=&quot;#%EC%A2%8B%EC%9D%80-%EC%B6%94%EC%83%81%ED%99%94%EB%A5%BC-%EC%9C%84%ED%95%B4-%EA%B3%A0%EB%AF%BC%ED%95%B4%EB%B3%BC%EB%A7%8C%ED%95%9C-%EA%B2%83%EB%93%A4&quot; aria-label=&quot;좋은 추상화를 위해 고민해볼만한 것들 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;추상화라는 개념과 추상화를 시작할 때의 접근 방법과 같은 거시적인 것들에 대해 알아보았다면, 지금부터는 실제로 추상화를 진행할 때 한번 고민해보면 좋을 법한 액션아이템들에 대한 이야기를 해보려고 한다.&lt;/p&gt;
&lt;p&gt;앞서 필자는 Bottom-Up 사고 방식을 통해, 구체적인 요구사항을 달성하기 위해서 어떤 추상화된 부품들이 필요할지에 대해 고민해보자고 이야기했었는데, 이런 방식을 통해 추상화를 진행하게 되면 이제 “부품을 어떤 단위로 설계해야하는지”, “부품의 기능을 어떻게 표현해줄지” 같은 고민이 새롭게 생겨난다.&lt;/p&gt;
&lt;p&gt;각각의 부품이 하나의 작은 역할만 담당하도록 관심사를 나눠서 설계할 수도 있지만 오히려 각 부품의 개념을 잘게 나누었다가 과한 추상화로 인해 맥락을 파악하기 어려운 코드가 될 수도 있으며, 각각의 부품의 기능을 제대로 표현하지 못 해 다른 부품과 합성이 어려운 부품을 만들어버리게 될 수도 있다.&lt;/p&gt;
&lt;p&gt;그래서 이번 챕터에서는 필자가 추상화를 진행할 때 신경쓰는 몇 가지 고민들을 함께 공유하려고 한다.&lt;/p&gt;
&lt;h3 id=&quot;개발자에게-과한-맥락을-부여하지-않기&quot; style=&quot;position:relative;&quot;&gt;개발자에게 과한 맥락을 부여하지 않기&lt;a href=&quot;#%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%97%90%EA%B2%8C-%EA%B3%BC%ED%95%9C-%EB%A7%A5%EB%9D%BD%EC%9D%84-%EB%B6%80%EC%97%AC%ED%95%98%EC%A7%80-%EC%95%8A%EA%B8%B0&quot; aria-label=&quot;개발자에게 과한 맥락을 부여하지 않기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;추상화의 장점이라고 하면 보통 재사용성에 대한 이야기를 많이 하지만, 필자가 여러 번 이야기 했듯이 추상화의 가장 큰 장점은 복잡한 것을 단순해보이게 만들 수 있다는 점이다.&lt;/p&gt;
&lt;p&gt;이러한 추상화의 장점은 오늘날 자주 사용하는 클래스, 함수, 컴포넌트 모두에게서 발견할 수 있는데, 대충 예를 들어보자면 이런 느낌이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;배열 내부에 있는 값들의 앞에 “I am “이라는 값을 붙혀주세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Evan&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Daniel&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Martin&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  newArr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;I am &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newArr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&apos;I am Evan&apos;, &apos;I am Daniel&apos;, &apos;I am Martin&apos;];&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;사실 요즘 이렇게 명령형 프로그래밍을 하시는 분을 많지 않을 거라고 생각하지만, 설명을 위해 조금 과장되게 작성해보았다. 위 코드는 배열 내부의 값들에 &lt;code class=&quot;language-text&quot;&gt;I am&lt;/code&gt;이라는 값을 붙히기 위해 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 사용하여 직접 배열을 순회하고 인덱스를 사용하여 각 원소에 접근하여 값을 재할당하고 있다.&lt;/p&gt;
&lt;p&gt;그리고 이 코드를 읽는 개발자는 자연스럽게 아래와 같은 맥락들을 파악하게 될 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 사용하여 내부의 코드를 반복 실행할 것이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt;라는 변수를 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;으로 초기화하고 반복이 한 번 종료될 때마다 해당 변수에 &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;을 더할 것이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;위에서 선언한 &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt;를 배열의 인덱스로 사용하여 각 원소에 접근한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;템플릿 스트링을 사용하여 배열의 원소 값의 앞 쪽에 &lt;code class=&quot;language-text&quot;&gt;I am&lt;/code&gt;이라는 값을 합성한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;사실 이 코드는 굉장히 많은 맥락을 내포하고 있는 코드이다. 왜냐하면 개발자는 이 코드가 배열 내부의 값들의 앞 쪽에 I am이라는 값을 붙힌다는 동작을 충실히 수행할 수 있는 코드인지만 알면 이 코드를 이해하는데 아무런 무리가 없기 때문이다. 인덱스를 어쩌고 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 어쩌고 하는 것들을 알 필요가 없다는 것이다.&lt;/p&gt;
&lt;p&gt;그렇다면 이 동작을 여러가지 레벨로 추상화해보면 어떻게 될까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 배열을 순회하며 새로운 배열을 만드는 부분까지만 추상화&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;I am &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;v&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 템플릿 스트링으로 문자열을 합성하는 부분까지도 추상화&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addPrefix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;I am&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// map을 사용한다는 사실까지도 추상화&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addPrefixToItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;I am&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// &quot;I am&quot;이라는 문자열을 합성하는 과정까지 추상화&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addIamToItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드들은 위에서 밑으로 내려갈수록 점차 높아지는 추상화 레벨을 보여주고 있다.&lt;/p&gt;
&lt;p&gt;가장 위 쪽에 있는 코드는 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 사용하여 배열을 순회하고 새로운 배열을 반환하는 부분이 추상화되었으니, 이제 개발자는 배열 내부의 원소에 접근하기 위해 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 사용하여 &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt;라는 변수를 직접 초기화하고 관리해야 한다는 맥락이나 새로운 변수로 배열을 선언해야한다는 맥락을 잊을 수 있다.&lt;/p&gt;
&lt;p&gt;즉, 개발자는 배열을 순회하여 기존 원소들을 토대로 만들어낸 새로운 원소를 담은 배열을 생성한다는 &lt;code class=&quot;language-text&quot;&gt;Array.prototype.map&lt;/code&gt;이라는 메소드의 동작만 알고 있으면 되는 것이다. 이렇게 추상화된 코드는 컴퓨터가 수행하는 명령의 절차보다는 개발자가 의도한 행위 자체에 더 초점을 맞춰 표현되게 되므로 이를 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%84%A0%EC%96%B8%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;선언적 프로그래밍&lt;/a&gt;이라고 하기도 한다. &lt;small&gt;(어떻게 할 것인지 보다는, 무엇을 할 것인지에 초점을 맞춰 선언하며 프로그래밍을 진행한다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;조금 더 일상적인 예시를 하나 더 보도록 하자. 아마 여러분은 이미 평소에 다양한 라이브러리를 사용하며 이러한 코드를 작성하는 경험을 하고 있을 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; css &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@emotion/css&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; format &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;date-fns/format&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Date 객체를 생성하고 내부 상태를 오늘 날짜로 초기화하는 행위를 추상화&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; now &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Date 객체를 토대로 원하는 String을 생성하는 행위를 추상화&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formattedDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;now&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;yyyy-MM-dd&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// React.createElement 함수로 VDOM 객체를 생성하는 행위를 추상화&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      css&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        font-size: 1.8rem;
        font-weight: 800;
      &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 작성한 css를 style 태그로 감싸 &amp;lt;head&gt; 태그에 넣는 행위, class를 생성하는 행위를 추상화&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      Today is &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;formattedDate&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 그리고 위 모든 행위를 추상화&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Foo&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; 컴포넌트는 단순히 오늘 날짜를 &lt;code class=&quot;language-text&quot;&gt;2023-03-02&lt;/code&gt;와 같은 포맷으로 보여주는 굉장히 간단한 일을 하는 녀석이지만, 이렇게 작은 컴포넌트조차 동작을 하나하나 뜯어본다면 굉장히 많은 부분이 추상화되어있다는 사실을 알 수 있다.&lt;/p&gt;
&lt;p&gt;만약 여러분이 이 컴포넌트 하나를 만들기 위해 이 모든 행위에 대한 코드를 읽고 이해해야 하거나, 혹은 코드를 직접 작성해서 해결해야 한다면, 더 이상 이 녀석이 간단한 컴포넌트라고 말하기는 어려울 것이다. 즉, 추상화를 통해 간단해보이도록 만들었을 뿐 사실은 전혀 간단하지 않은 것이다. &lt;small&gt;(일단 VanilaJS로 React 구현하는 것부터 빡세다…)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;하지만 위 코드에 적혀있는 주석들이 이야기하고 있는 행위들이 모두 &lt;code class=&quot;language-text&quot;&gt;emotion&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;date-fns&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;react&lt;/code&gt; 등의 라이브러리에 추상화되어있으니, 우리는 이런 복잡한 행위를 신경쓰지 않고 “현재 시간을 렌더하는 것”에만 집중할 수 있게 되었다.&lt;/p&gt;
&lt;p&gt;다시 강조하지만 산업에서의 추상화가 가지는 가치는 복잡한 무언가를 단순해보이게 만들어, 각각의 인간들이 자신의 전문 분야에만 집중하여 협업함으로써 더 고도화되고 복잡한 것을 만들 수 있게 만들어준다는 것이다. 이러한 추상화의 본질적 가치는 우리가 매일 경험하고 있는 프로그래밍의 세계에서도 마찬가지로 통용되고 있는 것이다.&lt;/p&gt;
&lt;p&gt;흔히들 가독성이 부족한 코드에 대한 내용을 이야기할 때 많은 분들이 코드 라인의 수에 대한 이야기를 하시는데, 이것은 단순히 코드 라인의 수가 많다는 것보다는 “모듈의 동작을 이해하기 위해 읽고 분석해야 할 코드의 양이 많다”라는 것에 대한 문제를 이야기하는 것에 가깝다.&lt;/p&gt;
&lt;p&gt;간단하게 생각해서 위 예시의 코드에서 &lt;code class=&quot;language-text&quot;&gt;emotion&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;date-fns&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;react&lt;/code&gt; 라이브러리들의 내용물이 전부 &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; 컴포넌트와 같은 모듈에 선언되어있다면 어떨지 상상해보면 된다.&lt;/p&gt;
&lt;p&gt;아무것도 모르는 상태에서 해당 모듈을 딱 열었을 때 모든 라이브러리의 코드가 한번에 보인다면 내가 어디에서부터 어디까지 읽어야 하는 것인지, 어떤 부분은 그냥 무시하고 넘어가도 되는 것인지, 도대체 이 많은 코드 중에서 버그는 어디에 발생한 것인지 한 번에 파악하기 어려울 것이기 때문이다. 즉, 개발자에게 강요되는 맥락이 과하다.&lt;/p&gt;
&lt;p&gt;조직 내에서 자주 사용되는 모듈을 굳이 어플리케이션 내에서 분리해두는 것이 아닌, 별도 패키지로 구성하여 레지스트리에 배포하고 사용하게 하는 이유도 마찬가지이다. 두 방법 모두 비즈니스 로직과 분리되어있는 것은 마찬가지겠지만, 개발자가 소스코드를 까보는 행위 자체를 아예 차단해버리거나 귀찮게 만듦으로써 분리된 모듈에 대한 맥락을 인식하는 것을 제한하려는 의도인 것이다. &lt;small&gt;(물론 의존성 관리가 가능하다는 점, 여러 어플리케이션 간 재사용이 용이하다는 점도 사내라이브러리의 장점이다)&lt;/small&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 딱 봐도 레퍼런스타면 @quotalab/utils.d.ts로 갈 것처럼 생김&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 그래서 사람들이 소스코드를 까볼 시도를 잘 안 한다&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; uniq &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@quotalab/utils&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 왠지 레퍼런스 타자마자 소스를 볼 수 있을 것만 같은 기분이 든다&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 경로가 이렇게 생기면 뭔가 이상하다 싶을 때 사람들이 바로 소스 까봄 -&gt; 맥락이 노출된다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; uniq &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utils/array&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;small&gt;
    개발자가 소스코드를 까보기 귀찮게 만들어버리면, 괜히 쓸데없는 맥락에 노출될 위험도 줄어든다.
  &lt;/small&gt;
  &lt;br /&gt;
  &lt;br /&gt;
&lt;/center&gt;
&lt;p&gt;결국 우리가 추상화를 해야하는 근본적인 이유는 내 코드를 읽는 다른 개발자, 혹은 미래의 나 자신이 코드의 동작을 이해할 때 너무 과한 맥락에 노출되지 않도록 맥락의 스코프를 만들어주는 것에 가깝다. 마치 컴퓨터를 사용할 때 반도체의 원리를 몰라도 괜찮은 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;그러니 추상화를 진행하는 사람은 다른 사람들이 내 코드의 동작을 이해하고 활용하기 위해 어떤 부분까지 알아야하는지, 어떤 부분은 굳이 몰라도 되는지에 대한 깊은 고민을 해볼 필요가 있다.&lt;/p&gt;
&lt;h3 id=&quot;표현에-대해서-고민하기&quot; style=&quot;position:relative;&quot;&gt;표현에 대해서 고민하기&lt;a href=&quot;#%ED%91%9C%ED%98%84%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-%EA%B3%A0%EB%AF%BC%ED%95%98%EA%B8%B0&quot; aria-label=&quot;표현에 대해서 고민하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;결국 좋은 추상화라는 것이 디테일한 코드를 숨겨, 개발자가 내부를 까보지 않더라도 코드의 동작을 이해하는 비용을 줄일 수 있도록 도와주는 수단이라면, 이제 우리는 추상화해놓은 모듈 내부에 존재하는 코드를 외부 세계에 어떻게 하면 잘 표현하여, 내가 작성한 모듈을 사용하는 개발자가 모듈 내부를 까보지 않아도 동작을 충분히 유추할 수 있을지에 대한 고민을 시작해야 한다.&lt;/p&gt;
&lt;p&gt;흔히들 사람들이 제품에 대한 설명서를 제대로 안 읽는다는 우스갯소리가 있는데, 결국 이런 밈이 가능한 이유도 사용자가 굳이 설명서를 처음부터 끝까지 읽지 않더라도 제품의 사용 방법을 대략적으로 예측할 수 있도록 만들어졌기 때문이다. 즉, 설명서를 읽지 않아도 제품을 사용할 수 있다는 것은 역설적으로 그 제품이 누구에게나 익숙한 UX 패턴을 가지고 있다는 것을 의미한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e76956dc70409588a90016bfaa880d8c/d2602/paper.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEA//EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGpp0lqMQf/xAAaEAACAgMAAAAAAAAAAAAAAAAAEQEQEiEi/9oACAEBAAEFAoNUzHpn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxABAAMAAAAAAAAAAAAAAAAAEAARYf/aAAgBAQAGPwKa2f/EABoQAAMBAAMAAAAAAAAAAAAAAAABESExUXH/2gAIAQEAAT8hXPCzrnSieEMaLRkLk//aAAwDAQACAAMAAAAQOM//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPxBGf//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EBJ//8QAGRABAQEBAQEAAAAAAAAAAAAAAREAITFh/9oACAEBAAE/ECWysEsxQBB8XEhymNvxmKdq2WzJwXZd/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;paper&quot; title=&quot;&quot; src=&quot;/static/e76956dc70409588a90016bfaa880d8c/c08c5/paper.jpg&quot; srcset=&quot;/static/e76956dc70409588a90016bfaa880d8c/0913d/paper.jpg 160w,
/static/e76956dc70409588a90016bfaa880d8c/cb69c/paper.jpg 320w,
/static/e76956dc70409588a90016bfaa880d8c/c08c5/paper.jpg 640w,
/static/e76956dc70409588a90016bfaa880d8c/6a068/paper.jpg 960w,
/static/e76956dc70409588a90016bfaa880d8c/eea4a/paper.jpg 1280w,
/static/e76956dc70409588a90016bfaa880d8c/d2602/paper.jpg 4032w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;당장 필자부터도 간단한 장비에 대해서는 제대로 설명서를 읽지 않는다.&lt;br&gt;사실 워런티 카드가 있다는 것도 방금 알았다.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;사실 대부분의 제품은 설명서를 읽어보지 않더라도, 눈에 보이는 버튼을 몇 번 눌러보고 대충 이것저것 만져보기만 해도 금새 사용법을 유추할 수 있다. 필자도 3년 전에 구매한 모니터 설명서를 아예 뜯지도 않았지만 모니터를 연결하고 사용하는 것에는 아무런 무리가 없었다.&lt;/p&gt;
&lt;p&gt;오히려 설명서를 읽지 않고는 전혀 제품의 사용 방법이나 동작을 유추할 수 없는 제품이라면, 그 제품의 사용법이 일반적이지 않고 너무 어렵다는 이야기이니 소비자들에게 외면받지는 않을까?&lt;/p&gt;
&lt;p&gt;우리가 만들어야 하는 모듈도 이와 똑같다. 설명서를 소스 코드라고 생각해보자. 추상화를 진행하는 개발자는 사용자가 설명서, 즉 소스 코드를 직접 까보지 않더라도 모듈의 사용 방법을 대략적으로라도 유추할 수 있도록 모듈의 동작, 입력/출력에 대해서 명확하게 표현해줘야 하는 것이다.&lt;/p&gt;
&lt;p&gt;우리가 외부 세계에 내부 동작을 표현하고 싶을 때 사용할 수 있는 방법은 크게 2가지 정도이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;변수나 모듈의 이름&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;대상이 함수나 클래스라면, 모듈의 입력과 출력 타입&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addDays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 예시는 &lt;a href=&quot;https://date-fns.org/v2.29.3/docs/addDays&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;addDays&lt;/a&gt;라는 &lt;code class=&quot;language-text&quot;&gt;date-fns&lt;/code&gt; 라이브러리의 함수의 정의이다. 이 함수는 이름만 봐도 특정 대상에게 &lt;code class=&quot;language-text&quot;&gt;days&lt;/code&gt;라는 것을 더하는 역할을 한다는 것을 알 수 있으며, &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; 타입의 값과 &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; 타입의 값을 입력으로 받고 다시 &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; 타입을 출력하고 있으니, 인자로 받은 &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; 객체에 &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt; 만큼의 일자를 더한 &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; 객체를 반환해준다는 동작을 유추해볼 수 있다.&lt;/p&gt;
&lt;p&gt;물론 필자는 이 함수를 호출했을 때 내부에서 정확히 어떤 일이 발생하는지 모른다. 뭐 대충 유추해보자면 &lt;code class=&quot;language-text&quot;&gt;Date.prototype.getDate&lt;/code&gt;로 일자를 가져와서 &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt; 만큼 값을 더하고 어쩌고 하는 행위를 수행하겠지만, 필자가 이 함수를 사용하기 위해 굳이 이런 것까지 알 필요는 없기 때문이다.&lt;/p&gt;
&lt;p&gt;필자는 그저 “이 함수를 사용하면 &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt; 객체에 원하는 만큼의 일자를 더한 새로운 &lt;code class=&quot;language-text&quot;&gt;Date&lt;/code&gt;객체를 얻을 수 있다”라는 사실 하나만 알면 되며, 이러한 사실은 함수의 이름과 입출력 타입에서 충분히 유추해볼 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 만약 이 함수의 이름과 입출력 타입이 이런 느낌이었다면 어땠을까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 301px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/61f22ae5a2042768a1b9ea04e05fc12e/e8ddc/mental.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 125.62499999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAZABQDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAIEAwUG/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3hr2OYSB6ZNIRBA//8QAHRAAAgMAAgMAAAAAAAAAAAAAAQMAAhEEEhQzQf/aAAgBAQABBQLyFx+GMcanjq6gYynJrUO+HMZWhtB6p//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EACEQAAECBQUBAAAAAAAAAAAAAAEAIQIQERJhAxMjMoGR/9oACAEBAAY/Am1IfiughIBxRdrmVPVyPRHbDYlhMTIy/8QAHRABAAIDAAMBAAAAAAAAAAAAAQARITFBEFFx8f/aAAgBAQABPyHHoXr8RM1AsMje4bMjZblCByZagSDJVvYAAVICqep211mWJGNnY6fD4fJ//9oADAMBAAIAAwAAABCTxTz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAdEAEBAAICAwEAAAAAAAAAAAABEQAhMVFBYbGh/9oACAEBAAE/ECqLiaIdTB4OoAQhvDuXzibAguK+NczNsBZomzQ9kwx5R6g3T6Zz7uEkMKpZvALl2fuFpvKgUdc5O4gYbd5+Bz7/AKY4P//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;mental&quot; title=&quot;&quot; src=&quot;/static/61f22ae5a2042768a1b9ea04e05fc12e/e8ddc/mental.jpg&quot; srcset=&quot;/static/61f22ae5a2042768a1b9ea04e05fc12e/0913d/mental.jpg 160w,
/static/61f22ae5a2042768a1b9ea04e05fc12e/e8ddc/mental.jpg 301w&quot; sizes=&quot;(max-width: 301px) 100vw, 301px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;도대체 무슨 일을 하는 녀석인지 알 수가 없다...!!!&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;일단 이 함수도 이름이 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt;이니 뭔가를 더하긴 더하는 것 같은데, 도대체 뭘 더한다는 것인지, 그리고 함수가 어떤 값을 반환하는지 전혀 감을 잡을 수가 없다. 왜냐하면 이 함수는 입출력에 대한 타입이나 변수명 등으로 자신 내부의 동작을 충실하게 표현하고 있지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;만약 여러분이 이 함수를 사용하는 사용자라면 이 함수의 동작을 믿고 사용할 수 있을까? 아니 믿는 것은 둘째치더라도 도대체 이 함수가 뭐 하는 녀석인지 감을 잡을 수 없으니 아예 사용 자체를 안 하게 될 수도 있을 것 같다.&lt;/p&gt;
&lt;p&gt;혹여나 어떻게든 사용을 한다고 해도 드러난 표현만으로는 함수의 동작을 이해할 수 없어 저 함수의 소스 코드를 까봐야지만 해당 함수를 사용할 수 있을테니, 복잡한 맥락을 감출 수 있다는 추상화의 장점 또한 잃어버리게 된다.&lt;/p&gt;
&lt;p&gt;이런 경우 외에도 함수의 인자가 지나치게 많다던가, 함수의 이름이 함수의 동작과 다른 맥락을 표현하고 있다던가 하는 것들 또한 내 코드를 사용하는 개발자가 함수의 역할을 쉽게 유추하지 못 하게 방해하는 요소일 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 표현의 중요성은 비단 함수가 아니더라도 클래스나 일반 변수 등 모듈 밖으로 노출될 수 있는 모든 개념들에게 공통적으로 적용되는 사항이며, 내가 작성한 코드를 사용할 다른 개발자나 혹은 미래의 나 자신을 배려하는 설계의 기초가 되는 것이기도 하다.&lt;/p&gt;
&lt;h3 id=&quot;입력의-자유도를-제어해서-좋은-dx-만들기&quot; style=&quot;position:relative;&quot;&gt;입력의 자유도를 제어해서 좋은 DX 만들기&lt;a href=&quot;#%EC%9E%85%EB%A0%A5%EC%9D%98-%EC%9E%90%EC%9C%A0%EB%8F%84%EB%A5%BC-%EC%A0%9C%EC%96%B4%ED%95%B4%EC%84%9C-%EC%A2%8B%EC%9D%80-dx-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;입력의 자유도를 제어해서 좋은 dx 만들기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;추상화된 모듈의 동작을 외부 세계에 제대로 표현하는 것에 대해 익숙하다면 이제는 내 모듈을 사용하는 사용자들의 DX에 대해서 깊게 고민해볼 차례이다.&lt;/p&gt;
&lt;p&gt;물론 DX를 만들어내는 요인은 여러가지가 있겠지만, 그 중에서도 필자가 가장 신경쓰는 부분 중 하나는 바로 “기능을 어디까지 열어줄 것이냐”이다. 왜냐하면 이 의사결정에 의해 필자가 개발한 모듈을 사용하는 사람들의 작업 리소스, 인지해야하는 맥락의 정도, 휴먼 에러의 가능성 등이 달라질 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;예를 들어 간단한 버튼 컴포넌트 하나를 개발한다고 생각해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropsWithChildren&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 컴포넌트는 외부 세계에 자신의 기능을 많이 드러내지 않고 있는, 이른바 기능이 닫힌 컴포넌트이다. 애초에 컴포넌트 자체에서 &lt;code class=&quot;language-text&quot;&gt;children&lt;/code&gt;을 꽂아넣을 수 있는 기능만을 제공하고 있으니, 이런 컴포넌트를 사용하는 사용자는 선택의 자유도가 높지 않다.&lt;/p&gt;
&lt;p&gt;그나마 &lt;code class=&quot;language-text&quot;&gt;children&lt;/code&gt;이라는 프로퍼티는 합성을 통해 마음껏 외부에서 주입할 수 있겠지만, 그 외에 &lt;code class=&quot;language-text&quot;&gt;button&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt;을 변경하고 싶다던가, 클릭 이벤트 핸들러를 사용하고 싶다던가 하는 것들은 전부 불가능하기 때문이다.&lt;/p&gt;
&lt;p&gt;그러나 제공해주고 있는 기능 자체가 매우 제한적이고 적기 때문에, 이 컴포넌트를 사용하는 사용자는 컴포넌트의 사용법에 대해서 크게 고민해야 할 필요가 사라졌다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-tsx line-numbers&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ComponentProps&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;반면 위 컴포넌트는 React의 &lt;code class=&quot;language-text&quot;&gt;button&lt;/code&gt; 컴포넌트가 기존에 제공하고 있던 모든 기능을 입력으로 받을 수 있도록 설계되었다. 이런 컴포넌트를 사용하는 사용자는 자신이 원하는 &lt;code class=&quot;language-text&quot;&gt;button&lt;/code&gt; 컴포넌트의 프로퍼티를 모두 사용할 수 있으니 자유도가 높은 개발을 할 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;그러나 컴포넌트가 제공하는 프로퍼티가 매우 많기 때문에 사용하는 입장에서도 자신의 목적과 다소 어긋난 맥락들에 지속적으로 노출될 수 있다. 필자는 이런 상황을 주로 “컴포넌트가 개발자에게 고민을 강요한다” 표현한다.&lt;/p&gt;
&lt;p&gt;또한 이 컴포넌트를 개발한 사람 입장에서는 사용자가 어떤 방식으로 내가 설계한 모듈을 사용하게 될 지에 대한 모든 경우의 수를 예측할 수 없으니 그만큼 버그나 설계 의도와 벗어난 사용 사례가 늘어날 수 있다는 리스크도 있다.&lt;/p&gt;
&lt;p&gt;즉, 추상화된 모듈을 만드는 개발자는 모듈의 입력 범위를 제어함으로써, 사용자가 어떤 방식으로 내 모듈을 사용하게 만들지도 어느 정도 제어할 수 있다는 것이다. 그러니 이런 입력에 대한 설계는 모듈을 사용하는 개발자의 DX와도 직결된다.&lt;/p&gt;
&lt;p&gt;이런 고민은 주로 다양한 개발자들이 함께 사용해야하는 사내라이브러리 등을 개발할 때 주로 하게 되는데, 특히 디자인 시스템 같은 경우는 이러한 인터페이스를 설계할 때 디자이너 분들의 의도까지 함께 녹여야하니 더 복잡한 상황이 펼쳐진다. &lt;small&gt;(코드에 정의된 프로퍼티들이 Figma, Framer 등에 정의된 프로퍼티와 유사할수록 개발자/디자이너 간 커뮤니케이션 비용이 낮아진다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;사실 모듈의 입력을 많이 열어줄 것이 좋냐, 혹은 제한할 것이 좋냐에 대한 정답은 없다. 이는 모듈을 사용하는 사용자들의 전문성, 모듈의 목적과 용도, 혹은 오픈소스와 같은 불특정 다수의 사용자인지 사내라이브러리같은 제한된 그룹의 사용자인지에 따라서도 달라질 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;이렇게 비슷한 역할을 하는 도구라고 해도 제공해주는 기능의 범위를 제한함으로써 사용자의 경험을 만들어나가는 개념은 비단 코드 뿐 아니라 우리의 일상 속에서도 흔히 볼 수 있는 개념이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6754c9f5811dfe2b0eeedef280d18fc0/12609/synth2.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 49.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAFkNwEFkP/EABwQAAAGAwAAAAAAAAAAAAAAAAABAgMSEwQQEf/aAAgBAQABBQJ1b103xjyriQ4Wv//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAQACAgMAAAAAAAAAAAAAAAEAAhExECIy/9oACAEBAAY/ArlLOBnpndyzRNcf/8QAHBABAAEEAwAAAAAAAAAAAAAAAQARITFhQVGR/9oACAEBAAE/IcIAU6hHT5g3l1bzqa3kAMFJ/9oADAMBAAIAAwAAABD0D//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB0QAQEAAgEFAAAAAAAAAAAAAAERADEhQVGB0fH/2gAIAQEAAT8QUDEIk4DNYk0eD1htaNXUvGO0BVirny2EwB2CZ//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;synth2&quot; title=&quot;&quot; src=&quot;/static/6754c9f5811dfe2b0eeedef280d18fc0/c08c5/synth2.jpg&quot; srcset=&quot;/static/6754c9f5811dfe2b0eeedef280d18fc0/0913d/synth2.jpg 160w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/cb69c/synth2.jpg 320w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/c08c5/synth2.jpg 640w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/6a068/synth2.jpg 960w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/eea4a/synth2.jpg 1280w,
/static/6754c9f5811dfe2b0eeedef280d18fc0/12609/synth2.jpg 3000w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 498px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a9317f4f11dd17948f8a328924b4d7d/4e442/piano.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 67.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAADBv/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAV5CGdNHj//EABwQAAMAAQUAAAAAAAAAAAAAAAECAwAEERIUMf/aAAgBAQABBQJtau/YocnfkqIAlLk5Pz//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAeEAACAQMFAAAAAAAAAAAAAAAAASEikbECAxFBUf/aAAgBAQAGPwKi5GCVK8HudI400othH//EABwQAAICAwEBAAAAAAAAAAAAAAERADEhQYFRcf/aAAgBAQABPyHEAx6jWroWPJqMiLMQnOAzA5E21Z+mDlF//9oADAMBAAIAAwAAABAkD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB4QAQACAwACAwAAAAAAAAAAAAEAESExcUFhobHw/9oACAEBAAE/ELogc3huIwrZIHhtX65bX4TGaHCdltPnQb+hwdywJWqV/KP1DV1iT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;piano&quot; title=&quot;&quot; src=&quot;/static/5a9317f4f11dd17948f8a328924b4d7d/4e442/piano.jpg&quot; srcset=&quot;/static/5a9317f4f11dd17948f8a328924b4d7d/0913d/piano.jpg 160w,
/static/5a9317f4f11dd17948f8a328924b4d7d/cb69c/piano.jpg 320w,
/static/5a9317f4f11dd17948f8a328924b4d7d/4e442/piano.jpg 498w&quot; sizes=&quot;(max-width: 498px) 100vw, 498px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;전문적인 오디오 지식이 있는 사람들은 기능이 다양한 신디사이저를 적재적소에 활용하지만&lt;br&gt;전문적인 지식이 없다면 차라리 기능이 제한된 디지털 피아노를 사용하는 게 더 목적에 맞을 수 있다.
  &lt;small&gt;
&lt;/small&gt;&lt;/small&gt;&lt;/center&gt;
&lt;p&gt;신디사이저라는 악기는 오디오 파형을 직접적으로 변경해가면서 원하는 소리를 만들 수 있는 악기이기에 사용자에게 무궁무진한 자유도를 가져다 주지만, 만약 오디오에 대한 전문적인 지식이 없는 사람에게 이런 악기를 가져다준다면 제대로 사용하지도 못 하고 이것저것 만져보다가 당근마켓에 올려버릴 가능성이 높다.&lt;/p&gt;
&lt;p&gt;게다가 이렇게 복잡한 장비들은 전압에 민감하게 반응하도록 설계된 경우도 있어, 사용자의 부주의로 인해 자칫 장비가 망가질 위험도 존재한다.&lt;/p&gt;
&lt;p&gt;그러니 오히려 전문적인 지식이 없는 사람이거나, 아예 이런 자유도가 필요없는 사람에게는 신디사이저보다 기능은 제한되어있지만 비전문가도 편하게 접근하여 이쁜 소리를 낼 수 있는 디지털 피아노가 더 적당할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;즉, 단순히 전문가가 더 많이 알고 있으니 기능을 노출시켜주자는 개념보다는 해당 도구가 사용되어야 하는 상황과 사용하는 사람이 도구의 원리에 대해서 알 필요가 있냐, 없냐에 따라 달라지는 개념이다. 애초에 단순히 피아노를 치고 싶어하는 사람이 신디사이저 같이 복잡하고 기능이 다양한 악기를 살 필요가 없다는 말이다.&lt;/p&gt;
&lt;p&gt;필자가 예시로 들었던 악기가 아니더라도 자동차의 수동 변속기와 자동 변속기, 휴대폰과 HAM에 사용하는 무선송수신기, C와 JavaScript처럼 비슷한 기능을 제공하지만 도구의 목적과 사용자의 페르소나에 따라 기능의 범위를 제한하는 개념은 무궁무진하게 많다.&lt;/p&gt;
&lt;p&gt;결국 우리는 사용자가 도구의 원리를 알 필요도 없는 상황에서 넓은 범위의 입력을 구현하여 괜히 고민하도록 만들거나, 반대로 도구의 원리를 이해하고 다양한 상황에 재사용해야하는 상황에서 좁은 범위의 입력을 구현하여 사용처를 제한해버리는 설계를 하지 않도록 주의해야 하는 것이다.&lt;/p&gt;
&lt;p&gt;앞서 이야기했던 것처럼 이는 비즈니스나 조직의 상황, 도구의 목적, 사용자들의 니즈 등의 문제를 모두 고려해서 의사결정해야하는 부분인 만큼 어떠한 정답이 있는 문제는 아니지만, 적어도 나 이외에 사용자들이 함께 사용해야하는 모듈을 추상화하여 만들어야 하는 입장이라면 한번 쯤 고민해볼만한 문제라고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;오늘날 지구 상에 존재하는 모든 개발자들은 다른 개발자들과 긴밀한 협력 관계에 놓여있다. 물론 프리랜서나 초기 스타트업에서 일하는 분들처럼 혼자서 개발하는 분들도 있겠지만, 결국 그 분들도 다른 사람이 고안하고 개발한 도구를 가져다 쓰는 것을 피할 수는 없으며, 내가 작성한 코드를 무덤까지 가져가는 것도 아니니 언젠가는 다른 개발자가 내 코드를 이어받는 그 날이 반드시 찾아온다.&lt;/p&gt;
&lt;p&gt;결국 내가 지금 작성한 코드를 다른 사람이 읽고 이해해야하는 순간은 피할 수 없기 때문에, 우리는 기본적으로 사람이 이해하기 좋은 코드를 작성하는 것이 힘을 기울일 수 밖에 없는 것이다. 심지어 정말로 혼자서만 작성하는 코드라고 해도, 결국 미래의 나 자신이 모든 코드의 동작을 기억하고 있을거란 보장이 없으니 미래의 나 자신을 위해서라도 이런 코드를 작성해야한다.&lt;/p&gt;
&lt;p&gt;결국 프로그래밍에서의 추상화는 복잡한 원리를 가진 무언가 또는 컴퓨터는 이해하기 쉽지만 사람은 이해하기 어려운 무언가를 사람이 이해하기 쉽도록 만드는 과정이다. 물론 좋은 추상화를 하는 방법이나 노하우는 사람마다 다를 수 있지만, 결국 이러한 추상화의 본질 자체는 바뀌지 않는 것이다.&lt;/p&gt;
&lt;p&gt;필자는 개인적으로 추상화에 대한 방법이나 노하우는 그렇게 중요하지 않다고 생각한다. 앞서 말한 것처럼 변경에 열린 설계를 하기 위한 패턴이나 방법들은 이미 인터넷에 널려있고, 이미 깔끔하게 정리되어있는 개념들이 많기 때문에 그 정보들을 읽고 몇 번 사용해보는 것만으로도 익히는 것에는 크게 문제가 없을 것이다.&lt;/p&gt;
&lt;p&gt;다만 추상화라는 선물이 우리에게 가져다주는 근원적 가치에 대한 이해가 없다면, 이렇게 공부한 정보들이 나에게 정말로 유용한 것인지 아닌지에 대한 가치 판단마저도 하기 어렵게 되어버릴 수 있다.&lt;/p&gt;
&lt;p&gt;개발자들은 모든 문제를 해결할 수 있는 만능적인 해결책은 존재하지 않는다는 “No Silver Bullet”이라는 문장을 자주 사용한다. 이 문장이 의미하는 것처럼 우리가 접하는 수많은 정보들은 모두 이익만을 가져다주는 것이 아니며, 때로는 내가 내린 기술적 의사결정으로 인해서 오히려 잃는 것이 발생할 수도 있다.&lt;/p&gt;
&lt;p&gt;이런 상황 속에서 개발자는 항상 내가 내리는 의사결정이 가져다주는 이익과 그와 반대로 잃게되는 손해에 대해서 냉철하게 저울질해보고 판단해야하며, 필자는 이러한 의사결정에 도움이 되는 것이 바로 “해당 기술이 가져다주는 근원적 가치에 대한 이해”라고 생각한다.&lt;/p&gt;
&lt;p&gt;물론 이 포스팅에서 필자가 작성한 것이 정답이라는 이야기는 아니다. 이 내용은 필자가 지금까지 개발자로 일을 하면서 고민했던 내용에 불과하며, 전 세계에 존재하는 수천만 명의 개발자들 또한 각각 저마다의 고민 끝에 내려진 정의를 가지고 있으리라 생각한다.&lt;/p&gt;
&lt;p&gt;필자가 고민해온 이 내용들이 독자 여러분이 내렸던 혹은 앞으로 내릴 추상에 대한 정의에 조금이나마 도움이 되길 바라면서, 이상으로 추상이란 무엇일까 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[What I learned about growth and leadership at Toss]]></title><description><![CDATA[In this post, I want to casually write about my experiences and realizations from the 2.5 years I spent at Toss. I actually left Toss back…]]></description><link>https://evan-moon.github.io/2022/05/07/toss-retrospective/en/</link><guid isPermaLink="false">20220507-toss-retrospective-en</guid><pubDate>Sat, 07 May 2022 01:53:50 GMT</pubDate><content:encoded>&lt;p&gt;In this post, I want to casually write about my experiences and realizations from the 2.5 years I spent at Toss. I actually left Toss back in March, but between getting settled at the new place and dealing with personal stuff, three months flew by before I could finally sit down to write this retrospective.&lt;/p&gt;
&lt;p&gt;After working as a developer for about 7 years and bouncing around different companies, my time at Toss definitely stands out. The culture was unique, my colleagues were brilliant, and I personally got the opportunity to grow from just being another developer to someone who could help grow the entire team.&lt;/p&gt;
&lt;!--more --&gt;
&lt;h2 id=&quot;how-does-toss-work-so-fast&quot; style=&quot;position:relative;&quot;&gt;How does Toss work so fast?&lt;a href=&quot;#how-does-toss-work-so-fast&quot; aria-label=&quot;how does toss work so fast permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Starting around late 2021, I got feedback from people around me that I should stop hanging out with only developers and meet people from other fields. So I started having coffee chats with various folks - C-level executives, HR people, VCs doing investment screening, and others - where we’d ask each other questions about what we were curious about.&lt;/p&gt;
&lt;p&gt;After several of these coffee chats, I’d sometimes visit their companies to meet the developers directly, suggest solutions to their technical challenges, and if I was curious about their business, I’d even get the chance to meet co-founders for deeper conversations. &lt;small&gt;(Reading this back, it sounds kind of like dating)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I got asked a lot of questions during this process, but aside from technical stuff, the question I heard most often - and usually right at the beginning - was this:&lt;/p&gt;
&lt;center&gt;
  &lt;br&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;img src=&quot;/ba4b53d43a9bececa2dac7b1b849aee8/question.gif&quot; width=&quot;100%&quot;&gt;
  &lt;/div&gt;
  &lt;small&gt;How does Toss work like that?&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;In the IT industry, Toss has a somewhat two-sided reputation. The positive image is that it’s a team that works really well and fast. The negative image is that it’s a sweatshop with too much work.&lt;/p&gt;
&lt;p&gt;Of course, from an employee’s perspective like mine, both working well and having personal time are important, so I’d weigh those two factors. But for people running companies or investors who’ve put money in, they’re naturally more interested in the first factor - “how to work fast and well” - so that question really meant “how can you work that fast and that well?”&lt;/p&gt;
&lt;h3 id=&quot;dri-culture-where-you-chart-your-own-path&quot; style=&quot;position:relative;&quot;&gt;DRI culture where you chart your own path&lt;a href=&quot;#dri-culture-where-you-chart-your-own-path&quot; aria-label=&quot;dri culture where you chart your own path permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;DRI (Directly Responsible Individual) is exactly what it sounds like - the person with final decision-making authority on a matter. This concept was first introduced to Apple by Steve Jobs, and it’s deeply embedded in Toss as well.&lt;/p&gt;
&lt;p&gt;Personally, I think the driving force behind Toss’s fast pace is a culture where each person’s final decision-making authority as a DRI is tremendously respected. At Toss, decision-making power isn’t concentrated in the CEO - it’s distributed across the entire team.&lt;/p&gt;
&lt;p&gt;In reality, Toss is a place where leaders can’t easily dictate a product’s direction. That’s because the DRI for each product belongs to the silo building that product, and specifically to that silo’s PO (Product Owner).&lt;/p&gt;
&lt;p&gt;Of course, the CEO’s authority definitely exists at Toss, and the weight of the CEO’s words is heavier than others’. But what made Toss different from other companies was that you’d often see POs fighting with the CEO, and the POs would frequently win. &lt;small&gt;(Watching a CEO and PO duke it out to the death isn’t something you typically see at companies of any significant size)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;At Toss, being a DRI is like a sacred, inviolable zone. Having a DRI means your colleagues trust your abilities in that area, and losing your DRI means losing your colleagues’ trust and becoming someone the team doesn’t need anymore. So everyone fights tooth and nail to defend their DRI by earning trust from colleagues and trying to help the team.&lt;/p&gt;
&lt;p&gt;In other words, even if you’re the CEO, if you try to crush and overturn someone’s DRI with leadership authority, the reaction won’t be “Well, the CEO wants it, so I guess we have to…” but rather “Who the hell are you to threaten my DRI?” At Toss, messing with someone’s DRI tends to really piss people off. &lt;small&gt;(Crudely speaking, you might trigger someone’s rage button)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;That’s why I say that at Toss, even the CEO - the company’s owner - can’t easily tell product development what to do. In fact, there are cases where a PO pushed forward with an item the CEO said not to do, and succeeded. These successful experiences accumulate and make the culture of respecting DRIs even stronger.&lt;/p&gt;
&lt;p&gt;Of course, the CEO has more business insights than POs because of years in this domain, but since the DRI for product direction belongs to that silo’s PO, the Toss CEO usually plays more of an advisor role.&lt;/p&gt;
&lt;p&gt;And thanks to this DRI system, each silo can determine their product’s direction themselves, develop it, observe the results, and iterate to evolve the product. Since there’s no pointless reporting or checking procedures in this process, the people making the product can decide “I want to make this!” and develop something like the &lt;a href=&quot;https://blog.toss.im/article/disasterfund-behindstory&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Disaster Relief Fund&lt;/a&gt; in just a day or two.&lt;/p&gt;
&lt;p&gt;I felt that the reason Toss can work fast and have fun doing it starts with this complete delegation of authority. Since it’s not about someone ordering you to make something, but team members coming up with their own ideas and evolving the product, the level of attachment to the product can’t help but be high.&lt;/p&gt;
&lt;h3 id=&quot;a-culture-tolerant-of-failure&quot; style=&quot;position:relative;&quot;&gt;A culture tolerant of failure&lt;a href=&quot;#a-culture-tolerant-of-failure&quot; aria-label=&quot;a culture tolerant of failure permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Toss is an organization that’s very forgiving of failures from new attempts. There was even a core value about having the courage to fail fast, and they held events like Failure Party where people shared their failure cases across the company.&lt;/p&gt;
&lt;p&gt;The reason for this culture is pretty simple - to provide an environment where people can try new things without fear of failure.&lt;/p&gt;
&lt;p&gt;Physicist Safi Bahcall, in his book &lt;a href=&quot;http://www.yes24.com/Product/Goods/90061659&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Loon Shots&lt;/a&gt;, says that one formula for success is to rapidly and frequently attempt projects that the majority ignores and neglects. As these attempts accumulate, you eventually cross a critical threshold, and that’s when you can finally shoot moon shots.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 458px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/f7c3c/loon_shots.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 148.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgQF/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAMBAv/aAAwDAQACEAMQAAAB3svJyhhTllsJGlhI3//EAB8QAAIBBAIDAAAAAAAAAAAAAAECAwAEEhMRMRQhM//aAAgBAQABBQJI01646uFUOny6q69SLPivkGpGzMfAdCAB1//EABcRAAMBAAAAAAAAAAAAAAAAAAABEBH/2gAIAQMBAT8BuI//xAAXEQEBAQEAAAAAAAAAAAAAAAABABAS/9oACAECAQE/AYzpL//EACMQAAEDAwIHAAAAAAAAAAAAAAABAhEhMTISURAiQWFxkaH/2gAIAQEABj8CbyNtsYM9CQ1tugyk0MFE8CJpsm5h9EXsS+qDtVZtw//EAB0QAQADAAMAAwAAAAAAAAAAAAEAESExYXFBkfD/2gAIAQEAAT8hsbuNRuQsbr+MSuR1ZywHVePIuKbxhon7bHHvQQ1IK4dgpKRrDPiEYt9MKabn/9oADAMBAAIAAwAAABCD37D/xAAZEQACAwEAAAAAAAAAAAAAAAAAAREhMVH/2gAIAQMBAT8QoekLgnXB/8QAGBEBAAMBAAAAAAAAAAAAAAAAAQARITH/2gAIAQIBAT8QVvsTRN7ccQz/xAAeEAEBAAIBBQEAAAAAAAAAAAABEQAhMUFhcZGhUf/aAAgBAQABPxCotV+Ic/cmiRtuveYKEIWYnBm1V6k0x3tSqBqb+4AGEd8FgixBYS4shRBTrGdFOtu1v3LqRBzj48X3iKyd3X1eOT1kpZ5uf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;loon shots&quot; title=&quot;&quot; src=&quot;/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/f7c3c/loon_shots.jpg&quot; srcset=&quot;/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/0913d/loon_shots.jpg 160w,
/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/cb69c/loon_shots.jpg 320w,
/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/f7c3c/loon_shots.jpg 458w&quot; sizes=&quot;(max-width: 458px) 100vw, 458px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;An environment where you can attempt projects that many point fingers at and not be criticized for failure is what ultimately creates moon shots&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Toss created an environment where you can comfortably shoot these loon shots. The focus isn’t on the fact of failure itself, but on recognizing what was learned from the failure and sharing it with others so the same failure doesn’t happen twice.&lt;/p&gt;
&lt;p&gt;Of course, sayings like “failure can’t be prevented” or “you grow by using failure as a stepping stone” are things many people already know, but actually infusing a culture that doesn’t fear failure into an organization is harder than you’d think.&lt;/p&gt;
&lt;p&gt;That’s why Toss runs campaigns like Failure Party to internally promote “how tolerant we are of failure,” or has the culture team and leaders constantly talk about how “it’s okay to fail.”&lt;/p&gt;
&lt;p&gt;In other words, to establish a culture where organization members don’t fear failure, you can’t just not criticize someone when they experience failure - you need more proactive actions alongside that.&lt;/p&gt;
&lt;p&gt;The truth is, most people have experienced more cultures that dismiss failure rather than encourage it throughout their lives, so even with these proactive actions, a culture that doesn’t fear failure won’t take root overnight. This kind of culture slowly seeps in through efforts to build it being consistently performed from the moment the company is founded until the day it shuts down.&lt;/p&gt;
&lt;p&gt;Plus, culture has a kind of inertia that tries to maintain the current state, so introducing it midway costs more than building it from the start. If you want to establish a culture that doesn’t fear failure in your team, you’ll need to continuously think about and perform actions that are at least more radical and proactive than Toss’s.&lt;/p&gt;
&lt;h3 id=&quot;the-ceo-also-works-to-maintain-the-culture&quot; style=&quot;position:relative;&quot;&gt;The CEO also works to maintain the culture&lt;a href=&quot;#the-ceo-also-works-to-maintain-the-culture&quot; aria-label=&quot;the ceo also works to maintain the culture permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;But settling these kinds of cultures into a typical startup isn’t easy. That’s because corporate culture is most influenced by the CEO, and from the CEO’s perspective, handing over DRIs to individual contributors or just watching team members fail requires quite a bit of courage.&lt;/p&gt;
&lt;p&gt;Usually we vent this kind of not-quite-complaint over drinks with friends:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our CEO micromanages even the tiniest details, it’s exhausting… Do they not trust us…? If this is how it is, why did they hire me?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Of course, I sympathize with this. Generally, CEOs are experts in management, not product development experts. Honestly, from the perspective of the PO, designer, or developer actually building that product, it can be annoying and frustrating to have someone who isn’t even an expert tell you what to do.&lt;/p&gt;
&lt;p&gt;But if you flip the perspective for a moment, that’s actually more natural and human. Because the CEO is the person who can grab the biggest profit when the company does well, but conversely, they’re also the person bearing the biggest risk when it fails.&lt;/p&gt;
&lt;p&gt;Generally, when startups receive investment, investors evaluate the company’s value, calculate the price per share based on that valuation, and invest by transferring shares. But the process of investors investing in startups is a bit different from how we normally buy and sell stocks.&lt;/p&gt;
&lt;p&gt;To minimize investment risk, investors use methods like buying corporate bonds to lend money and later converting the bonds to shares &lt;small&gt;(CB, convertible bonds)&lt;/small&gt;, or setting conditions where they can demand the company buy back shares whenever they want or continuously receive dividends &lt;small&gt;(RCPS, redeemable convertible preferred shares)&lt;/small&gt;, or actively using clauses that let them demand their shares be sold along when the controlling shareholder sells their stake &lt;small&gt;(Tag-along)&lt;/small&gt; as safety nets.&lt;/p&gt;
&lt;p&gt;Especially investors with preferred shares like RCPS have priority over common shareholders in various rights, and the problem is that CEOs also hold common shares.&lt;/p&gt;
&lt;p&gt;So if an investor with preferred shares exercises rights like receiving priority distribution of remaining assets over common shareholders when the company fails and is liquidated, or the right to force the company to buy back shares at any point during the contract period, situations can arise where the company must honor these rights even at a loss.&lt;/p&gt;
&lt;p&gt;In other words, startup investment is absolutely not free, and if the business doesn’t go well, the CEO can definitely suffer significant financial losses too. And as you all know, these amounts aren’t pocket change.&lt;/p&gt;
&lt;p&gt;Honestly, in this situation, delegating all decision-making authority about product direction to employees or tolerating failure isn’t easy at all. Even with employees you hired yourself, it’s hard to trust they’ll think “this is my business” like you do.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a133e4bae8986cb83c7de28c3bdd1b9e/8e1fc/out.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQT/xAAUAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAGGvELgEEf/xAAbEAACAgMBAAAAAAAAAAAAAAABAgADBBEhIv/aAAgBAQABBQJum5C6lmaVesewRjs//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAECIRBRcf/aAAgBAQAGPwLjKtxLbJN7z//EABsQAQADAQADAAAAAAAAAAAAAAEAESExQWFx/9oACAEBAAE/IQhuW1B1uo9xy3P2PoXyg47ZvY1r1n//2gAMAwEAAgADAAAAEBzv/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EBEyb//EABYRAQEBAAAAAAAAAAAAAAAAAAEQIf/aAAgBAgEBPxANn//EABwQAQADAQEAAwAAAAAAAAAAAAEAESFRQTFxof/aAAgBAQABPxCzq5z6S/2GSgoqgppfcKmfsrVhyvIlQOgjZx4pr5PYle9F6z//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;out&quot; title=&quot;&quot; src=&quot;/static/a133e4bae8986cb83c7de28c3bdd1b9e/c08c5/out.jpg&quot; srcset=&quot;/static/a133e4bae8986cb83c7de28c3bdd1b9e/0913d/out.jpg 160w,
/static/a133e4bae8986cb83c7de28c3bdd1b9e/cb69c/out.jpg 320w,
/static/a133e4bae8986cb83c7de28c3bdd1b9e/c08c5/out.jpg 640w,
/static/a133e4bae8986cb83c7de28c3bdd1b9e/8e1fc/out.jpg 900w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Wait, this guy&apos;s defending CEOs? Turns out he was on management&apos;s side all along?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The reason I’m saying all this isn’t “so let’s understand CEOs’ micromanaging” - it’s actually the opposite. What I want to say is that despite shouldering these huge risks, if you want to succeed in business, the CEO must be the first to work on building a culture of trusting team members and delegating authority.&lt;/p&gt;
&lt;p&gt;No matter how amazing a CEO is, one person can’t do everything in the world well. Plus, if you’ve recruited senior-level team members, that means they’re much more veteran than the CEO in their field, and a proper senior can definitely track business-level issues while making decisions.&lt;/p&gt;
&lt;p&gt;In other words, it’s more efficient to delegate authority to team members and collaborate with each person handling their specialty rather than the CEO telling everyone what to do.&lt;/p&gt;
&lt;p&gt;Of course, working together means you’ll see trusted team members fail sometimes and you might be disappointed. But once a CEO starts micromanaging because of a few failures by team members, even if your team members could do well in some areas, they’ll give up on showing their abilities thinking “they’ll do whatever they want anyway,” or in the worst case, capable employees will leave the company.&lt;/p&gt;
&lt;p&gt;If the CEO interferes in every little thing and restricts my abilities, why would I stay here when it’s neither fun nor conducive to growth?&lt;/p&gt;
&lt;p&gt;If this situation repeats, the company will either see all the people who actively make decisions and demonstrate their abilities leave, or become passive, and you’ll end up with a half-assed organization where employees can’t decide anything themselves unless the CEO makes every decision.&lt;/p&gt;
&lt;p&gt;The reason I still think Toss’s CEO Seunggun is amazing isn’t simply because he works well or is smart - it’s because he recognizes these issues himself and is directly leading the culture of delegating authority.&lt;/p&gt;
&lt;p&gt;No matter how great someone is, as long as they’re human, they’d naturally have fear of business failure, but overcoming that fear, fully trusting team members, delegating authority, and building a culture that encourages failure - that’s not normal-person-level mentality.&lt;/p&gt;
&lt;p&gt;Of course, the Toss culture I mentioned earlier about DRIs or an environment where you can freely experience failure might not be the right answer. In fact, Toss keeps trying new things and evolving the culture too.&lt;/p&gt;
&lt;p&gt;But whatever that culture is, it’s hard for it to take root in an organization without the CEO’s - the leader’s - attention. No matter how much team members interested in culture run around trying things, if the CEO just says “don’t do that,” everything rolls back, making their efforts rather meaningless. And even if you somehow establish a culture, if the leader doesn’t make efforts to maintain it, other team members won’t bother maintaining it either.&lt;/p&gt;
&lt;h2 id=&quot;problems-of-a-rapidly-growing-organization&quot; style=&quot;position:relative;&quot;&gt;Problems of a rapidly growing organization&lt;a href=&quot;#problems-of-a-rapidly-growing-organization&quot; aria-label=&quot;problems of a rapidly growing organization permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Actually, while Toss’s culture had many interesting aspects and was a new experience, the most valuable thing I experienced at this company wasn’t the culture.&lt;/p&gt;
&lt;p&gt;The most valuable thing I got from Toss was the opportunity to seriously think about “what is a senior developer” while actually performing that role.&lt;/p&gt;
&lt;p&gt;When I had my first salary negotiation after joining Toss, I got feedback to become someone who could grow the team, not just myself.&lt;/p&gt;
&lt;p&gt;I’d already been thinking about what being a senior means, and I was heading in a somewhat similar direction. That’s why I was trying to gain experience helping and growing others through things like the &lt;a href=&quot;https://lubycon.medium.com/%EC%84%B8-%EB%B2%88%EC%A7%B8-%EB%A9%98%ED%86%A0%EB%A7%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0-27c156e62568&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Lubycon Mentoring Project&lt;/a&gt; with friends.&lt;/p&gt;
&lt;p&gt;But I didn’t think I’d be able to exercise that kind of influence within Toss, so when I heard that feedback, I thought:&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6817a30c0c9d171cfd58a1f1f56210d6/65f94/what.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 86.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAUC/9oADAMBAAIQAxAAAAHBrlep5CB/ecLTsETv/8QAGxAAAwACAwAAAAAAAAAAAAAAAAECAzERIUH/2gAIAQEAAQUCd0JNLljxdzoorfn/xAAbEQABBAMAAAAAAAAAAAAAAAACAAEDEBEyYf/aAAgBAwEBPwEhyPbk3df/xAAaEQABBQEAAAAAAAAAAAAAAAACAAEDEBEy/9oACAECAQE/AQPCuPhl/8QAGxAAAgMAAwAAAAAAAAAAAAAAAAEQESExQXH/2gAIAQEABj8Cw5cXfRsIYvD/xAAdEAEAAgEFAQAAAAAAAAAAAAABABExIUFRYaFx/9oACAEBAAE/ITIPV34gVWnYymjCzA424lNTH4J7o+Cf/9oADAMBAAIAAwAAABDs8MP/xAAXEQEBAQEAAAAAAAAAAAAAAAABABGh/9oACAEDAQE/EDYYqOM3Zf/EABgRAQEBAQEAAAAAAAAAAAAAAAEAESGh/9oACAECAQE/EEJ3kYmkXkv/xAAfEAEBAAEDBQEAAAAAAAAAAAABEQAhMUEQUWFx8PH/2gAIAQEAAT8QKhSMYVGu9JHP0sVULYsJ654xi4INdmaaYyqUYxz63jpXxO2f/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;what&quot; title=&quot;&quot; src=&quot;/static/6817a30c0c9d171cfd58a1f1f56210d6/65f94/what.jpg&quot; srcset=&quot;/static/6817a30c0c9d171cfd58a1f1f56210d6/0913d/what.jpg 160w,
/static/6817a30c0c9d171cfd58a1f1f56210d6/cb69c/what.jpg 320w,
/static/6817a30c0c9d171cfd58a1f1f56210d6/65f94/what.jpg 420w&quot; sizes=&quot;(max-width: 420px) 100vw, 420px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;blockquote&gt;
&lt;p&gt;Wait, all the FE people at Toss seem to work better than me, so what exactly am I supposed to help with…?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-frontend-chapter-atmosphere-when-i-joined&quot; style=&quot;position:relative;&quot;&gt;The frontend chapter atmosphere when I joined&lt;a href=&quot;#the-frontend-chapter-atmosphere-when-i-joined&quot; aria-label=&quot;the frontend chapter atmosphere when i joined permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To understand why I thought this way, you need to know what the frontend chapter’s atmosphere was like when I first joined.&lt;/p&gt;
&lt;p&gt;When I first joined Toss in 2019, there were only a bit over 10 frontend developers, and I remember the entire Toss team was just over 300 people. At that time, we’d just received preliminary approval for internet banking for Toss Bank, and the headcount was definitely small considering the company’s scale and value.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e091f84babb31169e17d75eda86fc732/d2602/fe_chapter.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 82.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQDAv/EABcBAAMBAAAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAaUWs1SgMy5BBGn/xAAeEAABBAEFAAAAAAAAAAAAAAABAAIDEhEhIjEyQ//aAAgBAQABBQKgRDQLIOyTJsEukXXzZx//xAAXEQADAQAAAAAAAAAAAAAAAAAAAhAx/9oACAEDAQE/AauH/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/Aaz/xAAcEAABAwUAAAAAAAAAAAAAAAAAARAxAhEhQVH/2gAIAQEABj8CkkwXTUnWqEb/xAAeEAACAQQDAQAAAAAAAAAAAAAAAREhMUFxEJGx8f/aAAgBAQABPyFfGTp0aKEsSIa2r2CaacGx6hTrhv3L2z//2gAMAwEAAgADAAAAEKQQfv/EABgRAAMBAQAAAAAAAAAAAAAAAAABIREx/9oACAEDAQE/EHuRiqo+I4H/xAAXEQADAQAAAAAAAAAAAAAAAAAAATFB/9oACAECAQE/EFR00pn/xAAeEAEAAgICAwEAAAAAAAAAAAABABEhUTGhYbHB8P/aAAgBAQABPxAIbQofTV4US44aq5mGDDQLvjeWFS6Ba+QanHALfU6hPz+Sd/P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;fe chapter&quot; title=&quot;&quot; src=&quot;/static/e091f84babb31169e17d75eda86fc732/c08c5/fe_chapter.jpg&quot; srcset=&quot;/static/e091f84babb31169e17d75eda86fc732/0913d/fe_chapter.jpg 160w,
/static/e091f84babb31169e17d75eda86fc732/cb69c/fe_chapter.jpg 320w,
/static/e091f84babb31169e17d75eda86fc732/c08c5/fe_chapter.jpg 640w,
/static/e091f84babb31169e17d75eda86fc732/6a068/fe_chapter.jpg 960w,
/static/e091f84babb31169e17d75eda86fc732/eea4a/fe_chapter.jpg 1280w,
/static/e091f84babb31169e17d75eda86fc732/d2602/fe_chapter.jpg 4032w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    When we used to go around saying we&apos;d have no more wishes if we just had 20 frontend developers
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Back then, Toss was focused on a hiring strategy to create high talent density, with the recruiting catchphrase “Top compensation for top talent,” and they actually succeeded in building high talent density, creating what was like an elite sports team.&lt;/p&gt;
&lt;p&gt;This wasn’t just talk - new Toss hires feel considerable pressure about their colleagues’ work abilities. Of course, there’s the sheer amount of work, but seeing how they somehow cleanly handle all that work, you can’t help but think “Can I survive here…?”&lt;/p&gt;
&lt;p&gt;Of course, I haven’t worked at every company in Korea, so I can’t say Toss absolutely works better than other places, but it was at least the best-working organization among the ones I’ve experienced.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/58d328fdeff4c59ca29c3e17f42d0949/b4294/wakgood.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABQD/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAR2h3M1Go//EABwQAAAGAwAAAAAAAAAAAAAAAAECAwQTIRESNP/aAAgBAQABBQI4025EMxyUytqkGpP/xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwEn/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAEx/9oACAECAQE/AbiP/8QAGxAAAwACAwAAAAAAAAAAAAAAAAExESFRYXH/2gAIAQEABj8CUgvWbFZyY7Zg/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARUSExQf/aAAgBAQABPyGsT0fhCtLXKNHKg7CoVShAB10yURbDZ//aAAwDAQACAAMAAAAQGC//xAAXEQEBAQEAAAAAAAAAAAAAAAABABEh/9oACAEDAQE/EFjJ2//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQIBAT8QOqXL/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBUWGBwf/aAAgBAQABPxAAbLbYjXce1NhFNpU288IB3EQoICl16iHOFyWMxH5LTtlv7P/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;wakgood&quot; title=&quot;&quot; src=&quot;/static/58d328fdeff4c59ca29c3e17f42d0949/b4294/wakgood.jpg&quot; srcset=&quot;/static/58d328fdeff4c59ca29c3e17f42d0949/0913d/wakgood.jpg 160w,
/static/58d328fdeff4c59ca29c3e17f42d0949/cb69c/wakgood.jpg 320w,
/static/58d328fdeff4c59ca29c3e17f42d0949/b4294/wakgood.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Toss was a magical place where once goals were aligned, just saying &quot;everyone figure it out&quot; made work flow smoothly&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;So I was pretty indifferent to the growth of people in the same frontend chapter, because I thought everyone in our chapter was someone who did well on their own. And as I mentioned earlier, in an environment littered with people who work well, my own growth comes first - I didn’t have time to worry about others’ growth.&lt;/p&gt;
&lt;p&gt;Of course, technical discussions and in-house study groups were actively happening, but these activities weren’t so much about growing someone less capable than me, but more about stimulating each other and growing together. So I remember the frontend chapter back then felt like similar-level friends gathering to stimulate each other and grow together.&lt;/p&gt;
&lt;p&gt;In other words, I can list the internal culture of the frontend chapter at that time like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Because there were few people, everyone knew each other’s faces and names and had high intimacy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There was high trust in each other’s abilities, and members felt they were trusted by teammates.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Based on this intimacy and trust, there was psychological safety formed around the frontend chapter as an organization.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-emergence-of-the-concept-of-junior-developers&quot; style=&quot;position:relative;&quot;&gt;The emergence of the concept of junior developers&lt;a href=&quot;#the-emergence-of-the-concept-of-junior-developers&quot; aria-label=&quot;the emergence of the concept of junior developers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;But this frontend chapter culture started changing a bit starting in 2020. I think there were two main causes - one was that the chapter size, which had been barely in the low teens, grew rapidly and fast, and the other was the emergence of the concept of “junior.”&lt;/p&gt;
&lt;p&gt;Actually, until then the frontend chapter already had trust formed, so the very concept of needing to unilaterally help someone else grow was minimal.&lt;/p&gt;
&lt;p&gt;But when Toss took an aggressive hiring stance of betting on people with high growth potential even if their current skills weren’t outstanding by creating programs like &lt;a href=&quot;https://toss.im/career/next-developer-2021&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;NEXT Developer&lt;/a&gt;, Toss started having a persona of “team members who need help to grow,” and we called this persona “junior.”&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e2829c2438dce41760ecec2a2fbe9220/6052f/next2021.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 70.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABYlAAAWJQFJUiTwAAABnklEQVR42pVTy27CMBCME5I4j5aGkEcreuQIF5BoAYF4SzSIG9w48v9/MN3dKipVg4DDyPZoPbveWRtZlqHdbiPPc0RRBKUUTNMU8N5xHARhiJAQBAEajQY8z5dYrTXSNIXv+8K7rguDL9q2DcuyRMQwjH9g4RJlojK2PJcwrglU8XfhUp1Rq9UEXDU/gZ/M4D3D8zx5KnMcU5H898ABu90OnU4Hg8EAy+US0+kUk8kERVHIej6fhdtsNrKXvl0TZCRJgvF4jH6/j/l8jm63i9VqJdx6vcbxeJQ9c2xmxbP/EpxxsVhgOByKWK/Xw3a7xQdVXBRfxH9iNBqJeL1er+r59QYrcpDdV4pW6qtpWsLdMKbaZYcqbaY50tcWkrwla/72LpymOTSvC1dn4opcdtN7huU3UNNPlEQT59MU2I9VyODRaTZjMqmJPEuR0Y9I00xM45F5WJC/02w2w36/x+l0EncPh4Nw1Wao2xXy/2TEcSxrFPE5pgo1xdB/N8gow/6BciiBVK4u1e8AC/lw1As8FeHJjBDaETxNiYIE3ymPQYmdVFPZAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;next2021&quot; title=&quot;&quot; src=&quot;/static/e2829c2438dce41760ecec2a2fbe9220/6af66/next2021.png&quot; srcset=&quot;/static/e2829c2438dce41760ecec2a2fbe9220/69538/next2021.png 160w,
/static/e2829c2438dce41760ecec2a2fbe9220/72799/next2021.png 320w,
/static/e2829c2438dce41760ecec2a2fbe9220/6af66/next2021.png 640w,
/static/e2829c2438dce41760ecec2a2fbe9220/d9199/next2021.png 960w,
/static/e2829c2438dce41760ecec2a2fbe9220/21b4d/next2021.png 1280w,
/static/e2829c2438dce41760ecec2a2fbe9220/6052f/next2021.png 2030w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;The NEXT Developer job posting page says in huge letters &quot;developers with 3 years or less experience&quot;&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;NEXT Developer felt like a kind of junior job fair, and the problem was that the psychological state of people hired through a recruitment funnel that externally communicated “We’re hiring juniors!” was somewhat different from those who joined through the regular hiring process.&lt;/p&gt;
&lt;p&gt;Of course, we were able to recruit many excellent people through that program, but I felt that the behavioral patterns of some people hired through NEXT Developer were slightly different from existing people. Typical differences I noticed were roughly like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Why does everyone mostly just say it’s good, it’s fine? Don’t they have anything they don’t like?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;That opinion is a subjective opinion without basis, why are they just accepting it?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Why aren’t they actively participating in chapter activities?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Actually, these characteristics are typical of new hires who haven’t adapted to the organization yet, so you might think it’s not that strange. But the Toss new hires I’d experienced until then usually strongly challenged problems the existing chapter had even shortly after joining, or actively contributed to in-house libraries.&lt;/p&gt;
&lt;p&gt;It was also strange to just chalk it up to differences in skill or years of experience, because even among people hired through the same NEXT Developer funnel, some showed these behavioral patterns and some didn’t. So I thought about what caused these differences in proactivity and organization adaptation time.&lt;/p&gt;
&lt;h3 id=&quot;why-are-these-people-so-passive&quot; style=&quot;position:relative;&quot;&gt;Why are these people so passive?&lt;a href=&quot;#why-are-these-people-so-passive&quot; aria-label=&quot;why are these people so passive permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fortunately, this problem awareness wasn’t just mine but also shared by several other frontend developers, and we talked about whether these behavioral differences might be differences in hard skills - differences in confidence that they’re doing their job as a developer in this organization.&lt;/p&gt;
&lt;p&gt;So the chapter proactively promoted study groups, offline code reviews, pair programming with mates, etc. to level up developers’ hard skills.&lt;/p&gt;
&lt;p&gt;But there was one trap here - the technical level of these activities was often geared toward team members with good hard skill abilities. Since the frontend chapter until then had been an organization pursuing growth together, it was easier to select topics like abstraction and algebraic effects that everyone could newly learn, discuss, and grow from, rather than foundational content everyone already knew like Promises and React.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 546px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1a5521288f83b55d96114e32c9d3b6ef/f066e/hard_user.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAVABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQFAv/EABYBAQEBAAAAAAAAAAAAAAAAAAIEAf/aAAwDAQACEAMQAAAB2+M+omtGRmElIHf/xAAbEAABBAMAAAAAAAAAAAAAAAARAAECEBIiQf/aAAgBAQABBQKUgulqO2bUa//EABkRAQACAwAAAAAAAAAAAAAAAAEAAhASUf/aAAgBAwEBPwG60m1uRBx//8QAGhEAAgIDAAAAAAAAAAAAAAAAAQIAEBESUf/aAAgBAgEBPwFG2mV7ASK//8QAGRAAAgMBAAAAAAAAAAAAAAAAEBEAMWGB/9oACAEBAAY/AricscKwf//EAB0QAAIBBQEBAAAAAAAAAAAAAAERABAhMYGRQXH/2gAIAQEAAT8hClnYwPb9gAMO0RNoR4vR3op//9oADAMBAAIAAwAAABBjD7//xAAaEQEAAQUAAAAAAAAAAAAAAAARAAEQITFh/9oACAEDAQE/ECMLOuGNNW//xAAZEQEAAgMAAAAAAAAAAAAAAAARAAEQQWH/2gAIAQIBAT8QoeicEcMf/8QAGxABAQACAwEAAAAAAAAAAAAAAREAMRAhYUH/2gAIAQEAAT8QrCahptxkhVdJPcOl4Sxj8e1GlfuNRgb3QYxK9BwtadC/LeP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;hard user&quot; title=&quot;&quot; src=&quot;/static/1a5521288f83b55d96114e32c9d3b6ef/f066e/hard_user.jpg&quot; srcset=&quot;/static/1a5521288f83b55d96114e32c9d3b6ef/0913d/hard_user.jpg 160w,
/static/1a5521288f83b55d96114e32c9d3b6ef/cb69c/hard_user.jpg 320w,
/static/1a5521288f83b55d96114e32c9d3b6ef/f066e/hard_user.jpg 546w&quot; sizes=&quot;(max-width: 546px) 100vw, 546px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;It&apos;s like a game full of veterans with a few newbies thrown in&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The problem here is that when discussions go on about content that greatly exceeds your knowledge, not only is it hard to absorb that knowledge in the first place, but you might even feel greater burden or self-blame thinking you can’t understand these discussions because you’re lacking.&lt;/p&gt;
&lt;p&gt;Plus, since recruitment programs like NEXT Developer openly promoted hiring “juniors,” people who joined through this funnel tended to perceive themselves as juniors still lacking in skill regardless of their actual hard skill level, making them even more susceptible to these feelings.&lt;/p&gt;
&lt;p&gt;Actually, I didn’t think about this at all while running study groups, but I learned about it later during 1-on-1 coffee chats. From then on, I thought this wasn’t simply a difference in hard skills but a problem of self-confidence.&lt;/p&gt;
&lt;p&gt;While Toss aims for a challenging culture and transparent feedback culture, these things require a foundation of confidence that you’re doing at least your fair share of work within the team. When you’re uncertain whether you’re doing well or not, it takes tremendous courage to actively push your opinions or give feedback to others.&lt;/p&gt;
&lt;p&gt;There was also a difference in psychological safety about the organization. Before, when the chapter had only about 10 people and similar technical levels, it was an environment where people quickly became close and trust formed easily.&lt;/p&gt;
&lt;p&gt;When you know well what kind of person everyone is and their working style, even if you exchange somewhat blunt feedback, it’s easy to have a kind of certainty that this person is telling you this for the team’s development and there’s no emotion in this feedback, and this certainty can lead to psychological safety and trust in the organization.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5d46f54049984addc8b6d03c043eb3a3/b4294/passion.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAeJukzJGf//EABwQAAEDBQAAAAAAAAAAAAAAAAIAAQMREiEiMv/aAAgBAQABBQLpyG16osQRbAv/xAAVEQEBAAAAAAAAAAAAAAAAAAAQQf/aAAgBAwEBPwGH/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABsQAAIBBQAAAAAAAAAAAAAAAAAREAEDEjFR/9oACAEBAAY/AkKHTeRcfI//xAAcEAEAAgIDAQAAAAAAAAAAAAABACERQTFhgaH/2gAIAQEAAT8hBC1upVM47gjhiSo2+RqLpn9I2z//2gAMAwEAAgADAAAAENjP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EA2P/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxAf/8QAGhABAQEBAQEBAAAAAAAAAAAAAREAMSFBUf/aAAgBAQABPxAwrSP1gXwgS6+lw0UMp3BHYUZzmQX4kMlF7v/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;passion&quot; title=&quot;&quot; src=&quot;/static/5d46f54049984addc8b6d03c043eb3a3/b4294/passion.jpg&quot; srcset=&quot;/static/5d46f54049984addc8b6d03c043eb3a3/0913d/passion.jpg 160w,
/static/5d46f54049984addc8b6d03c043eb3a3/cb69c/passion.jpg 320w,
/static/5d46f54049984addc8b6d03c043eb3a3/b4294/passion.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Toss people might seem intense, but they&apos;re just really serious about work - get to know them and many are sweethearts&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;But as the headcount gradually increased, we’d reached a situation where people didn’t even know each other’s names and faces, plus a hierarchy had formed within the chapter due to hard skill differences, so worries like “If I say this, will I look incompetent?” or “Is it okay for me to say this now?” naturally arose. And this situation can be a factor that lowers psychological safety about the organization.&lt;/p&gt;
&lt;p&gt;So I thought the cause of this passive behavior wasn’t simply differences in hard skill level, but differences in confidence that you can blend in as a member of this organization, and differences in the psychological safety felt in the chapter. I thought I needed to approach it from a different direction than study groups or pair programming that could drive hard skill growth.&lt;/p&gt;
&lt;h2 id=&quot;the-emergence-of-f-evangelist&quot; style=&quot;position:relative;&quot;&gt;The emergence of F-Evangelist&lt;a href=&quot;#the-emergence-of-f-evangelist&quot; aria-label=&quot;the emergence of f evangelist permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I mentioned earlier, by the time we finished the 2021 Next Developer program, the frontend chapter had nearly 60 people - it had become a massive organization compared to before.&lt;/p&gt;
&lt;p&gt;So unlike before, people in the same frontend chapter started not knowing each other’s faces or names, and organization members’ intimacy began rapidly declining. &lt;small&gt;(The era when questions like “Who is OO?” became increasingly common…)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This declining intimacy also negatively affected people’s participation in various chapter decisions, and the culture of freely exchanging feedback or even technical opinions gradually faded. And this phenomenon was happening more frequently in the junior segment I mentioned earlier.&lt;/p&gt;
&lt;p&gt;At first, there was strong opinion in the chapter from the “return to the past” faction saying “we should try everything we can to recreate the old atmosphere,” but as time passed and headcount grew more, opinion tilted toward the realist faction that we needed to accept reality and find methods suitable for the chapter’s current size.&lt;/p&gt;
&lt;p&gt;I was close to the realist side from the start. What I strongly argued was that even in school when everyone was the same age with similar levels, you couldn’t be close with all 40 classmates in the same class, so how can you expect the same intimacy in the current frontend chapter with even more people and hierarchy formed by hard skill levels?&lt;/p&gt;
&lt;p&gt;In other words, the frontend chapter now needed to figure out new ways to increase intimacy and create psychological safety for an organization of over 60 people, not an organization of just about 10 people.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6167a981411988d8ff05e1fe86ac3795/d7854/school_class.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAQP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAAd5LWKE5m//EABoQAAIDAQEAAAAAAAAAAAAAAAECAxESEyL/2gAIAQEAAQUChY7aReozT+QxOzAL/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8BR//EABwQAAIBBQEAAAAAAAAAAAAAAAABIQIDEBExYv/aAAgBAQAGPwJq5txwcxjaRQ/J1n//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMUFRkf/aAAgBAQABPyEtomg1HLY1CbSr8lAIZ52IHVnj2XVsucT/2gAMAwEAAgADAAAAECA//8QAFxEBAQEBAAAAAAAAAAAAAAAAAQARIf/aAAgBAwEBPxANeWN//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhEf/aAAgBAgEBPxCJU0f/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhMZFhof/aAAgBAQABPxBxhykVX45GoeKji1+Y7svFl4gpbc1ExTlPscQiaqjRK+VnIK6C2A3eT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;school class&quot; title=&quot;&quot; src=&quot;/static/6167a981411988d8ff05e1fe86ac3795/d7854/school_class.jpg&quot; srcset=&quot;/static/6167a981411988d8ff05e1fe86ac3795/0913d/school_class.jpg 160w,
/static/6167a981411988d8ff05e1fe86ac3795/cb69c/school_class.jpg 320w,
/static/6167a981411988d8ff05e1fe86ac3795/d7854/school_class.jpg 550w&quot; sizes=&quot;(max-width: 550px) 100vw, 550px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Even among same-age classmates, the friends you&apos;re really close with usually don&apos;t even reach 10&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;For that reason, Toss Core frontend chapter - which had the most people - thought about dividing people into smaller subgroups, building intimacy within them to create psychological safety about the organization, while also considering a kind of lead role that could more actively help people in those groups and infuse them with growth direction.&lt;/p&gt;
&lt;p&gt;At Toss, there’s an organization called a tribe formed by gathering small purpose-driven organizations called silos, and originally each tribe has one role called T-Lead who rallies the developers. But since T-Leads are mainly held by backend folks, it was hard to expect them to actively suggest direction and lead on frontend stuff, which isn’t their specialty.&lt;/p&gt;
&lt;p&gt;For that reason, until now the frontend chapter had been making decisions and executing action items at the chapter level, but as the chapter’s headcount rapidly increased and the organization’s density decreased, the frontend side also needed a role that could help team members more closely than the chapter lead.&lt;/p&gt;
&lt;p&gt;So at first we tried to create a role named F-Lead as an homage to T-Lead, but there was worry that the word “Lead” might actually strengthen hierarchy, and the frontend chapter’s idea of a lead role wasn’t someone managing others but someone helping teammates, so there were many opinions wanting this feeling to strongly emerge from the name itself.&lt;/p&gt;
&lt;p&gt;In other words, we expected a kind of helper role that performs work in slightly gray areas like supporting other silos, administrative work like organizational restructuring, or counseling through 1-on-1 coffee chats, creating an environment where team members can focus more on work, and helping frontend chapter members grow quickly to level up the entire chapter’s hard skills and soft skills. &lt;small&gt;(While also completing all their silo work…muffled)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Through various ideation, many interesting names came up, but ultimately the role named F-Evangelist was born, and I - someone interested in chapter culture and psychological safety - ended up taking this role.&lt;/p&gt;
&lt;h3 id=&quot;bragging-about-my-shit&quot; style=&quot;position:relative;&quot;&gt;Bragging about my shit&lt;a href=&quot;#bragging-about-my-shit&quot; aria-label=&quot;bragging about my shit permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I consistently pushed the opinion that all people in the frontend chapter organization need an environment where they can comfortably try anything and comfortably give feedback on what they think is strange, because only then can the frontend chapter develop.&lt;/p&gt;
&lt;p&gt;When subgroups and F-Evangelist first emerged, I consistently pushed that we should focus on increasing organizational intimacy so people can feel psychological safety within the frontend chapter organization.&lt;/p&gt;
&lt;p&gt;The top priority I was thinking about at the time was making junior members of my group see developers with more years of experience or developers in specific roles like F-Evangelist not as intimidating people but just as fellow developers.&lt;/p&gt;
&lt;p&gt;No matter how much we removed the word “lead” from the role name to avoid creating hierarchy, since the actual actions are essentially those of a lead, I thought it was unrealistic to expect the distance or hierarchy people feel about this role to be completely removed with passive actions like just changing the name.&lt;/p&gt;
&lt;p&gt;Plus, Toss’s frontend chapter had several developers who’d built name value through various activities, and junior people tended to vaguely think that high name value means good skills. I judged that in a situation where hierarchy was already occurring due to hard skill differences, if this misunderstanding about name value was added, it would greatly hinder creating organizational psychological safety, so I wanted to completely remove this thinking. &lt;small&gt;(Being famous and being good at development have little correlation)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;So the first thing I did was a “shit bragging contest.”&lt;/p&gt;
&lt;p&gt;Generally developers aim for beautiful design, but when developing at a company, due to external factors like business situations, there are cases where you crush the design, and with tight schedules you often make bugs while rushing.&lt;/p&gt;
&lt;p&gt;In these situations, the act of writing poorly designed code or mistakes gets expressed as “taking a shit,” and I proposed we share exactly this kind of code. It was somewhat casual and a dirty name, but I wanted a space where everyone could laugh, have fun, and comfortably disclose mistakes, so I deliberately chose a fun name instead of stiff names like “sharing debt” or “retrospective.”&lt;/p&gt;
&lt;p&gt;My group had various segments distributed from completely new developers for whom Toss was their first job to developers with 6-7 years of experience. By running the shit bragging contest, I intended to inform everyone that regardless of years of experience, any developer can make mistakes and situations arise where you crush design, while sharing how experienced developers clean up this shit and what thought processes lead to the decision to crush design for speed.&lt;/p&gt;
&lt;p&gt;But I made one mistake here too - what people considered shit code differed by hard skill level. Of course, for shit with relatively low resolution difficulty, active discussion happened and problem-solving methods were suggested, but for shit that’s hard to even understand if you lack hard skills, participation was starkly divided by hard skill level.&lt;/p&gt;
&lt;p&gt;This problem had already occurred in previous study groups and offline code reviews, but when I first took on F-Evangelist, I was so eager to quickly remove psychological hierarchy that I forgot the lessons from past failures.&lt;/p&gt;
&lt;p&gt;Actually, people’s reviews of the shit bragging contest weren’t bad, but I finished the first action item without reaching my original intention of removing psychological hierarchy.&lt;/p&gt;
&lt;h3 id=&quot;finding-strengths&quot; style=&quot;position:relative;&quot;&gt;Finding strengths&lt;a href=&quot;#finding-strengths&quot; aria-label=&quot;finding strengths permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After that, I changed my approach direction and pushed a method of sharing many non-technical conversations so we could become close as person-to-person rather than developers, building up information.&lt;/p&gt;
&lt;p&gt;So I set up mogakko sessions where people with nothing to do on weekends gathered at pretty cafes to eat delicious things and do personal work, or used subgroup weekly meeting time as chatting time, repeatedly performing various action items and observing people’s reactions. After repeating several action items like this, intimacy definitely formed within the group compared to before, and psychological safety about the organization formed.&lt;/p&gt;
&lt;p&gt;But the issue I still hadn’t resolved was the burden junior developers carried of “I’m still lacking.” While this burden could be a great motivator for growth if it worked healthily, if this thinking became excessive, it could instead lead to drops in confidence or self-esteem and become toxic.&lt;/p&gt;
&lt;p&gt;Around that time, I noticed a designer from my silo looking at some spreadsheet, and that sheet was the result sheet from a test called “StrengthsFinder” that the design chapter had conducted.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/05f8e90b592bc1d348a7a51cb03b0c1e/9568a/book.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 133.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAH/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAdLrFNIxLj7KzNTo1//EAB0QAAICAgMBAAAAAAAAAAAAAAECAAMRMRASEyH/2gAIAQEAAQUCHGJVpbyzHaWYHtA3cBRAiwfJ/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BiM//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAeEAACAgAHAAAAAAAAAAAAAAAAERAxAQISIUFxgf/aAAgBAQAGPwKcM3gtKey5jooZRUf/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhMUFRkWH/2gAIAQEAAT8h0ThmYS8GlEVFvAveZSaG8StT0Suzf01GXgceR0IiSJRH/9oADAMBAAIAAwAAABAAJP7/xAAYEQADAQEAAAAAAAAAAAAAAAAAASEQEf/aAAgBAwEBPxC50xiUp//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EIM//8QAHhABAAMAAgIDAAAAAAAAAAAAAQARITFBUWFxoeH/2gAIAQEAAT8Qd0CI3Y+/c1zY+Xj5hGBkvA3YDjr1ARBqBrzPsRGNsjgu+yNlX2DRMSj2N1LMSvNz8LBIg6J//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;book&quot; title=&quot;&quot; src=&quot;/static/05f8e90b592bc1d348a7a51cb03b0c1e/c08c5/book.jpg&quot; srcset=&quot;/static/05f8e90b592bc1d348a7a51cb03b0c1e/0913d/book.jpg 160w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/cb69c/book.jpg 320w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/c08c5/book.jpg 640w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/6a068/book.jpg 960w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/eea4a/book.jpg 1280w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/9568a/book.jpg 3024w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;When you buy this book, they give you a code to take the StrengthsFinder test online&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;I don’t believe in these kinds of tests at all, so at first I thought “the design chapter did something fun again” and was going to move on, but soon I thought this test could be a good method to relieve people’s burdens. &lt;small&gt;(The design chapter does surprisingly many fun things like this)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;There are roughly two ways to grow - one is making what you’re bad at better, and the other is making what you’re already good at even better. But generally, developers in their growth phase tend to focus only on what they’re bad at rather than what they’re already good at, and try to fill those gaps.&lt;/p&gt;
&lt;p&gt;While focusing on and supplementing what you’re bad at is a good growth method, if you get too absorbed in the negative thought “I can’t do this,” situations can arise where you push yourself so hard that you study or work to the point of harming your health, or feel frustrated comparing yourself with developers around you.&lt;/p&gt;
&lt;p&gt;So I thought that if through the StrengthsFinder test we could give people metacognition so they could know “what they’re good at,” they’d learn both their strengths and weaknesses rather than just focusing on weaknesses, which might also build self-confidence.&lt;/p&gt;
&lt;p&gt;I talked about this idea with other frontend developers, and two people sympathized and joined to try running StrengthsFinder just among ourselves. At that time, one frontend developer belonging to the design platform team had already run StrengthsFinder with the design chapter, so they greatly helped in the process of finding methods suited to the frontend chapter based on that experience.&lt;/p&gt;
&lt;p&gt;The method of running the StrengthsFinder program was super simple - just request the company to buy the book, each person takes the test, shares the PDF test result sheet in the StrengthsFinder Slack channel, then meet offline where the facilitator explains each person’s result sheet.&lt;/p&gt;
&lt;p&gt;Here the facilitator’s role is to create an environment where team members participating in StrengthsFinder can empathize with and remember each other’s strengths rather than just reading them. The facilitator’s action items were roughly like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Rather than just reading the result sheet, give examples of situations you can actually experience at Toss.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Summarize teammates’ strengths in one line to make them easy for others to remember.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have them highlight which of their strengths they want others to pay more attention to.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have them decide on action items that can further strengthen each other’s strengths.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;The purpose of StrengthsFinder included building metacognition about what you do well yourself, but also teaching how working as one team is a process of various people with different strengths gathering to create synergy. So we didn’t just stop at knowing our own strengths, but additionally conducted activities to actively recognize and further strengthen each other’s strengths.&lt;/p&gt;
&lt;p&gt;After running this PoC on StrengthsFinder, it explained each person’s strengths in detail and was fun, so I soon ran StrengthsFinder with the subgroup I was leading.&lt;/p&gt;
&lt;p&gt;At that time, I didn’t want team members to feel this program was part of work, and since we were running a program somewhat removed from development anyway, I wanted to give them a feeling of escaping for a day, so we met at a pretty cafe in Chungmuro rather than the office to run the StrengthsFinder program.&lt;/p&gt;
&lt;p&gt;The results were better than expected. Honestly, I didn’t have high expectations since these tests have no scientific basis so people might not believe them, but surprisingly everyone was happy learning their strengths, and greatly empathized with how being a good developer isn’t one single form but various forms, and that the frontend chapter is a team where people with various strengths must gather to create synergy.&lt;/p&gt;
&lt;p&gt;Of course, I’d told team members these things a lot through coffee chats, but I was greatly impressed that running one program or campaign like this was more effective than a hundred words.&lt;/p&gt;
&lt;p&gt;After getting good results in the subgroup, I started evangelizing at F-Evangelist meetings, explaining StrengthsFinder’s purpose and methods. The original plan was to test it first at Toss Core and export it to other affiliates if the response was good, but frontend developers from other affiliates who were lurking in the StrengthsFinder channel started spreading it on their own, and we suddenly ended up exporting StrengthsFinder.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ffc77284035d39b5b0c853dc1b66ecff/c549b/strong.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 57.50000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABfUlEQVR42m2TabKCQAyEvYQgbshDERUXcEFE3Ervf6Q8vlhjgfija5IZppNODy3HccS2bfnzfYnjRGazmSwWC0W/39ezTqfTAPuA+1W0ut2uWJZdEoRyvRaSJImkaSr7/V78sojruuJ5noxGo09swF6v16sTvjt0JPAdydJYTqe8xElxu93k8XjI8/mU+/2uOXFRFKWaWDabjQwGA+24RsiG63pll5HM53MFklm5QBfINyA3JChsSG63LVkul/J6vSTPc8myTNfz+SxhGMp4PJbpdCpBECjITdyQ/J6hpWZAALHpkHi1Wmk8mUx0n+8owkoROq5JhhC3ODwejwpMAXS62+2UFMJql4C8Kr9iiq0XDoeDurxer5WETrjAHA3IcXc4HKrTjRmagNa3262S4jCxkVY1KYoiJYPom6xGyCEyIeQNQopkcLlcPk+JM1QwCor+fDaG0HxoZofTkDACY4gxgxkS/5yhAQ8VUyBjpYD5DZGK6/w9jAfZ4FvyP1eLWNLuMUijAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;strong&quot; title=&quot;&quot; src=&quot;/static/ffc77284035d39b5b0c853dc1b66ecff/6af66/strong.png&quot; srcset=&quot;/static/ffc77284035d39b5b0c853dc1b66ecff/69538/strong.png 160w,
/static/ffc77284035d39b5b0c853dc1b66ecff/72799/strong.png 320w,
/static/ffc77284035d39b5b0c853dc1b66ecff/6af66/strong.png 640w,
/static/ffc77284035d39b5b0c853dc1b66ecff/d9199/strong.png 960w,
/static/ffc77284035d39b5b0c853dc1b66ecff/21b4d/strong.png 1280w,
/static/ffc77284035d39b5b0c853dc1b66ecff/c549b/strong.png 2128w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;We even wrote guidelines for StrengthsFinder facilitators for smooth export&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Unfortunately I left around this time so I don’t know in detail how StrengthsFinder progressed afterward, but I heard through the grapevine after leaving that other frontend developers found it fun too, and I even heard the DS (Data Scientist) team ran StrengthsFinder. &lt;small&gt;(The export speed is incredible…)&lt;/small&gt;&lt;/p&gt;
&lt;h2 id=&quot;closing&quot; style=&quot;position:relative;&quot;&gt;Closing&lt;a href=&quot;#closing&quot; aria-label=&quot;closing permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The past 2.5 years working at Toss was time that created much foundation for growth for me. While Toss has a lot of work and is intense, I think it was an organization with that much immersion in work and growth.&lt;/p&gt;
&lt;p&gt;I got to experience what it feels like to work with capable colleagues while trusting each other, what the crazy speed of ideating a product in the morning and deploying it in the evening is like, and what the driving force that can create this productivity is - I had many experiences and thoughts.&lt;/p&gt;
&lt;p&gt;In my final exit interview, the POM (People Operation Manager) asked me “What would Toss need to improve to make you come back?” and I answered “If I come back, it would probably be when I feel that what exists at Toss doesn’t exist elsewhere.” That’s how high my satisfaction with this organization was. &lt;small&gt;(Looking back, that seems like a cool line…?)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Now Toss isn’t the 300-person startup from when I joined, but has become a mid-sized company of 2,000 people. So naturally there are parts that have changed from those days, and I feel a strange nostalgia and regret about those parts. If before it felt like doing work with really close friends whether in chapters or silos, recently it feels like it’s become a bit more like being a company employee.&lt;/p&gt;
&lt;p&gt;But Toss can’t return to its former form now. The culture of 300 people and the culture of 2,000 people are naturally different.&lt;/p&gt;
&lt;p&gt;So as I moved to a small startup this time, I wanted to experience directly creating that culture I loved - the one that immerses in work to create crazy productivity - and leading the product to success.&lt;/p&gt;
&lt;p&gt;The startup I joined, Quotalab, is also &lt;a href=&quot;https://quotalab.career.greetinghr.com/o/61278&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;enthusiastically hiring frontend developers&lt;/a&gt;, so if any readers want to experience introducing a culture that creates this crazy productivity into an organization and succeeding with a product based on that culture, please apply. &lt;small&gt;(In IT, talent density and culture really do everything)&lt;/small&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[토스에서 일하며 깨달은 성장과 리더십]]></title><description><![CDATA[이번 포스팅에서는 필자가 지난 2년 반 동안 몸 담았던 직장인 토스에서 경험하고 느꼈던 것들에 대해서 한번 편하게 적어보려고 한다. 사실 토스에서의 퇴사는 이미 3월에 진행했지만, 그 동안 새로운 곳에서의 할 일도 많았고 개인적인 일들도 겹쳐서 3개월이 지난 지금에서야 회고를 진행하게 되었다. 필자도 7년 정도 개발자로 일을 하면서 이 회사, 저 회사를 다녀봤지만 확실히 토스팀에서의 기억은 강렬하게 남는다. 워낙 문화가 특이한 조직이기도 했고, 함께 일했던 동료들도 훌륭했으며, 개인적으로도 그저 한 명의 개발자가 아닌 팀을 성장시킬 수 있는 개발자로 성장할 수 있었던 기회도 얻었기 때문이다.]]></description><link>https://evan-moon.github.io/2022/05/07/toss-retrospective/</link><guid isPermaLink="false">20220507-toss-retrospective</guid><pubDate>Sat, 07 May 2022 01:53:50 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 필자가 지난 2년 반 동안 몸 담았던 직장인 토스에서 경험하고 느꼈던 것들에 대해서 한번 편하게 적어보려고 한다. 사실 토스에서의 퇴사는 이미 3월에 진행했지만, 그 동안 새로운 곳에서의 할 일도 많았고 개인적인 일들도 겹쳐서 3개월이 지난 지금에서야 회고를 진행하게 되었다.&lt;/p&gt;
&lt;p&gt;필자도 7년 정도 개발자로 일을 하면서 이 회사, 저 회사를 다녀봤지만 확실히 토스팀에서의 기억은 강렬하게 남는다. 워낙 문화가 특이한 조직이기도 했고, 함께 일했던 동료들도 훌륭했으며, 개인적으로도 그저 한 명의 개발자가 아닌 팀을 성장시킬 수 있는 개발자로 성장할 수 있었던 기회도 얻었기 때문이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;토스는-어떻게-그렇게-일을-빠르게-할까&quot; style=&quot;position:relative;&quot;&gt;토스는 어떻게 그렇게 일을 빠르게 할까?&lt;a href=&quot;#%ED%86%A0%EC%8A%A4%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EA%B7%B8%EB%A0%87%EA%B2%8C-%EC%9D%BC%EC%9D%84-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%ED%95%A0%EA%B9%8C&quot; aria-label=&quot;토스는 어떻게 그렇게 일을 빠르게 할까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자는 작년인 2021년 말부터 주변 지인으로부터 너무 개발자들만 만나지 말고 다른 일을 하는 사람들도 많이 만나보라는 피드백을 받고, 다른 회사의 C-level 또는 HR 담당자나 VC에서 투자 심사역으로 종사하시는 분 같은 다양한 사람들을 만나보며 서로 궁금한 점을 물어보는 시간을 가지게 되었다.&lt;/p&gt;
&lt;p&gt;이렇게 몇 번의 커피챗을 거치며 서로를 알아가다가 가끔씩은 그 회사에 놀러가서 개발자분들도 직접 만나보고 그 회사가 겪고 있는 기술적인 문제에 대해 솔루션을 제안하기도 하고, 비즈니스에 대해 더 궁금증이 든다면 Co-founder 분들을 만나뵙고 더 자세한 이야기를 나눠볼 수 있는 기회도 가질 수 있었다. &lt;small&gt;(쓰고나니 뭔가 소개팅 같다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이 과정 속에서 굉장히 많은 질문들을 받기도 했지만, 기술적인 부분을 제외하고 필자가 제일 많이 들었던 질문이자 가장 처음에 듣는 질문은 보통 이 질문이었다.&lt;/p&gt;
&lt;center&gt;
  &lt;br&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;img src=&quot;/ba4b53d43a9bececa2dac7b1b849aee8/question.gif&quot; width=&quot;100%&quot;&gt;
  &lt;/div&gt;
  &lt;small&gt;토스는 어떻게 그렇게 일해요?&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;IT업계에서 토스는 꽤나 양면적인 이미지를 가진 기업으로 평가 받고 있다. 그 중 좋은 이미지는 굉장히 일을 잘 하고 빠르게 하는 팀이라는 것, 그리고 안 좋은 이미지는 일이 많은 원양어선이라는 것이다.&lt;/p&gt;
&lt;p&gt;물론 필자같은 직원 입장에서야 당연히 일을 잘 하는 것도 중요하고 내 개인 생활도 중요하니 저 두 가지 팩터들을 가지고 저울질을 하겠지만, 아무래도 회사를 경영하거나 투자를 해놓은 입장에서는 첫 번째 팩터인 “일을 빠르게 잘 하는 방법”에 대한 관심이 많을 수 밖에 없기 때문에 저 질문은 사실 “어떻게 그렇게 일을 빠르게 잘 할 수 있냐”라는 의미인 것이다.&lt;/p&gt;
&lt;h3 id=&quot;내-길은-내가-정하는-dri-문화&quot; style=&quot;position:relative;&quot;&gt;내 길은 내가 정하는 DRI 문화&lt;a href=&quot;#%EB%82%B4-%EA%B8%B8%EC%9D%80-%EB%82%B4%EA%B0%80-%EC%A0%95%ED%95%98%EB%8A%94-dri-%EB%AC%B8%ED%99%94&quot; aria-label=&quot;내 길은 내가 정하는 dri 문화 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;DRI(Directly Responsible Indivisual)는 이름 그대로 어떤 사안에 대한 최종의사결정권자를 의미한다. 이 개념은 스티브 잡스가 애플에 처음 도입했던 개념인데, 토스에도 이 DRI라는 개념이 뿌리깊게 박혀있다.&lt;/p&gt;
&lt;p&gt;개인적으로 토스가 빠른 속도로 일할 수 있는 원동력은 DRI라는 각자의 최종의사결정권이 굉장히 존중받는 문화에 있다고 생각한다. 토스팀은 조직의 의사결정권이 CEO 한 명에게 집중되어있는 것이 아니라 토스팀 전체의 팀원들에게 퍼져있는 문화이다.&lt;/p&gt;
&lt;p&gt;실제로 토스팀은 리더가 마음대로 제품의 방향성을 정하기 어려운 곳이다. 왜냐하면 각 제품에 대한 DRI는 그 제품을 만드는 사일로, 그 중에서도 그 사일로의 PO(Product Owner)가 가지고 있기 때문이다.&lt;/p&gt;
&lt;p&gt;물론 토스팀에도 CEO의 권위는 분명히 존재하고, 다른 사람보다 CEO가 던지는 말의 무게가 다른 사람에 비해 더 무거운 것도 사실이다. 하지만 토스팀이 다른 회사들과 달랐던 점은 PO들과 CEO가 싸우는 모습을 자주 볼 수 있다는 것, 그리고 결국 PO들이 이기는 경우가 많다는 점이다. &lt;small&gt;(대표랑 PO가 죽자살자 싸우는 그림은 어느 정도 규모가 있는 회사에서는 보기 힘든 모습이기는 하다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;토스에서 DRI라는 것은 일종의 신성불가침영역과도 같다. 어떤 DRI를 맡고 있다는 것은 동료들이 해당 업무에 대한 그 사람의 능력에 대해 신뢰하고 있다는 것이고, DRI를 잃는다는 것은 동료로부터 신뢰를 잃어 더 이상 토스팀에 필요없는 사람이 되는 것과 마찬가지이기 때문에 다들 죽기살기로 자신의 DRI를 지켜내기 위해 동료로부터 신뢰를 얻고 팀에 도움이 되려고 노력한다.&lt;/p&gt;
&lt;p&gt;즉, 아무리 CEO라고 해도 이 DRI를 리더의 권위로 뭉개고 뒤집어 엎으려고 한다면 “대표가 하라면 해야지…”가 아니라 “니가 뭔데 내 DRI를 위협해”와 같은 반응이 나오기 쉬운 환경이라는 이야기이다. 쉽게 말해서 토스에서 DRI를 건드는 행위를 하게 되면 생각보다 사람들이 많이 빡친다. &lt;small&gt;(속된 말로 발작버튼이 눌릴 수도 있다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그렇기 때문에 토스팀은 회사의 오너인 CEO조차도 쉽게 제품 개발에 이래라 저래라 할 수가 없는 문화라고 이야기하는 것이다. 실제로 CEO가 하지 말자고 했던 아이템을 PO가 끝까지 밀고나가서 성공시킨 사례도 있기 때문에, 이런 성공의 경험이 쌓여서 DRI를 존중하는 문화가 더 강력하게 유지된다.&lt;/p&gt;
&lt;p&gt;물론 CEO는 오랜 기간 이 도메인에서 사업을 해왔기 때문에 PO보다 사업에 대한 인사이트가 더 많이 있을 수 있지만, 제품의 방향성에 대한 DRI는 그 사일로의 PO가 가지고 있기 때문에 보통 토스의 CEO는 조언자의 역할을 주로 하게 되는 것 같다.&lt;/p&gt;
&lt;p&gt;그리고 이 DRI 덕분에 각 사일로는 본인들이 스스로 제품의 방향성을 결정하고 개발하고 결과를 관찰하는 이터레이션을 거치며 제품을 발전시킬 수 있게 되는 것이며, 이 과정 속에서 쓸데없는 보고나 확인 같은 절차가 없기 때문에 제품을 만드는 사람이 “나 이거 만들래!”라고 의사결정을 하고 하루이틀만에 제품을 개발해내는 &lt;a href=&quot;https://blog.toss.im/article/disasterfund-behindstory&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;재난지원금&lt;/a&gt; 같은 사례들이 나올 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;필자는 토스가 일을 빠르게 하고, 또 재밌게 할 수 있는 이유는 바로 이러한 완전한 권한의 위임에서부터 출발한다고 느꼈다. 애초에 누가 시켜서 만드는 것이 아니라 팀원들이 스스로 아이디어를 내고 제품을 발전시키기 때문에 제품에 대한 애정도가 높을 수 밖에 없지 않을까.&lt;/p&gt;
&lt;h3 id=&quot;실패에-관대한-문화&quot; style=&quot;position:relative;&quot;&gt;실패에 관대한 문화&lt;a href=&quot;#%EC%8B%A4%ED%8C%A8%EC%97%90-%EA%B4%80%EB%8C%80%ED%95%9C-%EB%AC%B8%ED%99%94&quot; aria-label=&quot;실패에 관대한 문화 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;토스팀은 새로운 시도로 인한 실패에 굉장히 관대한 조직이다. 심지어 코어 밸류에는 빨리 실패할 용기를 가지라는 말이 있었고, 전사에 자신의 실패 사례를 공유하는 Failure Party 같은 행사도 열릴 정도였으니 말이다.&lt;/p&gt;
&lt;p&gt;이런 문화가 있는 이유는 굉장히 간단한데, 실패를 두려워하지 않고 새로운 시도를 할 수 있는 환경을 제공하기 위해서이다.&lt;/p&gt;
&lt;p&gt;물리학자 사피 바칼은 본인의 저서인 &lt;a href=&quot;http://www.yes24.com/Product/Goods/90061659&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;룬샷(Loon Shots)&lt;/a&gt;에서 성공의 방정식 중 하나로 대다수가 무시하고 홀대하는 프로젝트를 빠르게 자주 시도해야 한다고 이야기한다. 이런 시도들이 쌓이다보면 어느 순간 임계점을 넘어서게 되고, 그때 비로소 문샷(Moon shots)을 쏠 수 있게 되는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 458px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/f7c3c/loon_shots.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 148.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgQF/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAMBAv/aAAwDAQACEAMQAAAB3svJyhhTllsJGlhI3//EAB8QAAIBBAIDAAAAAAAAAAAAAAECAwAEEhMRMRQhM//aAAgBAQABBQJI01646uFUOny6q69SLPivkGpGzMfAdCAB1//EABcRAAMBAAAAAAAAAAAAAAAAAAABEBH/2gAIAQMBAT8BuI//xAAXEQEBAQEAAAAAAAAAAAAAAAABABAS/9oACAECAQE/AYzpL//EACMQAAEDAwIHAAAAAAAAAAAAAAABAhEhMTISURAiQWFxkaH/2gAIAQEABj8CbyNtsYM9CQ1tugyk0MFE8CJpsm5h9EXsS+qDtVZtw//EAB0QAQADAAMAAwAAAAAAAAAAAAEAESExYXFBkfD/2gAIAQEAAT8hsbuNRuQsbr+MSuR1ZywHVePIuKbxhon7bHHvQQ1IK4dgpKRrDPiEYt9MKabn/9oADAMBAAIAAwAAABCD37D/xAAZEQACAwEAAAAAAAAAAAAAAAAAAREhMVH/2gAIAQMBAT8QoekLgnXB/8QAGBEBAAMBAAAAAAAAAAAAAAAAAQARITH/2gAIAQIBAT8QVvsTRN7ccQz/xAAeEAEBAAIBBQEAAAAAAAAAAAABEQAhMUFhcZGhUf/aAAgBAQABPxCotV+Ic/cmiRtuveYKEIWYnBm1V6k0x3tSqBqb+4AGEd8FgixBYS4shRBTrGdFOtu1v3LqRBzj48X3iKyd3X1eOT1kpZ5uf//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;loon shots&quot; title=&quot;&quot; src=&quot;/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/f7c3c/loon_shots.jpg&quot; srcset=&quot;/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/0913d/loon_shots.jpg 160w,
/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/cb69c/loon_shots.jpg 320w,
/static/3a6106ed1fa4e4c1dfa8fe3a68a2de80/f7c3c/loon_shots.jpg 458w&quot; sizes=&quot;(max-width: 458px) 100vw, 458px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;많은 이들이 손가락질 하는 프로젝트를 시도하고 실패해도 비난받지 않을 수 있는 환경이 결국 문샷을 만든다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;토스팀은 이 룬샷을 마음 편하게 쏠 수 있는 환경을 마련해두었다. 실패했다는 사실 자체가 아니라 실패에서 무엇을 배웠는지 인지하고 이 실패를 다른 사람들에게 공유해서 두 번 다시 동일한 실패 사례가 발생하지 않도록 만드는 것에 초점을 맞추고 있는 것이다.&lt;/p&gt;
&lt;p&gt;물론 실패는 예방할 수 없다라던가 실패를 발판삼아서 성장한다던가 같은 말들은 이미 많은 사람들이 알고 있는 말이지만, 실제로 실패를 두려워하지 않는 문화를 조직에 녹여내는 것은 생각보다 쉽지않다.&lt;/p&gt;
&lt;p&gt;그래서 토스팀은 Failure Party 같이 “우리가 실패에 얼마나 관대한지”를 팀 내부적으로 홍보하는 캠페인을 진행하거나 컬쳐팀이나 리더가 꾸준히 “실패해도 괜찮다”라는 메세지를 입에 달고 다니는 것이다.&lt;/p&gt;
&lt;p&gt;즉, 이렇게 조직 구성원들이 실패를 두려워하지 않는 문화를 정착시키기 위해서는 단순히 누군가 실패를 경험했을 때 그를 비난하지 않는 것이 아니라, 그보다 적극적인 액션들이 함께 동반되어야한다.&lt;/p&gt;
&lt;p&gt;사실 대부분의 사람들은 지금까지 살아오면서 실패를 장려하는 문화가 아닌 실패를 경질하는 문화를 더 많이 경험해왔기 때문에, 이런 적극적인 액션들이 동반되더라도 실패를 두려워하지 않는 문화가 하루아침에 정착되지는 않는다. 이런 문화는 문화를 만들기 위한 노력들이 회사가 설립된 순간부터 망하는 그 날까지 꾸준히 수행되는 과정에서 천천히 스며드는 것이기 때문이다.&lt;/p&gt;
&lt;p&gt;게다가 문화는 현재 상황을 유지하려는 일종의 관성을 가지고 있기 때문에, 처음부터 빌딩하는 것보다 중간에 도입하는 것이 더 큰 비용이 든다. 결국 여러분의 팀에 실패를 두려워하지 않는 문화를 정착시키고 싶다면 적어도 토스보다도 더 파격적이고 적극적인 액션들을 지속적으로 고민하고 수행해야 할 것이다.&lt;/p&gt;
&lt;h3 id=&quot;ceo-스스로도-문화를-유지하려고-노력한다&quot; style=&quot;position:relative;&quot;&gt;CEO 스스로도 문화를 유지하려고 노력한다&lt;a href=&quot;#ceo-%EC%8A%A4%EC%8A%A4%EB%A1%9C%EB%8F%84-%EB%AC%B8%ED%99%94%EB%A5%BC-%EC%9C%A0%EC%A7%80%ED%95%98%EB%A0%A4%EA%B3%A0-%EB%85%B8%EB%A0%A5%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;ceo 스스로도 문화를 유지하려고 노력한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;하지만 이런 문화들이 일반적인 스타트업에 정착되기란 참 쉽지 않은 일이다. 왜냐하면 기업 문화라는 것은 CEO의 영향을 가장 많이 받을 수 밖에 없는데, CEO 입장에서 실무자들에게 DRI를 넘기거나 팀원들이 실패하는 걸 가만히 보고 있는 것은 꽤나 용기가 필요한 일이기 때문이다.&lt;/p&gt;
&lt;p&gt;보통 우리는 친구들끼리 있는 술자리에서 이런 종류의 한탄아닌 한탄을 많이 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;우리 대표는 너무 디테일한 것까지 마이크로매니징을 해서 진짜 피곤해…우리를 못 믿나…? 이럴거면 날 왜 뽑은거래?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 필자도 이 부분에 대해서는 공감이 간다. 일반적으로 CEO는 경영의 전문가이지 제품 개발의 전문가는 아니니 말이다. 솔직히 그 제품을 개발하고 있는 PO, 디자이너, 개발자 입장에서는 전문가도 아닌 사람이 이래라 저래라하는 것이 귀찮고 짜증날 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 잠시만 입장을 바꿔서 생각해보면 그게 오히려 자연스럽고 인간다운 모습이기는 하다. 왜냐면 CEO는 회사가 잘 되었을 때 가장 큰 이익을 챙길 수 있는 사람이기도 하지만, 반대로 망했을 때 가장 큰 리스크를 지는 사람이기도 하기 때문이다.&lt;/p&gt;
&lt;p&gt;일반적으로 스타트업은 투자를 받을 때 투자자로부터 회사의 가치를 평가받고 그 평가된 가치로 주식 1주의 가격을 계산해서 주식을 넘겨주는 형태로 투자를 받는데, 이렇게 투자자들이 스타트업에 투자하는 과정은 우리가 일반적으로 주식을 사고 파는 행위와는 약간 차이가 있다.&lt;/p&gt;
&lt;p&gt;투자자들은 투자에 대한 리스크를 최대한 줄이기 위해 기업이 발행한 채권을 사서 돈을 빌려주고 나중에 채권을 주식으로 바꾸는 방법&lt;small&gt;(CB, 전환사채)&lt;/small&gt;을 사용하거나 자신이 원할 때 기업이 주식을 무조건 사줘야하는 조건 또는 꾸준히 배당금을 받겠다는 조건&lt;small&gt;(RCPS, 상환전환우선주)&lt;/small&gt;을 걸기도 하고, 지배주주가 지분을 매각할 때 투자자의 주식도 함께 팔아달라고 요구할 수 있는 조항&lt;small&gt;(Tag-along)&lt;/small&gt; 등을 적극적으로 사용하기도 하면서 안전장치를 걸어둔다.&lt;/p&gt;
&lt;p&gt;특히 RCPS 같은 우선주를 가진 투자자들은 보통주를 가진 일반주주들보다 여러가지 권리에 대해 우선권을 가지게 되는데, 문제는 CEO도 보통주를 가지고 있다는 것이다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 우선주를 가지고 있는 투자자가 기업이 망해서 청산당했을 경우 보통주를 가진 주주들보다 잔여재산을 먼저 분배받을 수 있는 권리나 투자자가 계약기간 중 원하는 시점에 기업에게 강제로 주식을 팔 수 있는 권리 등을 행사할 경우에는 기업이 손해를 보더라도 이 권리를 지켜줘야 하는 경우도 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;즉, 스타트업이 받는 투자는 절대 공짜가 아니며, 사업이 잘 안되었을 경우에는 CEO가 보는 금전적 손해 또한 충분히 발생할 수 있다는 것이다. 그리고 다들 아시다시피 이 금액은 한 두푼이 아니다.&lt;/p&gt;
&lt;p&gt;솔직히 이런 상황에서 직원들에게 제품 방향성에 대한 모든 의사결정권을 위임하거나 실패를 용인한다는 결정을 실천하는 것은 결코 쉽지 않다. 아무리 자신의 손으로 뽑은 직원이라고 해도 이 직원이 자신처럼 “내 사업이다”라고 생각할거라는 신뢰를 가지기가 어렵기 때문이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a133e4bae8986cb83c7de28c3bdd1b9e/8e1fc/out.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQT/xAAUAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAGGvELgEEf/xAAbEAACAgMBAAAAAAAAAAAAAAABAgADBBEhIv/aAAgBAQABBQJum5C6lmaVesewRjs//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAECIRBRcf/aAAgBAQAGPwLjKtxLbJN7z//EABsQAQADAQADAAAAAAAAAAAAAAEAESExQWFx/9oACAEBAAE/IQhuW1B1uo9xy3P2PoXyg47ZvY1r1n//2gAMAwEAAgADAAAAEBzv/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EBEyb//EABYRAQEBAAAAAAAAAAAAAAAAAAEQIf/aAAgBAgEBPxANn//EABwQAQADAQEAAwAAAAAAAAAAAAEAESFRQTFxof/aAAgBAQABPxCzq5z6S/2GSgoqgppfcKmfsrVhyvIlQOgjZx4pr5PYle9F6z//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;out&quot; title=&quot;&quot; src=&quot;/static/a133e4bae8986cb83c7de28c3bdd1b9e/c08c5/out.jpg&quot; srcset=&quot;/static/a133e4bae8986cb83c7de28c3bdd1b9e/0913d/out.jpg 160w,
/static/a133e4bae8986cb83c7de28c3bdd1b9e/cb69c/out.jpg 320w,
/static/a133e4bae8986cb83c7de28c3bdd1b9e/c08c5/out.jpg 640w,
/static/a133e4bae8986cb83c7de28c3bdd1b9e/8e1fc/out.jpg 900w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;아니 이 자식, CEO들을 옹호하는 발언을 해? 알고보니 사측이었잖아?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;필자가 이런 이야기를 하는 이유는 “그러니까 CEO들의 마이크로매니징을 이해해주자”라는 의미가 아니라, 오히려 그 반대이다. 이렇게 큰 리스크를 어깨에 짊어지고 있는 상황임에도 불구하고 사업을 성공시키고 싶다면 CEO부터가 팀원들을 신뢰하고 권한을 위임하는 문화를 만들기 위해 노력해야 한다는 이야기를 하고 싶은 것이다.&lt;/p&gt;
&lt;p&gt;CEO가 아무리 대단한 사람이라고 할지라도 한 사람이 세상 모든 일을 전부 다 잘 할수는 없는 노릇이다. 게다가 시니어 레벨의 팀원을 영입했다면 그 사람은 CEO보다 그 분야에 있어서 훨씬 더 베테랑이라는 것을 의미하며, 제대로 된 시니어라면 당연히 비즈니스 레벨의 이슈들도 모두 트래킹하면서 의사결정을 진행할 수 있는 능력을 지니고 있다.&lt;/p&gt;
&lt;p&gt;즉, CEO가 이래라 저래라 하는 것보다 그냥 팀원에게 권한을 위임하고 각자 잘 하는 분야를 맡아서 협업하는 것이 더 효율적이라는 것이다.&lt;/p&gt;
&lt;p&gt;물론 함께 일하다보면 믿었던 팀원이 실패하는 모습들도 보게 될 것이고 이에 실망하는 경우도 있을 수 있다. 하지만 팀원이 저지른 몇 번의 실패 때문에 한번 CEO가 마이크로매니징을 하기 시작하면, 혹여 여러분의 팀원들이 잘 할 수 있는 부분이 있더라도 “어차피 자기 맘대로 할텐데 뭐”라고 생각하며 본인의 능력을 발휘하는 것을 포기하거나, 최악의 경우에는 유능한 직원들이 회사를 떠나는 상황까지도 펼쳐질 수 있다.&lt;/p&gt;
&lt;p&gt;CEO가 사사건건 관여하며 내 능력을 제한하는 회사라면 굳이 여기 있어봤자 재미도 없고 성장도 할 수 없지 않은가?&lt;/p&gt;
&lt;p&gt;이런 상황이 반복되다보면 회사에는 능동적으로 의사결정을 수행하며 자신의 능력을 발휘하는 사람들이 모두 떠나거나, 혹은 수동적으로 변한 상태가 되고, CEO가 일일히 의사결정해주지 않으면 직원들 스스로는 아무것도 결정하지 못 하는 반쪽짜리 조직이 될 수도 있다.&lt;/p&gt;
&lt;p&gt;필자가 지금도 토스의 CEO인 승건님을 대단하다고 생각하는 이유는 단순히 이 분이 일을 잘 해서, 똑똑해서라기보다는 이런 부분을 스스로 인지하고 권한을 위임하는 문화를 본인이 직접 주도해나가고 있다는 점이다.&lt;/p&gt;
&lt;p&gt;아무리 대단한 사람이라고 해도 결국 사람인 이상 사업 실패에 대한 두려움은 당연히 있을텐데, 그런 두려움을 이겨내고 팀원들을 온전히 신뢰하고 권한을 위임하며 실패를 장려하는 문화를 만들어나간다는 것 자체가 일반인 수준의 멘탈리티는 아니라고 생각한다.&lt;/p&gt;
&lt;p&gt;물론 필자가 상기했던 DRI라던가 실패를 자유롭게 경험할 수 있는 환경이라는 토스의 문화는 정답이 아닐수도 있다. 실제로 토스 내에서도 계속 새로운 시도를 하며 문화를 발전시켜나가고 있고 말이다.&lt;/p&gt;
&lt;p&gt;하지만 그 문화가 무엇이던간에 CEO, 즉 리더의 관심없이는 조직 내에 문화가 정착되기 어렵다. 아무리 문화에 관심있는 팀원들이 이리 뛰고 저리 뛰고 해봐도 결국 CEO가 “하지마”라는 말 한마디만 하면 다시 롤백되는 환경이라면 팀원들의 노력이 크게 의미없기도 하고, 어찌어찌 문화를 정착시킨다고 해도 리더부터 그 문화를 지키려는 노력을 하지 않는다면 다른 팀원들도 굳이 그 문화를 지키려고 하지 않게 되기 때문이다.&lt;/p&gt;
&lt;h2 id=&quot;빠르게-성장한-조직의-문제&quot; style=&quot;position:relative;&quot;&gt;빠르게 성장한 조직의 문제&lt;a href=&quot;#%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EC%84%B1%EC%9E%A5%ED%95%9C-%EC%A1%B0%EC%A7%81%EC%9D%98-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;빠르게 성장한 조직의 문제 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사실 토스의 문화도 재밌는 부분이 많았고 새로운 경험이기는 했지만, 필자가 이 회사에서 경험했던 것들 중에서 가장 값진 것은 문화가 아니다.&lt;/p&gt;
&lt;p&gt;필자가 토스라는 곳에서 얻어갈 수 있었던 가장 값진 것은 바로 “시니어 개발자란 무엇인지”에 대해서 본격적으로 고민을 함과 동시에 실제로 그런 역할을 수행해볼 수 있는 기회를 얻을 수 있었던 것이다.&lt;/p&gt;
&lt;p&gt;필자는 토스에 입사하고 첫 연봉협상을 진행할 때 본인의 성장 뿐만 아니라 팀을 성장시킬 수 있는 사람이 되어달라는 피드백을 받았었다.&lt;/p&gt;
&lt;p&gt;물론 필자도 평소에 시니어란 무엇인가에 대한 고민을 거듭하고 있는 상황이었고, 어느 정도는 이 피드백과 비슷한 방향성을 잡고 있는 상태였다. 그렇기 때문에 친구들과 함께 &lt;a href=&quot;https://lubycon.medium.com/%EC%84%B8-%EB%B2%88%EC%A7%B8-%EB%A9%98%ED%86%A0%EB%A7%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0-27c156e62568&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;루비콘 멘토링 프로젝트&lt;/a&gt;와 같이 다른 사람들을 도와주고 성장시킬 수 있는 경험을 쌓으려고 했던 것이다.&lt;/p&gt;
&lt;p&gt;하지만 필자는 스스로 토스팀에서 이런 영향력을 행사할 수 있을 것이라고 생각하지는 않았기 때문에, 당시 저 피드백을 들었을 때 이런 생각을 했었다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 420px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6817a30c0c9d171cfd58a1f1f56210d6/65f94/what.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 86.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAUC/9oADAMBAAIQAxAAAAHBrlep5CB/ecLTsETv/8QAGxAAAwACAwAAAAAAAAAAAAAAAAECAzERIUH/2gAIAQEAAQUCd0JNLljxdzoorfn/xAAbEQABBAMAAAAAAAAAAAAAAAACAAEDEBEyYf/aAAgBAwEBPwEhyPbk3df/xAAaEQABBQEAAAAAAAAAAAAAAAACAAEDEBEy/9oACAECAQE/AQPCuPhl/8QAGxAAAgMAAwAAAAAAAAAAAAAAAAEQESExQXH/2gAIAQEABj8Cw5cXfRsIYvD/xAAdEAEAAgEFAQAAAAAAAAAAAAABABExIUFRYaFx/9oACAEBAAE/ITIPV34gVWnYymjCzA424lNTH4J7o+Cf/9oADAMBAAIAAwAAABDs8MP/xAAXEQEBAQEAAAAAAAAAAAAAAAABABGh/9oACAEDAQE/EDYYqOM3Zf/EABgRAQEBAQEAAAAAAAAAAAAAAAEAESGh/9oACAECAQE/EEJ3kYmkXkv/xAAfEAEBAAEDBQEAAAAAAAAAAAABEQAhMUEQUWFx8PH/2gAIAQEAAT8QKhSMYVGu9JHP0sVULYsJ654xi4INdmaaYyqUYxz63jpXxO2f/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;what&quot; title=&quot;&quot; src=&quot;/static/6817a30c0c9d171cfd58a1f1f56210d6/65f94/what.jpg&quot; srcset=&quot;/static/6817a30c0c9d171cfd58a1f1f56210d6/0913d/what.jpg 160w,
/static/6817a30c0c9d171cfd58a1f1f56210d6/cb69c/what.jpg 320w,
/static/6817a30c0c9d171cfd58a1f1f56210d6/65f94/what.jpg 420w&quot; sizes=&quot;(max-width: 420px) 100vw, 420px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/center&gt;
&lt;blockquote&gt;
&lt;p&gt;아니 토스에 있는 FE들은 다 나보다 일을 잘 하는 것 같은데 도대체 뭘 도와주라는 거지…?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;내가-입사할-당시의-프론트엔드-챕터의-분위기&quot; style=&quot;position:relative;&quot;&gt;내가 입사할 당시의 프론트엔드 챕터의 분위기&lt;a href=&quot;#%EB%82%B4%EA%B0%80-%EC%9E%85%EC%82%AC%ED%95%A0-%EB%8B%B9%EC%8B%9C%EC%9D%98-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%B1%95%ED%84%B0%EC%9D%98-%EB%B6%84%EC%9C%84%EA%B8%B0&quot; aria-label=&quot;내가 입사할 당시의 프론트엔드 챕터의 분위기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자가 이렇게 생각했던 이유를 알기 위해서는 필자가 처음 입사했을 당시 프론트엔드 챕터의 분위기가 어땠는지에 대해서 먼저 알아야 한다.&lt;/p&gt;
&lt;p&gt;필자가 처음 토스에 입사했던 2019년에는 프론트엔드 개발자가 총 10명이 조금 넘는 정도 밖에 안 되었고, 토스팀 전체 인원도 아마 300명이 조금 넘는 수준이었던 걸로 기억한다. 그 당시는 막 토스뱅크를 위해 인터넷 은행 예비인가를 받은 시점이었는데, 회사 규모나 가치에 비하면 인원이 확실히 적은 편이긴 했다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e091f84babb31169e17d75eda86fc732/d2602/fe_chapter.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 82.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQDAv/EABcBAAMBAAAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAaUWs1SgMy5BBGn/xAAeEAABBAEFAAAAAAAAAAAAAAABAAIDEhEhIjEyQ//aAAgBAQABBQKgRDQLIOyTJsEukXXzZx//xAAXEQADAQAAAAAAAAAAAAAAAAAAAhAx/9oACAEDAQE/AauH/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/Aaz/xAAcEAABAwUAAAAAAAAAAAAAAAAAARAxAhEhQVH/2gAIAQEABj8CkkwXTUnWqEb/xAAeEAACAQQDAQAAAAAAAAAAAAAAAREhMUFxEJGx8f/aAAgBAQABPyFfGTp0aKEsSIa2r2CaacGx6hTrhv3L2z//2gAMAwEAAgADAAAAEKQQfv/EABgRAAMBAQAAAAAAAAAAAAAAAAABIREx/9oACAEDAQE/EHuRiqo+I4H/xAAXEQADAQAAAAAAAAAAAAAAAAAAATFB/9oACAECAQE/EFR00pn/xAAeEAEAAgICAwEAAAAAAAAAAAABABEhUTGhYbHB8P/aAAgBAQABPxAIbQofTV4US44aq5mGDDQLvjeWFS6Ba+QanHALfU6hPz+Sd/P/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;fe chapter&quot; title=&quot;&quot; src=&quot;/static/e091f84babb31169e17d75eda86fc732/c08c5/fe_chapter.jpg&quot; srcset=&quot;/static/e091f84babb31169e17d75eda86fc732/0913d/fe_chapter.jpg 160w,
/static/e091f84babb31169e17d75eda86fc732/cb69c/fe_chapter.jpg 320w,
/static/e091f84babb31169e17d75eda86fc732/c08c5/fe_chapter.jpg 640w,
/static/e091f84babb31169e17d75eda86fc732/6a068/fe_chapter.jpg 960w,
/static/e091f84babb31169e17d75eda86fc732/eea4a/fe_chapter.jpg 1280w,
/static/e091f84babb31169e17d75eda86fc732/d2602/fe_chapter.jpg 4032w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    프론트엔드 개발자 20명만 되면 진짜 소원이 없겠다고 말하고 다닐 때
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;당시 토스팀은 “최고의 인재에게 최고의 보상을”이라는 채용 캐치프라이즈를 내걸만큼 높은 인재밀도를 만들어내기 위한 채용전략에 집중하고 있었고, 실제로 높은 인재밀도를 구축하는데 성공해서 이른바 정예 스포츠팀 같은 조직을 만들어 낼 수 있었다.&lt;/p&gt;
&lt;p&gt;이게 그냥 말 뿐만이 아닌게, 실제로 토스의 신규입사자들은 주변 동료들의 업무 능력에 대해서 상당한 압박감을 느낀다. 물론 일의 양도 일의 양이지만 그 많은 일들을 어떻게든 말끔하게 처리해내는 모습을 보면 “나 여기서 버틸 수 있나…?”라는 생각이 들 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;물론 필자가 대한민국에 있는 회사를 전부 다녀본 것은 아니기 때문에 토스팀이 절대적으로 다른 곳보다 일을 잘 한다고 말하기는 어렵겠지만, 적어도 필자가 지금까지 경험해본 조직들 중에서는 가장 일을 잘 하는 조직이기는 했다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/58d328fdeff4c59ca29c3e17f42d0949/b4294/wakgood.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABQD/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAR2h3M1Go//EABwQAAAGAwAAAAAAAAAAAAAAAAECAwQTIRESNP/aAAgBAQABBQI4025EMxyUytqkGpP/xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwEn/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAEx/9oACAECAQE/AbiP/8QAGxAAAwACAwAAAAAAAAAAAAAAAAExESFRYXH/2gAIAQEABj8CUgvWbFZyY7Zg/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARUSExQf/aAAgBAQABPyGsT0fhCtLXKNHKg7CoVShAB10yURbDZ//aAAwDAQACAAMAAAAQGC//xAAXEQEBAQEAAAAAAAAAAAAAAAABABEh/9oACAEDAQE/EFjJ2//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQIBAT8QOqXL/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBUWGBwf/aAAgBAQABPxAAbLbYjXce1NhFNpU288IB3EQoICl16iHOFyWMxH5LTtlv7P/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;wakgood&quot; title=&quot;&quot; src=&quot;/static/58d328fdeff4c59ca29c3e17f42d0949/b4294/wakgood.jpg&quot; srcset=&quot;/static/58d328fdeff4c59ca29c3e17f42d0949/0913d/wakgood.jpg 160w,
/static/58d328fdeff4c59ca29c3e17f42d0949/cb69c/wakgood.jpg 320w,
/static/58d328fdeff4c59ca29c3e17f42d0949/b4294/wakgood.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;토스는 목표만 Align되고 나면 &quot;그냥 각자 알잘딱합시다.&quot;라고만 해도 일이 잘 돌아가는 신기한 곳이었다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그래서인지 필자는 같은 프론트엔드 챕터에 있는 사람들의 성장에 대해서는 상당히 무관심했는데, 그 이유는 우리 챕터에 있는 사람들은 모두 각자 알아서 잘 하는 사람들이라고 생각했기 때문이다. 그리고 앞서 이야기했듯이 이렇게 주변에 일 잘하는 놈들이 널려있는 환경이라면 내가 성장하는게 우선이지 남의 성장 따위는 신경쓸 겨를이 없기도 하다.&lt;/p&gt;
&lt;p&gt;물론 기술적인 토론이나 사내 스터디 같은 것들은 활발하게 이루어졌지만, 이런 활동들은 나보다 부족한 다른 사람을 성장시키는 것이라기보다는 서로 자극을 주고 받으며 우리가 함께 성장하자는 마음에 가까운 액션아이템이다. 그래서 필자에게 당시 프론트엔드 챕터는 실력이 비슷비슷한 친구들끼리 모여서 서로 자극을 주고 받으며 함께 성장하는 그런 느낌이었다고 기억된다.&lt;/p&gt;
&lt;p&gt;즉, 당시 프론트엔드 챕터 내부의 문화를 정리하자면 이렇게 리스트업해볼 수 있겠다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;사람이 적기 때문에 서로 얼굴, 이름을 다 알고 친밀도가 높은 편이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;서로의 능력에 대한 신뢰도가 높고, 조직원들 스스로 나도 팀원들에게 신뢰받고 있다는 생각을 하고 있다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이러한 친밀도와 신뢰를 바탕으로 프론트엔드 챕터라는 조직에 대한 심리적 안정감이 형성되어있다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;주니어-개발자라는-개념의-등장&quot; style=&quot;position:relative;&quot;&gt;주니어 개발자라는 개념의 등장&lt;a href=&quot;#%EC%A3%BC%EB%8B%88%EC%96%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%9D%BC%EB%8A%94-%EA%B0%9C%EB%85%90%EC%9D%98-%EB%93%B1%EC%9E%A5&quot; aria-label=&quot;주니어 개발자라는 개념의 등장 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;하지만 이러한 프론트엔드 챕터의 문화는 2020년을 기점으로 조금씩 달라지기 시작했다. 필자가 생각하는 원인은 크게 두 가지인데, 하나는 꼴랑 10명 초반대에 불과했던 챕터의 크기가 급격하게 빠른 속도로 커졌다는 것, 그리고 다른 하나는 주니어라는 개념이 등장했다는 것이다.&lt;/p&gt;
&lt;p&gt;사실 그 전까지의 프론트엔드 챕터는 이미 서로에 대한 신뢰가 형성되어있기 때문에 내가 누군가를 성장시키기 위해 일방적으로 도와줘야 한다는 개념 자체가 희박했다.&lt;/p&gt;
&lt;p&gt;하지만 토스팀이 &lt;a href=&quot;https://toss.im/career/next-developer-2021&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;NEXT Developer&lt;/a&gt;와 같은 프로그램을 만들면서까지 현재 실력이 출중하지 않더라도 앞으로의 성장 가능성이 큰 사람에게 기대를 걸고 채용하겠다는 공격적인 채용 스탠스를 취하면서 토스팀에는 “성장을 위해 도움을 받아야하는 팀원”이라는 페르소나가 생기기 시작했으며, 이 페르소나를 “주니어”라고 불렀다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e2829c2438dce41760ecec2a2fbe9220/6052f/next2021.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 70.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABYlAAAWJQFJUiTwAAABnklEQVR42pVTy27CMBCME5I4j5aGkEcreuQIF5BoAYF4SzSIG9w48v9/MN3dKipVg4DDyPZoPbveWRtZlqHdbiPPc0RRBKUUTNMU8N5xHARhiJAQBAEajQY8z5dYrTXSNIXv+8K7rguDL9q2DcuyRMQwjH9g4RJlojK2PJcwrglU8XfhUp1Rq9UEXDU/gZ/M4D3D8zx5KnMcU5H898ABu90OnU4Hg8EAy+US0+kUk8kERVHIej6fhdtsNrKXvl0TZCRJgvF4jH6/j/l8jm63i9VqJdx6vcbxeJQ9c2xmxbP/EpxxsVhgOByKWK/Xw3a7xQdVXBRfxH9iNBqJeL1er+r59QYrcpDdV4pW6qtpWsLdMKbaZYcqbaY50tcWkrwla/72LpymOTSvC1dn4opcdtN7huU3UNNPlEQT59MU2I9VyODRaTZjMqmJPEuR0Y9I00xM45F5WJC/02w2w36/x+l0EncPh4Nw1Wao2xXy/2TEcSxrFPE5pgo1xdB/N8gow/6BciiBVK4u1e8AC/lw1As8FeHJjBDaETxNiYIE3ymPQYmdVFPZAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;next2021&quot; title=&quot;&quot; src=&quot;/static/e2829c2438dce41760ecec2a2fbe9220/6af66/next2021.png&quot; srcset=&quot;/static/e2829c2438dce41760ecec2a2fbe9220/69538/next2021.png 160w,
/static/e2829c2438dce41760ecec2a2fbe9220/72799/next2021.png 320w,
/static/e2829c2438dce41760ecec2a2fbe9220/6af66/next2021.png 640w,
/static/e2829c2438dce41760ecec2a2fbe9220/d9199/next2021.png 960w,
/static/e2829c2438dce41760ecec2a2fbe9220/21b4d/next2021.png 1280w,
/static/e2829c2438dce41760ecec2a2fbe9220/6052f/next2021.png 2030w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;NEXT Developer 공채 페이지에는 대문짝만하게 &quot;3년차 이하 개발자&quot;라고 적혀있다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;NEXT Developer는 일종의 주니어 공채 같은 느낌이었는데, 문제는 이렇게 대외적으로 “저희 주니어 뽑아요!”라고 커뮤니케이션을 했던 채용 퍼널을 통해 입사하신 분들의 심리 상태는 일반 채용 과정을 통해서 입사하셨던 분들과 약간 차이가 있다는 것이다.&lt;/p&gt;
&lt;p&gt;물론 해당 프로그램을 통해 훌륭하신 분들을 많이 모실 수 있었지만, 당시 필자는 NEXT Developer를 통해 채용된 몇몇 분들의 행동 패턴이 기존에 있던 사람들과 약간 다르다는 느낌을 받았는데, 대표적으로 차이를 느낀 지점은 대충 이렇다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;왜 대부분 좋다, 괜찮다고만 말씀하시지? 맘에 안 드는 부분이 없으신가?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;저 의견은 근거가 없는 주관적인 의견인데, 왜 그대로 받아들이시지?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;왜 챕터 활동에 적극적으로 참여를 안 하실까?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;사실 이런 특징들은 아직 조직에 적응하지 못한 신규입사자들의 일반적인 특징이기 때문에 크게 이상하지 않다고 생각할 수도 있지만, 이때까지 필자가 경험했던 토스의 신규입사자들은 보통 입사하고 얼마 되지 않았음에도 불구하고 기존의 챕터가 가지고 있던 문제점에 대해 강하게 챌린지를 하거나 사내 라이브러리에 기여를 하는 등 활발한 활동을 하는 경우가 많았다.&lt;/p&gt;
&lt;p&gt;또한 단순히 실력이나 연차의 차이라고 하기도 이상했던 것이, 같은 NEXT Developer 퍼널을 통해서 입사하신 분들 중에서도 저런 행동 패턴을 보이는 분과 아닌 분이 나뉘었다. 그래서 필자는 도대체 어떤 이유로 이런 적극성이나 조직 적응 시간에 대한 차이가 발생하는지에 대한 고민을 했던 것이다.&lt;/p&gt;
&lt;h3 id=&quot;왜-이-분들은-소극적일까&quot; style=&quot;position:relative;&quot;&gt;왜 이 분들은 소극적일까?&lt;a href=&quot;#%EC%99%9C-%EC%9D%B4-%EB%B6%84%EB%93%A4%EC%9D%80-%EC%86%8C%EA%B7%B9%EC%A0%81%EC%9D%BC%EA%B9%8C&quot; aria-label=&quot;왜 이 분들은 소극적일까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;다행히 이런 문제의식은 필자 뿐 아니라 몇몇 다른 프론트엔드 개발자분들도 가지고 계셨었고, 이러한 행동의 차이가 하드 스킬의 차이, 즉 자신이 이 조직에서 개발자로써 1인분의 역할은 하고 있다는 자신감의 차이가 아닐까 정도로 이야기가 되었었던 걸로 기억한다.&lt;/p&gt;
&lt;p&gt;그래서 당시 챕터에서는 개발자들의 하드 스킬 상향 평준화를 위해 스터디, 오프라인 코드리뷰, 메이트와의 페어프로그래밍 등을 적극적으로 추진했었다.&lt;/p&gt;
&lt;p&gt;하지만 여기에는 함정이 하나 있는데, 이러한 활동들의 기술적 수준이 하드 스킬 능력이 좋은 팀원들에게 맞춰져있는 경우가 많았다는 것이다. 아무래도 지금까지의 프론트엔드 챕터는 모두 함께 성장하는 것을 추구했던 조직이기 때문에 Promise, React와 같이 이미 알고 있는 기초적인 내용보다는 추상화, 대수적 효과처럼 모두가 새롭게 익히고 토론하며 성장할 수 있는 내용들이 선정되기 쉬운 환경이었다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 546px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1a5521288f83b55d96114e32c9d3b6ef/f066e/hard_user.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAVABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQFAv/EABYBAQEBAAAAAAAAAAAAAAAAAAIEAf/aAAwDAQACEAMQAAAB2+M+omtGRmElIHf/xAAbEAABBAMAAAAAAAAAAAAAAAARAAECEBIiQf/aAAgBAQABBQKUgulqO2bUa//EABkRAQACAwAAAAAAAAAAAAAAAAEAAhASUf/aAAgBAwEBPwG60m1uRBx//8QAGhEAAgIDAAAAAAAAAAAAAAAAAQIAEBESUf/aAAgBAgEBPwFG2mV7ASK//8QAGRAAAgMBAAAAAAAAAAAAAAAAEBEAMWGB/9oACAEBAAY/AricscKwf//EAB0QAAIBBQEBAAAAAAAAAAAAAAERABAhMYGRQXH/2gAIAQEAAT8hClnYwPb9gAMO0RNoR4vR3op//9oADAMBAAIAAwAAABBjD7//xAAaEQEAAQUAAAAAAAAAAAAAAAARAAEQITFh/9oACAEDAQE/ECMLOuGNNW//xAAZEQEAAgMAAAAAAAAAAAAAAAARAAEQQWH/2gAIAQIBAT8QoeicEcMf/8QAGxABAQACAwEAAAAAAAAAAAAAAREAMRAhYUH/2gAIAQEAAT8QrCahptxkhVdJPcOl4Sxj8e1GlfuNRgb3QYxK9BwtadC/LeP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;hard user&quot; title=&quot;&quot; src=&quot;/static/1a5521288f83b55d96114e32c9d3b6ef/f066e/hard_user.jpg&quot; srcset=&quot;/static/1a5521288f83b55d96114e32c9d3b6ef/0913d/hard_user.jpg 160w,
/static/1a5521288f83b55d96114e32c9d3b6ef/cb69c/hard_user.jpg 320w,
/static/1a5521288f83b55d96114e32c9d3b6ef/f066e/hard_user.jpg 546w&quot; sizes=&quot;(max-width: 546px) 100vw, 546px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이건 마치 고인물만 득시글거리는 게임에 뉴비 몇 명이 들어온 느낌이랄까&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;여기서의 문제는 이렇게 자신의 지식을 크게 넘어서는 내용에 대한 이야기가 오가는 상황이라면 애초에 그 지식을 흡수하기도 어려울 뿐더러 오히려 자신이 부족해서 이런 이야기를 알아듣지 못 한다는 생각에 더 큰 부담감이나 자책감까지도 생길 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;게다가 NEXT Developer같은 채용 프로그램은 처음부터 “주니어”를 뽑겠다고 대놓고 홍보했던 프로그램이었기 때문에 이 퍼널을 통해 입사하신 분들은 실제 본인의 하드 스킬 수준이 어느 정도던 간에 스스로를 아직 실력이 부족한 주니어라고 인지하는 경향이 있었고, 이로 인해 이런 감정을 느끼기 더 쉬운 상황이었다.&lt;/p&gt;
&lt;p&gt;사실 필자도 스터디를 진행할 때까지는 이런 생각을 전혀 못 하고 있다가 나중에 1 on 1 커피챗을 진행하면서 알게 되었는데, 이때부터 필자는 이게 단순히 하드스킬의 차이가 아니라 스스로 느끼는 자신감에 대한 문제라고 생각했다.&lt;/p&gt;
&lt;p&gt;토스팀이 챌린지 문화나 투명한 피드백 문화를 지향하고 있기는 하지만, 사실 이런 것들은 자신이 팀 내에서 최소한 1인분의 역할 정도는 하고 있다는 자신감이 기반이 되어야 행동에 옮길 수 있다. 스스로도 잘 하고 있는지 못 하고 있는지 긴가민가한 상황에서 자신의 의견을 적극적으로 밀어붙히거나 다른 사람에게 피드백을 주는 것은 굉장한 용기를 필요로 하기 때문이다.&lt;/p&gt;
&lt;p&gt;또한 조직에 대한 심리적 안정감에 대한 차이도 있었는데, 예전에는 챕터에 고작 10명 남짓의 인원 밖에 없었고 기술적인 수준도 비슷했기 때문에 서로 빠르게 친해지고 신뢰가 형성되기도 쉬운 환경이었다.&lt;/p&gt;
&lt;p&gt;이렇게 서로가 어떤 성격인지, 일 하는 스타일은 어떤지 잘 알고 있다면 다소 통랄한 피드백을 주고 받더라도 이 사람이 정말로 팀의 발전을 위해 나에게 이런 이야기를 하는 것, 그리고 이 피드백에는 어떠한 감정도 없다는 일종의 확신을 하기가 쉽고, 또 이런 확신이 조직에 대한 심리적 안정감과 신뢰로 이어질 수 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5d46f54049984addc8b6d03c043eb3a3/b4294/passion.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAeJukzJGf//EABwQAAEDBQAAAAAAAAAAAAAAAAIAAQMREiEiMv/aAAgBAQABBQLpyG16osQRbAv/xAAVEQEBAAAAAAAAAAAAAAAAAAAQQf/aAAgBAwEBPwGH/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABsQAAIBBQAAAAAAAAAAAAAAAAAREAEDEjFR/9oACAEBAAY/AkKHTeRcfI//xAAcEAEAAgIDAQAAAAAAAAAAAAABACERQTFhgaH/2gAIAQEAAT8hBC1upVM47gjhiSo2+RqLpn9I2z//2gAMAwEAAgADAAAAENjP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EA2P/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxAf/8QAGhABAQEBAQEBAAAAAAAAAAAAAREAMSFBUf/aAAgBAQABPxAwrSP1gXwgS6+lw0UMp3BHYUZzmQX4kMlF7v/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;passion&quot; title=&quot;&quot; src=&quot;/static/5d46f54049984addc8b6d03c043eb3a3/b4294/passion.jpg&quot; srcset=&quot;/static/5d46f54049984addc8b6d03c043eb3a3/0913d/passion.jpg 160w,
/static/5d46f54049984addc8b6d03c043eb3a3/cb69c/passion.jpg 320w,
/static/5d46f54049984addc8b6d03c043eb3a3/b4294/passion.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;토스 사람들이 좀 빡세보이긴 해도 워낙 일에 진심이라서 그런 것 뿐이지, 막상 알고보면 순딩이들이 많다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;하지만 점차 인원이 많아지게 되면서 이제 서로 이름과 얼굴도 잘 모르는 상황이 되어버린데다가 챕터 내에 하드스킬의 차이로 인한 위계까지 생겨버린 상황이니 “내가 이런 이야기를 하면 내가 못 하는 사람으로 보이지는 않을까?”, “내가 지금 이런 이야기를 하는게 맞을까?”와 같은 걱정들도 자연스럽게 생겨버린 것이다. 그리고 이런 상황은 조직에 대한 심리적 안정감을 떨어트리는 요인이 될 수 있다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 이렇게 소극적인 행동의 원인이 단순한 하드 스킬 수준의 차이가 아니라 내가 이 조직의 일원으로써 녹아들 수 있다는 자신감의 차이, 그리고 챕터에서 느끼는 심리적 안정감의 차이라고 생각했고, 오히려 스터디나 페어프로그래밍처럼 하드 스킬의 성장을 이끌어낼 수 있는 방향과는 다른 방향으로 접근해야겠다는 생각이 들었다.&lt;/p&gt;
&lt;h2 id=&quot;f-evangelist의-등장&quot; style=&quot;position:relative;&quot;&gt;F-Evangelist의 등장&lt;a href=&quot;#f-evangelist%EC%9D%98-%EB%93%B1%EC%9E%A5&quot; aria-label=&quot;f evangelist의 등장 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 이야기 했듯 2021년 Next Developer 프로그램을 끝마쳤을 때 즈음, 이제 프론트엔드 챕터의 인원은 거의 60명에 육박할 정도로 예전에 비하면 굉장히 거대한 조직이 되어버렸다.&lt;/p&gt;
&lt;p&gt;그러다보니 예전과 달리 같은 프론트엔드 챕터끼리도 얼굴이나 이름을 모르는 사람들이 생기기 시작했고, 조직원들의 친밀도는 빠르게 낮아지기 시작했다. &lt;small&gt;(OO님이 누구야? 라는 질문이 점차 많아지던 시절…)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이렇게 낮아진 친밀도는 챕터의 여러 의사결정에 대한 사람들의 참여도에도 좋지 않은 영향을 끼쳤고, 서로에 대해 피드백이나 심지어는 기술적인 의견을 자유롭게 주고 받는 문화도 점차 흐려지게 되었다. 그리고 이런 현상은 앞서 이야기했던 주니어 세그먼트에서 더 잦게 발생하고 있었다.&lt;/p&gt;
&lt;p&gt;처음에는 챕터 내에서도 “그래도 예전같은 분위기를 만들기 위해 해볼 수 있는 것은 다 해봐야한다”라는 회귀파의 여론이 강했지만, 점차 시간이 흐르고 인원이 더 늘어나게 되자 현실을 인정하고 현재 챕터의 규모에 맞는 방법을 찾아야한다는 현실파 쪽으로 기울기 시작했다.&lt;/p&gt;
&lt;p&gt;그 당시 필자는 처음부터 현실파 쪽에 가까웠는데, 필자가 강하게 주장했던 것은 모두 같은 나이, 비슷한 수준을 가지고 있는 학생 때도 40명 밖에 안 되는 같은 반 친구들조차 전부 친하게 지내지 못 하는데, 인원도 더 많고 하드스킬 수준에 따라 위계가 생겨버린 현재의 프론트엔드 챕터에서 어떻게 예전 같은 친밀도가 형성되기를 기대하냐는 것이었다.&lt;/p&gt;
&lt;p&gt;즉, 이제 프론트엔드 챕터는 고작 10명 남짓으로 구성된 조직의 규모가 아닌 60명이 넘는 조직에서의 친밀도를 높히고 조직에 대한 심리적 안정감을 만들어낼 수 있는 새로운 방법을 강구해야했다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6167a981411988d8ff05e1fe86ac3795/d7854/school_class.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAQP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAAd5LWKE5m//EABoQAAIDAQEAAAAAAAAAAAAAAAECAxESEyL/2gAIAQEAAQUChY7aReozT+QxOzAL/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8BR//EABwQAAIBBQEAAAAAAAAAAAAAAAABIQIDEBExYv/aAAgBAQAGPwJq5txwcxjaRQ/J1n//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMUFRkf/aAAgBAQABPyEtomg1HLY1CbSr8lAIZ52IHVnj2XVsucT/2gAMAwEAAgADAAAAECA//8QAFxEBAQEBAAAAAAAAAAAAAAAAAQARIf/aAAgBAwEBPxANeWN//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhEf/aAAgBAgEBPxCJU0f/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhMZFhof/aAAgBAQABPxBxhykVX45GoeKji1+Y7svFl4gpbc1ExTlPscQiaqjRK+VnIK6C2A3eT//Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;school class&quot; title=&quot;&quot; src=&quot;/static/6167a981411988d8ff05e1fe86ac3795/d7854/school_class.jpg&quot; srcset=&quot;/static/6167a981411988d8ff05e1fe86ac3795/0913d/school_class.jpg 160w,
/static/6167a981411988d8ff05e1fe86ac3795/cb69c/school_class.jpg 320w,
/static/6167a981411988d8ff05e1fe86ac3795/d7854/school_class.jpg 550w&quot; sizes=&quot;(max-width: 550px) 100vw, 550px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;심지어 동갑끼리 모인 같은 반 사람들 중에서도 진짜 친하게 지내는 친구는 보통 10명이 채 안된다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그런 이유로 인원이 가장 많았던 토스 코어 프론트엔드 챕터는 사람들을 더 작은 소그룹으로 나누고 그 안에서의 친밀도를 높혀 조직에 대한 심리적 안정감을 만들어냄과 동시에, 해당 그룹에 속한 사람들을 더 적극적으로 도와주고 성장의 방향성을 부어줄 수 있는 일종의 리드의 역할을 고민하게 되었다.&lt;/p&gt;
&lt;p&gt;토스에는 작은 목적조직인 사일로들이 모여서 형성된 트라이브라는 조직이 있는데, 원래 이 트라이브에는 개발자들을 규합하는 T-Lead라는 역할이 한 명씩 존재한다. 하지만 T-Lead는 백엔드 분들이 주로 맡으시다보니 아무래도 자신들의 전문 분야가 아닌 프론트엔드 쪽에 대해서 적극적으로 방향성을 제시해주고 이끌어주는 것을 기대하기 어려운 상황이었다.&lt;/p&gt;
&lt;p&gt;그런 이유로 지금까지의 프론트엔드 챕터는 챕터 단위로 의사결정을 내리고 액션아이템을 실천하고 있었지만, 챕터의 인원이 급격하게 늘어나며 조직의 밀도가 낮아지다보니 이제 프론트엔드 쪽에도 챕터 리드보다 더 가까이서 팀원들을 도와줄 수 있는 역할이 필요해졌던 것이다.&lt;/p&gt;
&lt;p&gt;그래서 처음에는 T-Lead를 오마쥬한 F-Lead라는 이름의 역할을 만드려고 했었지만 아무래도 Lead라는 단어가 오히려 위계를 더 강화시킬 수 있다는 걱정도 들었고, 프론트엔드 챕터가 생각하는 리드의 역할은 다른 사람들을 관리하는 사람이 아니라 팀원들을 도와주는 사람이었기 때문에, 이름에서부터 이런 느낌이 강하게 드러났으면 좋겠다는 의견이 많았다.&lt;/p&gt;
&lt;p&gt;즉, 다른 사일로를 지원해야하는 업무처럼 약간 Gray한 영역에 있는 일들이나 조직 개편같은 행정적인 일 혹은 1 on 1 커피챗을 통한 고민 상담 등을 수행하며 팀원들이 일에 더 집중할 수 있는 환경을 만들어주고, 프론트엔드 챕터의 인원들이 빠르게 성장할 수 있게 도와줌으로써 챕터 전체의 하드스킬과 소프트스킬을 상향평준화시키는 일종의 도우미같은 역할을 기대한 것이다. &lt;small&gt;(그러면서 자기 사일로 업무도 다 해내야한…읍읍)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이런저런 아이데이션을 통해 재미있는 이름들이 많이 나왔지만 최종적으로는 F-Evangelist라는 이름의 역할이 탄생하게 되었고, 챕터의 문화나 심리적 안정감에 관심이 많았던 필자도 어쩌다보니 이 역할을 맡게 되었다.&lt;/p&gt;
&lt;h3 id=&quot;내가-싼-똥-자랑하기&quot; style=&quot;position:relative;&quot;&gt;내가 싼 똥 자랑하기&lt;a href=&quot;#%EB%82%B4%EA%B0%80-%EC%8B%BC-%EB%98%A5-%EC%9E%90%EB%9E%91%ED%95%98%EA%B8%B0&quot; aria-label=&quot;내가 싼 똥 자랑하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;필자는 프론트엔드 챕터라는 조직 안에 있는 모든 사람들이 무엇이든 편하게 도전할 수 있고, 스스로 이상하다고 생각하는 것을 편하게 피드백할 수 있는 환경이 우선적으로 마련되어야 프론트엔드 챕터가 발전할 수 있다고 생각했었기 때문에, 처음 소그룹과 F-Evangelist가 등장했을 때부터 조직 내 친밀도를 높혀 사람들이 프론트엔드 챕터라는 조직 안에서 심리적 안정감을 느낄 수 있게 만드는 것에 집중해야한다는 의견을 꾸준히 밀었다.&lt;/p&gt;
&lt;p&gt;당시 필자가 생각했던 최우선 과제는 필자의 그룹에 있는 주니어 구성원들이 자신보다 연차가 많은 개발자나 F-Evangelist와 같이 특정한 역할을 맡고 있는 개발자를 어려운 사람이 아닌 그냥 한 명의 동료 개발자로 느끼도록 만드는 것이었다.&lt;/p&gt;
&lt;p&gt;아무리 위계를 만들기 싫다는 이유로 역할의 이름에서 리드라는 단어를 제거하기는 했지만, 실질적으로 하는 행동들을 보면 리드나 다름없기 때문에 이름 변경과 같은 소극적인 액션만으로 다른 사람들이 이 역할에 대해 느끼는 거리감이나 위계감이 완전히 제거되는 것을 바라는 것은 무리라고 생각했다.&lt;/p&gt;
&lt;p&gt;게다가 토스 프론트엔드 챕터에는 여러가지 활동을 통해 네임 밸류가 쌓여있는 개발자들도 여럿 있었고, 주니어 분들은 네임 밸류가 높으면 막연하게 실력도 좋을 것이라고 생각하는 경향이 있었다. 필자는 안 그래도 하드 스킬에 대한 편차로 인해 위계가 발생하는 상황에서 이런 네임 밸류에 대한 오해까지 덧붙혀지면 조직 내 심리적 안정감을 만드는데 큰 방해가 될 것이라고 판단했기 때문에 이런 생각을 완전히 제거하고 싶었다. &lt;small&gt;(유명한 것과 개발 잘 하는 것은 크게 상관관계가 없다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그래서 필자가 가장 처음 했던 것은 바로 “똥 자랑 대회”였다.&lt;/p&gt;
&lt;p&gt;일반적으로 개발자들은 아름다운 설계를 지향하지만 회사에서 개발을 하다보면 비즈니스 상황과 같은 외부 요인으로 인해 설계를 뭉개고 가는 경우도 있으며 바쁜 일정으로 인해 서두르다 버그를 내는 경우도 흔하다.&lt;/p&gt;
&lt;p&gt;이런 상황에서 제대로 설계하지 않은 코드를 짜는 행위나 실수를 “똥을 쌌다”라고 표현하고는 하는데, 필자는 바로 이런 코드들을 서로 공유해보자고 제안했던 것이다. 물론 다소 캐쥬얼하기도 하고 더러운 이름이기는 하지만, 필자는 모두가 웃고 즐기며 실수를 편하게 공개할 수 있는 자리를 원했기 때문에 일부러 “부채 공유하기”나 “회고”와 같은 딱딱한 이름이 아닌 재미있는 이름을 선정했다.&lt;/p&gt;
&lt;p&gt;필자의 그룹에는 토스가 완전 첫 직장인 신입 개발자부터 연차가 6-7년 정도 되는 개발자까지 다양한 세그먼트들이 분포해있었는데, 똥 자랑 대회를 진행함으로써 연차와 상관없이 개발자라면 누구나 다 실수를 할 수 있고 설계를 뭉개는 상황도 발생한다는 것을 알림과 동시에, 경험이 많은 개발자들이 이런 똥을 어떻게 치워나가는지, 그리고 어떤 사고 과정을 통해 설계를 뭉개서라도 속도를 챙기겠다는 의사결정까지 다다르는지와 같은 경험을 공유하는 것을 의도했다.&lt;/p&gt;
&lt;p&gt;그러나 필자는 여기서도 한 가지 실수를 했는데, 하드스킬 수준에 따라서 스스로 똥이라고 생각하는 코드가 달랐던 것이다. 물론 상대적으로 해결 난이도가 낮은 똥에 대해서는 활발한 토론이 이루어졌고 문제 해결 방식도 제안되었지만, 하드스킬이 부족하다면 이해하는 것 자체가 어려운 똥에 대해서는 하드스킬 수준에 따라 참여도가 극명하게 갈렸다.&lt;/p&gt;
&lt;p&gt;이 문제는 이미 이전에 진행했던 스터디나 오프라인 코드리뷰 등에서 발생했던 문제였지만, 처음 F-Evangelist를 맡았을 때의 필자는 얼른 심리적 위계를 제거하고 싶다는 마음만 앞서서 지난 실패에서 얻었던 경험을 잊어버리고 만 것이다.&lt;/p&gt;
&lt;p&gt;사실 똥 자랑 대회에 대한 사람들의 후기는 나쁘지 않았지만, 필자가 원래 의도했던 심리적 위계를 제거하는 행위까지는 다다르지 못 한채로 첫 번째 액션아이템을 마무리하게 되었다.&lt;/p&gt;
&lt;h3 id=&quot;강점찾기&quot; style=&quot;position:relative;&quot;&gt;강점찾기&lt;a href=&quot;#%EA%B0%95%EC%A0%90%EC%B0%BE%EA%B8%B0&quot; aria-label=&quot;강점찾기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이후 필자는 접근 방향을 바꿔서 기술적인 것 외적인 이야기를 서로 많이 나누어서, 개발자가 아닌 사람 대 사람으로써 친해질 수 있는 정보를 쌓아보자는 방식을 밀어보게되었다.&lt;/p&gt;
&lt;p&gt;그래서 주말에 할 거 없는 사람들끼리 모여서 이쁜 카페에 가서 맛있는 것도 먹고 개인 작업도 하는 모각코 자리를 마련하거나 소그룹 위클리 미팅 시간을 잡담 타임으로 활용하는 등 여러가지 액션아이템을 계속 반복해서 수행하고 사람들의 반응을 관찰했다. 이렇게 몇 번의 액션아이템을 반복하다보니, 그룹 내에는 확실히 이전에 비해 친밀도가 형성되었고 이에 대한 조직 내 심리적 안정감도 형성되었다.&lt;/p&gt;
&lt;p&gt;하지만 아직 필자가 해결하지 못 했던 이슈는 주니어 개발자 분들이 가지고 있는 “나는 아직 부족해”라는 부담감이었다. 물론 이러한 부담감이 건강하게 작용한다면 성장에 대한 훌륭한 동기 부여가 될 수 있었지만, 이런 생각이 너무 과해진다면 오히려 자신감이나 자존감 하락으로 이어져서 독이 될 수도 있다.&lt;/p&gt;
&lt;p&gt;그러던 와중 필자는 같은 사일로의 디자이너 분이 어떤 스프레드시트를 보고 있는 것을 발견했는데, 그 시트는 바로 디자인 챕터에서 진행했었던 “강점찾기”라는 테스트의 결과지였다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/05f8e90b592bc1d348a7a51cb03b0c1e/9568a/book.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 133.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAH/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAdLrFNIxLj7KzNTo1//EAB0QAAICAgMBAAAAAAAAAAAAAAECAAMRMRASEyH/2gAIAQEAAQUCHGJVpbyzHaWYHtA3cBRAiwfJ/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BiM//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAeEAACAgAHAAAAAAAAAAAAAAAAERAxAQISIUFxgf/aAAgBAQAGPwKcM3gtKey5jooZRUf/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhMUFRkWH/2gAIAQEAAT8h0ThmYS8GlEVFvAveZSaG8StT0Suzf01GXgceR0IiSJRH/9oADAMBAAIAAwAAABAAJP7/xAAYEQADAQEAAAAAAAAAAAAAAAAAASEQEf/aAAgBAwEBPxC50xiUp//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EIM//8QAHhABAAMAAgIDAAAAAAAAAAAAAQARITFBUWFxoeH/2gAIAQEAAT8Qd0CI3Y+/c1zY+Xj5hGBkvA3YDjr1ARBqBrzPsRGNsjgu+yNlX2DRMSj2N1LMSvNz8LBIg6J//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;book&quot; title=&quot;&quot; src=&quot;/static/05f8e90b592bc1d348a7a51cb03b0c1e/c08c5/book.jpg&quot; srcset=&quot;/static/05f8e90b592bc1d348a7a51cb03b0c1e/0913d/book.jpg 160w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/cb69c/book.jpg 320w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/c08c5/book.jpg 640w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/6a068/book.jpg 960w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/eea4a/book.jpg 1280w,
/static/05f8e90b592bc1d348a7a51cb03b0c1e/9568a/book.jpg 3024w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이 책을 사면 인터넷에서 강점찾기 테스트를 할 수 있는 코드를 준다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;필자는 이런 종류의 테스트는 전혀 믿지 않는 편이라 처음에는 그냥 “디자인 챕터에서 또 재밌는 거 했네” 정도로 생각하고 넘어가려고 했으나, 이내 곧 이 테스트가 사람들의 부담감을 덜어줄 수 있는 좋은 메소드가 될 수도 있겠다는 생각이 들었다. &lt;small&gt;(디자인 챕터가 은근히 이런 재밌는 걸 많이 한다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;성장에는 크게 두 가지 방법이 있는데, 한 가지는 내가 못하는 것을 더 잘하게 만드는 것이고, 다른 한 가지는 내가 이미 잘 하고 있는 부분을 더 잘하게 만드는 방법이다. 하지만 일반적으로 한창 성장하는 시기의 개발자들은 자신이 이미 잘 하고 있는 것보다 자신이 못 하는 것에만 집중하고 그 부분을 채우려고 하는 성향이 크다.&lt;/p&gt;
&lt;p&gt;비록 자신이 못 하는 것에 집중하고 보완하는 것이 좋은 성장의 방법이기는 하지만, 자칫 “난 이걸 못해”라는 부정적인 생각에 너무 빠지다보면 스스로를 너무 몰아세워 건강을 해치면서까지 공부나 일을 한다거나, 주변의 개발자들과 자신을 비교하며 좌절하는 상황도 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 강점찾기라는 테스트를 통해서 사람들이 스스로 “자신이 잘 하는 것이 무엇인지”를 알 수 있도록 메타인지를 심어주면, 자신의 약점에만 집중하는 것이 아닌 강점과 약점을 모두 알게 되면서 스스로에 대한 자신감도 생기지 않을까하는 생각을 했던 것이다.&lt;/p&gt;
&lt;p&gt;이후 이 생각에 대해 다른 프론트엔드 개발자 분들에게 이야기를 했는데, 이에 공감해주시는 두 분이 조인하여 우리끼리 강점찾기를 한번 직접 진행해보기로 했다. 이때 디자인 플랫폼팀 소속인 프론트엔드 개발자 분은 이미 디자인 챕터와 함께 강점찾기를 진행해보신 경험이 있었기 때문에, 당시의 경험을 살려 프론트엔드 챕터에 맞는 방식을 찾아나가는 과정에 큰 도움을 주셨다.&lt;/p&gt;
&lt;p&gt;강점찾기 프로그램을 진행하는 방법은 굉장히 심플했는데, 그냥 회사에 요청을 해서 책을 구매한 뒤 각자 테스트를 진행하고 PDF로 나온 테스트 결과지를 다시 강점찾기 슬랙 채널에 공유하면, 이후 오프라인으로 모여서 진행자가 각자의 결과지를 해설해주는 것이다.&lt;/p&gt;
&lt;p&gt;이때 진행자는 팀원들의 강점 결과를 단순히 읽어주기보다는 강점찾기에 참여한 팀원들이 서로의 강점에 대해서 공감하고 기억할 수 있는 환경을 만들어주는 역할을 하는데, 진행자의 액션아이템은 대략 이런 느낌이었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;결과지를 단순히 읽어주는 것이 아니라, 실제로 토스팀에서 경험해볼 수 있는 상황들을 예를 들어주는 것이 좋다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;팀원들의 강점을 한 줄로 요약 정리해서 다른 사람들이 기억하기 쉽도록 만들어주자.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;내 강점 중 다른 사람들이 더 관심을 가져줬으면 하는 부분에 하이라이팅을 하도록 시키자.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;서로의 강점을 더욱 더 강화시킬 수 있는 액션아이템을 정해주도록 시키자.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;강점찾기의 목적에는 스스로 무엇을 잘 하는지에 대한 메타인지를 키우도록 하는 것도 있었지만, 하나의 팀으로 일을 한다는 것이 얼마나 다양한 강점을 가진 사람들이 모여 시너지를 만드는 과정인지 알려주는 것도 있었기 때문에, 단순히 스스로 강점을 알고 끝나는 것이 아니라 적극적으로 서로의 강점을 인지하고 더 강화시키기 위한 활동도 추가적으로 진행했다.&lt;/p&gt;
&lt;p&gt;이렇게 강점찾기에 대한 PoC를 진행해보니 생각보다 각자의 강점에 대해서 상세하게 설명해주기도 하고 재미도 있어서, 곧 필자가 리딩하고 있는 소그룹에서도 강점찾기를 진행해보았다.&lt;/p&gt;
&lt;p&gt;그 당시 필자는 팀원들이 이 프로그램을 업무의 일환이라고 느끼게 만들고 싶지 않았기도 했고, 어차피 개발과 조금 동떨어진 느낌의 프로그램을 진행하는 김에 아예 하루 일탈하는 기분도 내기를 바라서 사무실이 아닌 충무로에 있는 이쁜 카페에 모여서 강점찾기 프로그램을 진행했다.&lt;/p&gt;
&lt;p&gt;결과는 생각보다 좋았다. 솔직히 이런 테스트에는 어떠한 과학적 근거도 없으니 사람들이 믿지 않을 수도 있기 때문에 큰 기대는 하지 않았지만, 생각보다 다들 자신의 강점을 알아보며 기뻐해주셨고, 좋은 개발자라는 것이 한 가지 모습이 아니라 여러 가지 모습이라는 것, 프론트엔드 챕터는 다양한 강점을 가진 사람들이 모여서 시너지를 만들어내야하는 팀이라는 것들에 크게 공감해주셨다.&lt;/p&gt;
&lt;p&gt;물론 필자는 커피챗 등을 통해 팀원들에게 이런 이야기들을 많이 해줬었지만, 백 마디 말보다 이런 프로그램이나 캠페인을 한 번 진행하는 것이 더 효과가 좋다는 점에 큰 감명을 받았다.&lt;/p&gt;
&lt;p&gt;이후 소그룹에서 좋은 결과를 얻었던 필자는 F-Evangelist 미팅에서 강점찾기의 목적과 방법을 설명하며 전도하기 시작했다. 원래 목적은 토스 코어에서 우선 테스트해보고 반응이 좋으면 다른 계열사로 수출하는 그림을 그렸었는데, 강점찾기 채널을 눈팅하고 있던 다른 계열사 프론트엔드 개발자 분들이 강점찾기를 알아서 퍼나르기 시작하면서 갑자기 강점찾기를 수출당해버렸다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ffc77284035d39b5b0c853dc1b66ecff/c549b/strong.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 57.50000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABfUlEQVR42m2TabKCQAyEvYQgbshDERUXcEFE3Ervf6Q8vlhjgfija5IZppNODy3HccS2bfnzfYnjRGazmSwWC0W/39ezTqfTAPuA+1W0ut2uWJZdEoRyvRaSJImkaSr7/V78sojruuJ5noxGo09swF6v16sTvjt0JPAdydJYTqe8xElxu93k8XjI8/mU+/2uOXFRFKWaWDabjQwGA+24RsiG63pll5HM53MFklm5QBfINyA3JChsSG63LVkul/J6vSTPc8myTNfz+SxhGMp4PJbpdCpBECjITdyQ/J6hpWZAALHpkHi1Wmk8mUx0n+8owkoROq5JhhC3ODwejwpMAXS62+2UFMJql4C8Kr9iiq0XDoeDurxer5WETrjAHA3IcXc4HKrTjRmagNa3262S4jCxkVY1KYoiJYPom6xGyCEyIeQNQopkcLlcPk+JM1QwCor+fDaG0HxoZofTkDACY4gxgxkS/5yhAQ8VUyBjpYD5DZGK6/w9jAfZ4FvyP1eLWNLuMUijAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;strong&quot; title=&quot;&quot; src=&quot;/static/ffc77284035d39b5b0c853dc1b66ecff/6af66/strong.png&quot; srcset=&quot;/static/ffc77284035d39b5b0c853dc1b66ecff/69538/strong.png 160w,
/static/ffc77284035d39b5b0c853dc1b66ecff/72799/strong.png 320w,
/static/ffc77284035d39b5b0c853dc1b66ecff/6af66/strong.png 640w,
/static/ffc77284035d39b5b0c853dc1b66ecff/d9199/strong.png 960w,
/static/ffc77284035d39b5b0c853dc1b66ecff/21b4d/strong.png 1280w,
/static/ffc77284035d39b5b0c853dc1b66ecff/c549b/strong.png 2128w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;원활한 수출을 위해 강점찾기 진행자를 위한 가이드라인도 작성했었다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;아쉽게 필자는 이때쯤 퇴사를 했기 때문에 이후 강점찾기가 어떻게 진행되었는지 자세히는 알지 못 하지만, 퇴사 후 건너건너 듣기로는 다른 프론트엔드 개발자 분들도 재밌어했다는 후기도 들었고, 심지어는 DS(Data Scientist)팀에서도 강점찾기를 진행했다는 얘기도 들었다. &lt;small&gt;(수출 속도가 어마무시하다…)&lt;/small&gt;&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;토스에서 일했던 지난 2년 반은 필자에게 있어서 많은 성장의 밑거름을 만들어 낼 수 있었던 시간이었다. 물론 토스는 일이 많고 빡세긴 하지만 그 만큼 일과 성장에 대한 몰입도가 높은 조직이었다는 생각이 든다.&lt;/p&gt;
&lt;p&gt;능력있는 동료들과 서로 신뢰하면서 일을 한다는 것이 어떤 기분인지, 아침에 제품 아이데이션을 하고 저녁에 배포하는 미친 속도감이 무엇인지, 그리고 이런 생산성을 만들어 낼 수 있는 원동력이 무엇인지 등 많은 경험과 고민들을 할 수 있었다.&lt;/p&gt;
&lt;p&gt;마지막 퇴사자 면담에서 POM(People Operation Manager)이 필자에게 “동욱님이 토스에 다시 돌아오게 하려면, 토스팀은 어떤 점을 보완해야할까요?”라는 질문을 했었는데, 그때 필자는 “내가 다시 돌아온다면, 아마 토스에 있는 것들이 다른 곳에는 없다는 것을 느낄때일 것 같다”라고 답변했었다. 그만큼 필자는 이 조직에 대한 만족도가 높았던 것 같다. &lt;small&gt;(지나고 나서 보니 뭔가 멋진 대사인듯…?)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이제 토스는 필자가 입사했을 당시의 300명짜리 스타트업이 아니라 2,000명 규모의 머기업이 되어버렸다. 그러니 당연히 그 시절의 토스와는 달라진 부분들이 있고, 필자는 그 부분에서 묘한 향수감과 아쉬움을 느끼고 있기는 하다. 예전에는 챕터든 사일로든 진짜 친한 친구들이랑 으쌰으쌰 일 하는 느낌이었다면, 최근에는 조금 더 회사원 같아진 느낌이랄까.&lt;/p&gt;
&lt;p&gt;하지만 이제 토스는 예전의 모습으로 돌아갈 수는 없을 것이다. 300명짜리 문화와 2,000명짜리 문화는 당연히 다를 수 밖에 없기 때문이다.&lt;/p&gt;
&lt;p&gt;그래서 필자는 이번에 작은 스타트업으로 이직을 하면서, 업무에 몰입하여 미친 생산성을 만들어내는, 예전에 필자가 사랑했던 그 문화를 직접 만들어내어 제품을 성공의 길로 이끌어내는 경험을 해보고 싶었다.&lt;/p&gt;
&lt;p&gt;필자가 이직한 쿼타랩이라는 스타트업에서도 역시 &lt;a href=&quot;https://quotalab.career.greetinghr.com/o/61278&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;프론트엔드 개발자를 절찬리 채용 중&lt;/a&gt;이니, 이 글을 읽는 독자분들 중에서도 혹시 이런 미친 생산성을 만들어내는 문화를 조직에 도입하고 그 문화를 기반으로 제품을 성공시키는 경험을 해보고 싶으신 분들이 있다면 지원해주셨으면 한다. &lt;small&gt;(IT는 진짜 인재밀도랑 문화가 다 해먹는다)&lt;/small&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Everything developers need to know about stock options]]></title><description><![CDATA[This post is going to be a bit different from my usual content - instead of talking about philosophy or technical topics, I want to talk about something that pretty much everyone working in tech has heard about at least once: stock options.]]></description><link>https://evan-moon.github.io/2021/12/04/what-is-stock-options/en/</link><guid isPermaLink="false">20211204-what-is-stock-options-en</guid><pubDate>Sat, 04 Dec 2021 02:31:02 GMT</pubDate><content:encoded>&lt;p&gt;This post is going to be a bit different from my usual content - instead of talking about philosophy or technical topics, I want to talk about something that pretty much everyone working in tech has heard about at least once: &lt;strong&gt;stock options&lt;/strong&gt;.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;With the ongoing developer hiring crunch, more and more companies are offering signing bonuses or stock options as part of their compensation packages. But the thing is, a lot of people don’t really understand what stock options are, how they can actually make you money, or how much you’ll owe in taxes - they just accept them without thinking too hard about it.&lt;/p&gt;
&lt;p&gt;I’ve even heard people say things like “I got 100 shares worth 100 million won when my company was valued at 100 billion, and now it’s at 500 billion, so my money must have 5x’d too!” But stock options don’t work that simply. You have to pay taxes on your gains, and the actual profit you pocket will be lower than you think. Plus, some people get caught off guard when they don’t have the cash on hand to pay the strike price or taxes.&lt;/p&gt;
&lt;p&gt;Signing bonuses are easy to understand - the company gives you a lump sum of cash with your first paycheck after joining. It’s just regular incentive money. But stock options are financial derivatives, so if you don’t have any background in finance, they can be pretty confusing.&lt;/p&gt;
&lt;p&gt;Sure, you could just think of them as regular stock and probably be fine in most cases. But stock options are not the same as stock, and if you don’t understand the difference, it could mess with your personal cash flow planning.&lt;/p&gt;
&lt;h2 id=&quot;5k-raise-or-50k-in-stock-options&quot; style=&quot;position:relative;&quot;&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;5K raise or &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;Kr&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;seor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;50K in stock options?&lt;a href=&quot;#5k-raise-or-50k-in-stock-options&quot; aria-label=&quot;5k raise or 50k in stock options permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, let’s talk about what stock options actually are. As a developer, you’ve probably gotten offers like this at some point:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;5K salary increase vs. same salary + &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Ks&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;ry&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cre&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;am&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;ry&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;50K worth of stock options&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;50&lt;/mn&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;50K signing bonus vs. &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Ks&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nin&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;100K worth of stock options (or RSUs)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you’ve been around the block a few times, you can probably make a good call based on your situation. But if it’s your first time seeing an offer like this, it can be pretty overwhelming. If you don’t know much about stock options, you might think:&lt;/p&gt;
&lt;center&gt;
  &lt;img src=&quot;/61beca707059c9a6222de21b1eda6779/good.gif&quot; width=&quot;100%&quot;&gt;
  &lt;br&gt;
  &lt;small&gt;They&apos;re giving me $50K worth of stock instead of a $5K raise? That&apos;s amazing!&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;You hear stories about people making millions from stock options, buying houses, and so on. And let’s be real - a &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;5K raise doesn&apos;t increase your take-home pay by that much after taxes anyway. So an offer of &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9463em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;Kr&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oes&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cre&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;seyo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03148em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;ff&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ero&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;50K worth of company stock sounds pretty good, right?&lt;/p&gt;
&lt;p&gt;But here’s the key thing: &lt;strong&gt;stock options are not stock&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Wait, what? Stock options aren’t stock? But companies talk about them like they are - “100 shares of stock options granted” and all that.&lt;/p&gt;
&lt;p&gt;To understand the real difference between stock and stock options, we need to understand what this &lt;strong&gt;option&lt;/strong&gt; thing actually is as a financial instrument.&lt;/p&gt;
&lt;h2 id=&quot;options-financial-instruments-with-time-value&quot; style=&quot;position:relative;&quot;&gt;Options: financial instruments with time value&lt;a href=&quot;#options-financial-instruments-with-time-value&quot; aria-label=&quot;options financial instruments with time value permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An option is &lt;strong&gt;a contract that gives you the right to buy or sell an underlying asset at a specific price at a future point in time&lt;/strong&gt;. In simple terms, it’s a derivative product where you’re betting on how the price will change in the future.&lt;/p&gt;
&lt;p&gt;If you haven’t been into investing much, that might sound confusing, so let’s break it down step by step.&lt;/p&gt;
&lt;p&gt;First, an &lt;strong&gt;underlying asset&lt;/strong&gt; is something like stock, bonds, dollars, gold, or Bitcoin - assets that have economic value on their own. Derivatives like options, futures, and swaps were created to meet market needs like making it easier to trade these assets or hedging against price volatility.&lt;/p&gt;
&lt;p&gt;For stock options, the underlying asset is stock - pretty straightforward.&lt;/p&gt;
&lt;p&gt;The phrase &lt;strong&gt;“the right to buy or sell at a specific price at a future point in time”&lt;/strong&gt; means exactly what it sounds like - you can buy or sell the underlying asset at a predetermined price in the future. Let me give you an example using corn as the underlying asset:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;December 4 (current corn price: $0.50 per ear)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Me: I want to buy corn for $0.60 per ear on January 4, one month from now.&lt;/p&gt;
&lt;p&gt;Merchant: Sure. I’ll sell you the right to buy corn for &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0.60&lt;/mn&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0.60 one month from now, no matter what the price is then. That right costs &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0.60&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ro&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mn&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;tt&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;tt&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ce&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;0.10. You can decide whether to actually buy it when the time comes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;January 4 (current corn price: $1.00 per ear)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Me: Oh wow, corn went up a lot! Now I’ll exercise my option (the right to buy) and purchase corn for $0.60 per ear!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This example shows a call option - buying and selling the right to purchase something. Since I can exercise my call option and buy corn for $0.60 no matter what the current price is, the more the corn price goes up over that month, the bigger my profit.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ff68626a0dad3dd5b48e34a969701d5d/9cac8/call-option.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 33.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABJ0lEQVR42mNgwATCQMzEQAT4z8DA+P//f0Z8ajiAmA+IGYk15H99PdOxwkJOkNh/BkzDxYFYkqAhQPbz4mLu19nZUq+ys9XO5DYrE3IlE1ZD09K4XqWlSb7MSlb5kJmo9DQtTeR/KAPzwop1wktqtuqubdkOdowAEPOC6DTjNFZ1dSteYyANdAbjqlWrmE/k1vPdLiqSvZ+ZqXk3JVvtflaJxCqgFxkY6pkY6v8zhYauYp6cvVB4Zv0mrpkzz7CCDFQAYhkgVpyYO5Hd3z5e4FBupeiz4mr5RxnFOvfyS9VvFlZJ78+q50lLO8NaX3+FbWLuNvZtEyF4fv1+jt7CVZy4vCuSrKWlcig0VGuWh4eMvagoD1CMGYhZgJgdGhwcWNggzA8yAQBQZWpop7Fk2AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;call option&quot; title=&quot;&quot; src=&quot;/static/ff68626a0dad3dd5b48e34a969701d5d/6af66/call-option.png&quot; srcset=&quot;/static/ff68626a0dad3dd5b48e34a969701d5d/69538/call-option.png 160w,
/static/ff68626a0dad3dd5b48e34a969701d5d/72799/call-option.png 320w,
/static/ff68626a0dad3dd5b48e34a969701d5d/6af66/call-option.png 640w,
/static/ff68626a0dad3dd5b48e34a969701d5d/d9199/call-option.png 960w,
/static/ff68626a0dad3dd5b48e34a969701d5d/21b4d/call-option.png 1280w,
/static/ff68626a0dad3dd5b48e34a969701d5d/9cac8/call-option.png 2288w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    No matter how much corn prices rise, I can exercise my call option&lt;br&gt;
    and buy at $0.60, so higher corn prices mean more profit for me
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;If there’s a right to buy, there’s also a right to sell, and that’s called a put option.&lt;/p&gt;
&lt;p&gt;If the option I bought from the merchant was a put option instead of a call option - meaning the right to sell corn for &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0.60&lt;/mn&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0.60 - then even if the current corn price drops to &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0.60&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ni&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;rre&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;cor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ce&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ro&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;0.10, I can still sell at $0.60. So with put options, the more the price drops over that month, the bigger my profit. &lt;small&gt;(That’s why call options are bullish bets and put options are bearish bets)&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/65f5c9330f73b05984b596d7b5354bbe/9cac8/put-option.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 33.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABFUlEQVR42mNgQAWMQCzEEBrK/P//f0YGKgA2GQs3IY/ciezIgmDDybRASNsqQDl34hEwzp58Urhw1TFOUl3LBcQgF3H+r//PJCMjw1kY2suZVb+Kp6jnoGxRz261/P696jndBxUzp20RrK/fz/EfGDT/Gf6D8f79+1lWrVrFjGygChDLArHyRKBXvb2jBGNiirnPzDzDOjNtJitIrL5+MV9l6zZRsOGde9XzuvbolXdskquv3yTSW9jLubBinfBSIHsK0BHorhUAYlF83gF5f9X//8y5Ew+JFs85Kp8+/bxCS8tOg+X1u9UW1e8UQ49hNiDmA2JuUBBAMRcES3JJSkpyQcU4gJgViJlVzDz4rKz8eKF6GAA3A2GQZ1XiaQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;put option&quot; title=&quot;&quot; src=&quot;/static/65f5c9330f73b05984b596d7b5354bbe/6af66/put-option.png&quot; srcset=&quot;/static/65f5c9330f73b05984b596d7b5354bbe/69538/put-option.png 160w,
/static/65f5c9330f73b05984b596d7b5354bbe/72799/put-option.png 320w,
/static/65f5c9330f73b05984b596d7b5354bbe/6af66/put-option.png 640w,
/static/65f5c9330f73b05984b596d7b5354bbe/d9199/put-option.png 960w,
/static/65f5c9330f73b05984b596d7b5354bbe/21b4d/put-option.png 1280w,
/static/65f5c9330f73b05984b596d7b5354bbe/9cac8/put-option.png 2288w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    No matter how much corn prices fall, I can exercise my put option&lt;br&gt;
    and sell at $0.30, so falling corn prices mean more profit for me
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Basically, options let you bet on whether the underlying asset’s price will go up or down by locking in a future price in advance.&lt;/p&gt;
&lt;p&gt;Now, what if I’m holding a call option to buy corn at &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0.60&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0.60, but a month later corn is still &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0.60&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;am&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;ercor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ni&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ss&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;ll&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;0.50 or even lower? What should I do? There’s no profit in exercising the option, right?&lt;/p&gt;
&lt;p&gt;Simple - you just don’t exercise your right to buy or sell. That’s why they’re called options - you have the option to exercise them or let them expire. If you don’t exercise an option, you only lose what you paid for the option itself.&lt;/p&gt;
&lt;h3 id=&quot;options-in-everyday-life-apartment-pre-sale-rights&quot; style=&quot;position:relative;&quot;&gt;Options in everyday life: apartment pre-sale rights&lt;a href=&quot;#options-in-everyday-life-apartment-pre-sale-rights&quot; aria-label=&quot;options in everyday life apartment pre sale rights permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A classic real-world example of options is apartment pre-sale rights in Korea. When you win an apartment lottery, you get the right to buy an apartment at the pre-sale price, which is usually much cheaper than market value.&lt;/p&gt;
&lt;p&gt;But having the right to buy an apartment for 300 million won means you need to actually have 300 million won in cash to use that right. If you can’t come up with the money or don’t want the apartment, people often sell these pre-sale rights to others.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 604px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7b2452ff1dcab002720732bbd4d3b4f3/efa6e/option.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 136.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHskUaCBXlRYg//xAAaEAABBQEAAAAAAAAAAAAAAAAAAQIQETFB/9oACAEBAAEFArnHCF3Kbw//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAXEAEAAwAAAAAAAAAAAAAAAAAQASAx/9oACAEBAAY/ArYy/wD/xAAaEAADAQEBAQAAAAAAAAAAAAAAAREhUWEQ/9oACAEBAAE/IVSbdxie+lfR6Qje6JgqRCwopdefP//aAAwDAQACAAMAAAAQIwkA/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHRABAAICAwEBAAAAAAAAAAAAAQARMVEhQYGx4f/aAAgBAQABPxBUqEsmIB2IfohGXPYJEh1bEPUNQFbJe2OC2iO8IYzz9lt+0AM//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;option&quot; title=&quot;&quot; src=&quot;/static/7b2452ff1dcab002720732bbd4d3b4f3/efa6e/option.jpg&quot; srcset=&quot;/static/7b2452ff1dcab002720732bbd4d3b4f3/0913d/option.jpg 160w,
/static/7b2452ff1dcab002720732bbd4d3b4f3/cb69c/option.jpg 320w,
/static/7b2452ff1dcab002720732bbd4d3b4f3/efa6e/option.jpg 604w&quot; sizes=&quot;(max-width: 604px) 100vw, 604px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Trading pre-sale rights isn&apos;t trading the apartment itself - it&apos;s trading the right to buy the apartment&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;In other words, an apartment pre-sale right is a contract containing “the right to buy an apartment for 300 million won by a certain date,” so people trading these rights are buying and selling “the right to buy an apartment,” not the apartment itself. That’s an option.&lt;/p&gt;
&lt;h3 id=&quot;aside-whats-the-difference-between-options-and-futures&quot; style=&quot;position:relative;&quot;&gt;Aside: what’s the difference between options and futures?&lt;a href=&quot;#aside-whats-the-difference-between-options-and-futures&quot; aria-label=&quot;aside whats the difference between options and futures permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A quick aside since many people confuse futures and options. They’re confusing because both involve making trades now based on predictions about future asset prices. But futures are the broader concept, and options are a type of futures contract.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Futures contracts are about pulling a future transaction into the present&lt;/strong&gt;. So a corn futures contract would be like “one month from now, I’m going to trade corn for $0.60 - stamp stamp” in the contract. When the futures contract expires, the settlement goes through and the transaction is executed.&lt;/p&gt;
&lt;p&gt;Since you’re literally contracting now for a future transaction, futures contracts don’t give you the choice to exercise or not exercise like options do.&lt;/p&gt;
&lt;p&gt;Just like with options, if corn prices go up to &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1.00&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1.00, the person who bought corn futures gets a &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1.00&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;erso&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;ug&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;cor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;0.40 profit. If corn prices drop to &lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0.30&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0.30, the person who sold corn futures for &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0.30&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;erso&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02691em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oso&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;cor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;or&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;0.60 gets a $0.30 profit. &lt;small&gt;(Futures trading is a zero-sum game - one person always wins and one person always loses)&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5ae794732187196080a4074fd043ebe6/41099/future.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 63.74999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABw7mRFiQv/8QAGhAAAwEAAwAAAAAAAAAAAAAAAAECEQMSIf/aAAgBAQABBQJLSpfUmsXJ4M//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAwADAAAAAAAAAAAAAAAAAAEQESFx/9oACAEBAAY/AjcSwdn/xAAbEAADAAIDAAAAAAAAAAAAAAAAAREhMVFhcf/aAAgBAQABPyFzQQfgXC8JqkTNU7Gx/9oADAMBAAIAAwAAABDT3//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxAEO3//xAAWEQEBAQAAAAAAAAAAAAAAAAABEQD/2gAIAQIBAT8Qjck3/8QAHBABAQACAgMAAAAAAAAAAAAAAREAITFBYYGR/9oACAEBAAE/EDQvMWWYmABho3h8TF3hWiXXeQJSvXxkNAGuDP/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;future&quot; title=&quot;&quot; src=&quot;/static/5ae794732187196080a4074fd043ebe6/41099/future.jpg&quot; srcset=&quot;/static/5ae794732187196080a4074fd043ebe6/0913d/future.jpg 160w,
/static/5ae794732187196080a4074fd043ebe6/cb69c/future.jpg 320w,
/static/5ae794732187196080a4074fd043ebe6/41099/future.jpg 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;This is the futures contract that Squid Game&apos;s Cho Sang-woo lost 6 billion won on&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;But most people trading futures don’t actually want to own the underlying asset - they just want to profit from price changes. So before the contract expires and they actually have to take delivery, they sell their futures contract to someone who actually wants to buy the asset cheap, then roll over into next month’s futures contract.&lt;/p&gt;
&lt;h4 id=&quot;memories-of-negative-oil-prices-in-march-2020&quot; style=&quot;position:relative;&quot;&gt;Memories of negative oil prices in March 2020&lt;a href=&quot;#memories-of-negative-oil-prices-in-march-2020&quot; aria-label=&quot;memories of negative oil prices in march 2020 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;So what happens if the futures contract is about to expire but there’s nobody who wants to buy the underlying asset cheap, so you can’t roll over your contract?&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3e32591136ab104e94bd94d2dee99f11/72e01/container_ship.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 73.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMFAf/EABUBAQEAAAAAAAAAAAAAAAAAAAID/9oADAMBAAIQAxAAAAF2T1o0SaOf/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECEhMh/9oACAEBAAEFAnaNGx0dBV5//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAS/9oACAEDAQE/ATLP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAh/9oACAECAQE/AaF//8QAGBAAAgMAAAAAAAAAAAAAAAAAARAgITL/2gAIAQEABj8CqGiv/8QAGxABAAEFAQAAAAAAAAAAAAAAAQAQESFhgTH/2gAIAQEAAT8hurBxuPRR1jZkF2DML2f/2gAMAwEAAgADAAAAEI/f/8QAFxEBAAMAAAAAAAAAAAAAAAAAAQARIf/aAAgBAwEBPxCjuMWmf//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAgEBPxBYMv/EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQXFRobH/2gAIAQEAAT8QRQkW3ZeiMFnYRHmLi8DhjpBtfRx7itDpt5n/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;container ship&quot; title=&quot;&quot; src=&quot;/static/3e32591136ab104e94bd94d2dee99f11/c08c5/container_ship.jpg&quot; srcset=&quot;/static/3e32591136ab104e94bd94d2dee99f11/0913d/container_ship.jpg 160w,
/static/3e32591136ab104e94bd94d2dee99f11/cb69c/container_ship.jpg 320w,
/static/3e32591136ab104e94bd94d2dee99f11/c08c5/container_ship.jpg 640w,
/static/3e32591136ab104e94bd94d2dee99f11/6a068/container_ship.jpg 960w,
/static/3e32591136ab104e94bd94d2dee99f11/72e01/container_ship.jpg 1024w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Hi Evan, delivery of the 100,000 barrels of crude oil you contracted for last month - honk honk~&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;When a futures contract expires, ownership of the underlying asset actually transfers to you. If it’s stock that’s not a huge deal, but if it’s a physical commodity like crude oil or corn, the moment it expires you have an absolute disaster on your hands - &lt;strong&gt;this stuff actually gets shipped to some unknown port in America with your name on it&lt;/strong&gt;. &lt;small&gt;(This is why messing with futures without understanding them can really screw you)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The reason crude oil futures prices dropped to -$37 in March 2020 when COVID first hit was because of this characteristic of futures contracts. By the way, a negative price means you have to pay someone extra to take your futures contract off your hands. Around that time, the WHO declared a pandemic, and the market sentiment was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh crap, a pandemic? Consumer spending will drop 👉 Production will drop too 👉 Wait…so we won’t need much crude oil to make and ship stuff for a while…?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/15ec7/mang.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 121.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAYABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAMEBQH/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAG7Ja4Yq8NGMMkH/8QAHBAAAgICAwAAAAAAAAAAAAAAAQMAEgIQESEz/9oACAEBAAEFAlKsGIFZiKY9ThWhGen/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAbEAABBQEBAAAAAAAAAAAAAAAAAhAREiExcf/aAAgBAQAGPwKVcJS1TDat4KP/xAAdEAACAwACAwAAAAAAAAAAAAABEQAhMRBRQWFx/9oACAEBAAE/IRgc3uMjpWnwMDUMJhcK3jJ1xP0cYQF4i1dz/9oADAMBAAIAAwAAABATDzz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAgEAEAAgIBBAMAAAAAAAAAAAABABEhQTEQUWFxgaGx/9oACAEBAAE/ED6VlBQo7waJDJYTowbDWwS2ASJrgcNeIAGGYKPx9x4gRINjY5qE16M/nf3P/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;mang&quot; title=&quot;&quot; src=&quot;/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/c08c5/mang.jpg&quot; srcset=&quot;/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/0913d/mang.jpg 160w,
/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/cb69c/mang.jpg 320w,
/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/c08c5/mang.jpg 640w,
/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/15ec7/mang.jpg 690w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;&quot;I need to dump these futures contracts fast...&quot;&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;When demand for crude oil itself drops, oil prices naturally fall. And at that time, Russia and Saudi Arabia were in an oil price war and increased production, causing crude oil spot prices to absolutely crater.&lt;/p&gt;
&lt;p&gt;The problem was that futures contracts bought before the crash had strike prices around $20 - the pre-crash price. For these contracts to be profitable, future crude oil spot prices needed to go up. But with all these factors combined, nobody wanted to buy these futures contracts. It was cheaper to just buy at current spot prices than to buy futures contracts.&lt;/p&gt;
&lt;p&gt;So there was an oversupply of sellers and no buyers - a truly tragic market situation.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1335a33be53bfd1691c01d192a5e32cc/6aca1/oil-future.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB5LbEcqWf/8QAFxABAQEBAAAAAAAAAAAAAAAAAQIQEv/aAAgBAQABBQKFa6ygwgT/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwFX/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BR//EABcQAAMBAAAAAAAAAAAAAAAAAAAQMRH/2gAIAQEABj8Cwij/AP/EABgQAQEBAQEAAAAAAAAAAAAAAAEAERBR/9oACAEBAAE/IR+pCeJgaAMOE1W//9oADAMBAAIAAwAAABDg7//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxCxh//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCNP//EABoQAQEBAQEBAQAAAAAAAAAAAAERACExYfD/2gAIAQEAAT8QAA8bYcC6KRx+7ppCCeXG9YBDuuscScfu/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;oil future&quot; title=&quot;&quot; src=&quot;/static/1335a33be53bfd1691c01d192a5e32cc/c08c5/oil-future.jpg&quot; srcset=&quot;/static/1335a33be53bfd1691c01d192a5e32cc/0913d/oil-future.jpg 160w,
/static/1335a33be53bfd1691c01d192a5e32cc/cb69c/oil-future.jpg 320w,
/static/1335a33be53bfd1691c01d192a5e32cc/c08c5/oil-future.jpg 640w,
/static/1335a33be53bfd1691c01d192a5e32cc/6aca1/oil-future.jpg 650w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;This is the &quot;I&apos;ll give you $37.63 if you please just buy my contract...&quot; situation&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;As futures contracts couldn’t be sold and expiration dates approached, futures investors panicked about actually taking delivery of crude oil. So they started throwing their contracts away while paying $37 per contract just to get rid of them. &lt;small&gt;&lt;del&gt;(The ultimate panic sell isn’t selling cheap - it’s paying someone to take it off your hands…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This is the scary situation that arises from the key difference between options and futures: “you can’t back out of the transaction when it expires.”&lt;/p&gt;
&lt;p&gt;On the other hand, &lt;strong&gt;options are about buying and selling the right to transact in the future&lt;/strong&gt;. They’re a type of futures contract, but since you’re contracting for “the right to transact” rather than “to transact,” you have the choice to exercise or not exercise your rights at expiration. In simple terms, options give you one more chance to make the final decision compared to regular futures.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;What you’re trading&lt;/th&gt;
&lt;th&gt;When it expires?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Futures&lt;/td&gt;
&lt;td&gt;Contract to transact underlying asset&lt;/td&gt;
&lt;td&gt;Transaction is executed no matter what&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Options&lt;/td&gt;
&lt;td&gt;Contract for the right to transact underlying asset&lt;/td&gt;
&lt;td&gt;You can exercise the right or not&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Also, since futures require mandatory execution at expiration, it’s a zero-sum game where one person profits and one person loses. But with options, the buyer can just abandon their rights, so the option seller can end up with a pure loss.&lt;/p&gt;
&lt;p&gt;That’s why when you buy an option, you pay the option seller a separate price for the option itself. This option price is calculated using methods like the &lt;a href=&quot;https://namu.wiki/w/%EB%B8%94%EB%9E%99-%EC%88%84%EC%A6%88%20%EB%AA%A8%ED%98%95&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Black-Scholes model&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;stock-options-the-right-to-buy-stock&quot; style=&quot;position:relative;&quot;&gt;Stock options: the right to buy stock&lt;a href=&quot;#stock-options-the-right-to-buy-stock&quot; aria-label=&quot;stock options the right to buy stock permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we know what options are, stock options are easy to explain. Stock options are options where the underlying asset is stock, meaning they’re contracts that give you the right to buy or sell stock at a specific price at a specific time.&lt;/p&gt;
&lt;p&gt;However, the incentive stock options we typically encounter aren’t about selling stock you already own - they’re additional incentives given when you don’t have any stock yet. So stock options just mean the right to buy stock, not to sell it. That’s why in Korean they’re called “stock purchase option rights.”&lt;/p&gt;
&lt;p&gt;When you receive stock options, you’re not receiving stock - you’re receiving “the right to buy stock.” And the act of “using my stock options to buy stock” is exercising your right to purchase stock, which is why we say we’re “exercising stock options.”&lt;/p&gt;
&lt;h3 id=&quot;granting-stock-options&quot; style=&quot;position:relative;&quot;&gt;Granting stock options&lt;a href=&quot;#granting-stock-options&quot; aria-label=&quot;granting stock options permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you join a company and they promise to grant you stock options, do you get them on day one when you sign your employment contract?&lt;/p&gt;
&lt;p&gt;Nope. Stock options aren’t something you can just hand out with a single contract. For a corporation to grant stock options to someone, they must hold a shareholders’ meeting and go through an approval process.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 78.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABumprSpigf//EABoQAAIDAQEAAAAAAAAAAAAAAAACAQMTBBL/2gAIAQEAAQUCzQwgzrF71gZva2dC1v8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAgEFAQAAAAAAAAAAAAAAAAECETEyQZEi/9oACAEBAAY/AsFwwiWXDBnmSVdjhem0f//EABwQAQEBAAEFAAAAAAAAAAAAAAERABAhMVGhsf/aAAgBAQABPyEZhkj8ocfbfRNKZDs6zQw+YI7/2gAMAwEAAgADAAAAEGjf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EFtL/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Qh//EABwQAQADAQADAQAAAAAAAAAAAAEAESExUWGR0f/aAAgBAQABPxAAmvAP5Ddtq0Mk518cfn0UCnh2BrQhBaY9ORaLqWmE/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;meeting&quot; title=&quot;&quot; src=&quot;/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg&quot; srcset=&quot;/static/783da1105578e0f9950fffb6d49bf961/0913d/meeting.jpg 160w,
/static/783da1105578e0f9950fffb6d49bf961/cb69c/meeting.jpg 320w,
/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg 640w,
/static/783da1105578e0f9950fffb6d49bf961/6a068/meeting.jpg 960w,
/static/783da1105578e0f9950fffb6d49bf961/eea4a/meeting.jpg 1280w,
/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg 1685w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Corporations can only grant stock options to specific individuals after shareholder approval&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;After the shareholders’ meeting resolves to grant the stock options and approve the shares to be issued or transferred upon exercise, then they can enter into a stock option grant agreement with the recipient.&lt;/p&gt;
&lt;p&gt;Why should we care about shareholder meetings when the company handles them? Because when your stock options are granted depends on how often these meetings are held. If you join in January 2021 but the shareholders’ meeting is in December, your stock option grant date could be after that.&lt;/p&gt;
&lt;p&gt;And the criteria for when and how much you can exercise your stock options are calculated from the &lt;strong&gt;stock option grant date&lt;/strong&gt; determined by this shareholders’ meeting, not your hire date. So you need to know when your company holds shareholder meetings to estimate when your grant date will be.&lt;/p&gt;
&lt;p&gt;Anyway, once the shareholders’ meeting approves granting you stock options, you’ll sign a stock option agreement. This agreement includes information like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Number of shares to receive&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stock option grant method and grant date&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stock option exercise price&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cliff and vesting period&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to exercise stock options&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;All of this is important, but when you get this agreement, the key things to look at are the stock option &lt;strong&gt;strike price&lt;/strong&gt;, &lt;strong&gt;cliff&lt;/strong&gt;, and &lt;strong&gt;vesting&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;strike-price&quot; style=&quot;position:relative;&quot;&gt;Strike price&lt;a href=&quot;#strike-price&quot; aria-label=&quot;strike price permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I mentioned earlier that stock options give you the right to buy stock at a predetermined price at a specific time. This “predetermined price” is called the &lt;strong&gt;strike price&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In other words, it’s literally the money you have to pay when you exercise your stock options to buy stock. If you thought stock options were just stock, you might be caught off guard when the company suddenly asks you to pay money when you want to exercise them.&lt;/p&gt;
&lt;p&gt;Stock options aren’t free stock - they’re “the right to buy stock,” so of course you have to pay. According to &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%83%81%EB%B2%95/%EC%A0%9C340%EC%A1%B0%EC%9D%982&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Article 340-2 of the Commercial Act&lt;/a&gt;, the strike price must be set at the higher of either the par value (initial capital divided by number of issued shares) or the current market price.&lt;/p&gt;
&lt;p&gt;However, companies that qualify for &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EB%B2%A4%EC%B2%98%EA%B8%B0%EC%97%85%EC%9C%A1%EC%84%B1%EC%97%90%EA%B4%80%ED%95%9C%ED%8A%B9%EB%B3%84%EC%A1%B0%EC%B9%98%EB%B2%95%EC%8B%9C%ED%96%89%EB%A0%B9/%EC%A0%9C11%EC%A1%B0%EC%9D%983&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;venture exemptions&lt;/a&gt; can set the strike price below market value if they meet certain conditions. Most startups qualify for venture exemptions, so they often set strike prices below market value. &lt;small&gt;(Kakao was a famous case that didn’t qualify for venture exemptions, so they had to set their strike price at market value at the time of grant)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Your actual pre-tax profit from stock options is &lt;code class=&quot;language-text&quot;&gt;(market price - strike price) * number of shares&lt;/code&gt;, and you might need to have cash ready to pay the strike price when exercising. So you absolutely need to know your stock options’ strike price.&lt;/p&gt;
&lt;h3 id=&quot;vesting&quot; style=&quot;position:relative;&quot;&gt;Vesting&lt;a href=&quot;#vesting&quot; aria-label=&quot;vesting permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Many of you probably know this already, but you can’t exercise stock options immediately after they’re granted.&lt;/p&gt;
&lt;p&gt;In Korea, &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%83%81%EB%B2%95/(20190916,14096,20160322)/%EC%A0%9C340%EC%A1%B0%EC%9D%984&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Article 340-4 of the Commercial Act&lt;/a&gt; states that you must remain employed “for at least 2 years from the shareholders’ meeting resolution date” before you can exercise stock options. Though in practice, companies usually count 2 years from the grant date rather than the resolution date. &lt;small&gt;(Since the grant date is always later than the resolution date anyway, this is legally fine)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Without this requirement, employees could exercise all their stock options immediately after receiving them and quit - a classic pump and dump - and the company would have no recourse. So this is a minimum safeguard.&lt;/p&gt;
&lt;p&gt;That’s why stock option agreements always include language like &lt;strong&gt;“can exercise n% after remaining employed for at least 24 months from grant date.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;How much you can exercise after 24 months depends on the company’s vesting plan. Early-stage startups sometimes let you exercise 100% after 2 years, but larger companies often split it up like “50% after 2 years, 25% in year 3, 25% in year 4.”&lt;/p&gt;
&lt;p&gt;It’s important to understand that after these periods pass, your stock options transition from unexercisable to exercisable - they’re not being granted or exercised automatically, and you’re not receiving stock yet. This &lt;strong&gt;transition from unexercisable to exercisable status is called vesting&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The first moment when you can exercise any of your granted stock options is called the &lt;strong&gt;cliff&lt;/strong&gt;. Cliff literally means cliff, and it’s called that because the amount of exercisable stock options jumps from 0 to some positive number. When you graph exercisable quantity over time, it looks like a cliff.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/830230ebe0f0489c89ca66d73e19a1a9/2adcb/cliff.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 46.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABKElEQVR42mNggABmIBYHYmkgZmdAA/8Z/jMykAi4gJgDivGC/wwMjHAcGsr8v76eCZs6TiQMA2BXrSpfxb+8aYvm/Pr9HMiGgun6fIH/lbmiyGLILuTC5sL9QIMWt2yXBNIsIP7LrHiJZ1lZ8o9TUmSe5+QoPi8u5sbmQlZo2GH18triRWIgjf9nprH+yEtXPRYaynklNJTtTFoaK66g4cPmQpg3HuXl6bzIzFR6k5si8yIvWZzYiGFBC0O4ge/S0uSAgc9Cakwzx+jpcf8HegPkHZABtzw82EEx+T4nRXEbkA1Uw1QPxAwIzAjFIMvYoDQEcHNzi9dYWhr+y82VuR4fr7A1IEDtK5D9LClJvsfeXgOkBOoDUWgQgYJHGIj5gVgAiOWAWAgAQQdW2jCQZooAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cliff&quot; title=&quot;&quot; src=&quot;/static/830230ebe0f0489c89ca66d73e19a1a9/6af66/cliff.png&quot; srcset=&quot;/static/830230ebe0f0489c89ca66d73e19a1a9/69538/cliff.png 160w,
/static/830230ebe0f0489c89ca66d73e19a1a9/72799/cliff.png 320w,
/static/830230ebe0f0489c89ca66d73e19a1a9/6af66/cliff.png 640w,
/static/830230ebe0f0489c89ca66d73e19a1a9/d9199/cliff.png 960w,
/static/830230ebe0f0489c89ca66d73e19a1a9/21b4d/cliff.png 1280w,
/static/830230ebe0f0489c89ca66d73e19a1a9/2adcb/cliff.png 1984w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;A sharp increase in exercisable stock options occurs 2 years from the grant date&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;This graph shows a vesting plan with a 4-year total vesting period and a 2-year cliff.&lt;/p&gt;
&lt;p&gt;Let’s say I join this company and immediately get granted 100 stock options after a shareholders’ meeting. Here’s roughly what happens:&lt;/p&gt;
&lt;p&gt;I have 100 stock options but can’t exercise any of them for the first 2 years from the grant date. Not being able to exercise stock options means I can’t exercise “the right to buy stock cheap,” so for the first 2 years I’m just holding them. &lt;small&gt;&lt;del&gt;(But I’m definitely tracking the company’s stock price from day one…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;When 2 years pass from the grant date, I can exercise 50% of my 100 stock options - that’s 50 shares. Since there’s still a long way to go before the vesting plan ends, it’s up to me whether to exercise then. As I’ll mention below, for tax optimization it’s sometimes better to exercise in batches rather than all at once, so exercising at this point isn’t a bad choice.&lt;/p&gt;
&lt;p&gt;After 3 years, I can exercise another 25% (half of the remaining 50%). So at this point I can exercise 75 of my original 100 stock options.&lt;/p&gt;
&lt;p&gt;Finally, after 4 years, I can exercise all my granted stock options and the vesting period ends. This 2-year cliff with &lt;code class=&quot;language-text&quot;&gt;50%/25%/25%&lt;/code&gt; vesting is very common, but there are various other vesting plans - some companies vest monthly after the 2-year cliff, for example.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🧐  I’ve seen places offering 1-year cliffs though?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As I mentioned, the minimum 2-year cliff is specified in Korean commercial law.&lt;/p&gt;
&lt;p&gt;So foreign companies, especially US companies where there’s no specific law about cliffs, might offer vesting plans like “1-year cliff, then monthly vesting in equal parts.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;exercising-stock-options-to-buy-stock&quot; style=&quot;position:relative;&quot;&gt;Exercising stock options to buy stock&lt;a href=&quot;#exercising-stock-options-to-buy-stock&quot; aria-label=&quot;exercising stock options to buy stock permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now we know when and how we receive stock options from the company and when we can exercise our rights. Let’s talk about the most important part: “the process of turning stock options into money.”&lt;/p&gt;
&lt;p&gt;The first step in turning stock options into money is exercising them to buy stock. As I’ve mentioned many times, exercising stock options means “I’m going to use my right to buy stock cheap to actually buy the stock.”&lt;/p&gt;
&lt;p&gt;The exercise method usually involves written notification to the company, but the exact process can vary by company, so check with your company’s person in charge or read your stock option agreement carefully.&lt;/p&gt;
&lt;h3 id=&quot;paying-the-stock-option-strike-price&quot; style=&quot;position:relative;&quot;&gt;Paying the stock option strike price&lt;a href=&quot;#paying-the-stock-option-strike-price&quot; aria-label=&quot;paying the stock option strike price permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Stock options come in three main types: new share issuance type, treasury stock delivery type, and cash settlement type. Whether you need to pay the strike price depends on which type you have.&lt;/p&gt;
&lt;p&gt;With cash settlement type, the company pays you cash equal to the difference between your stock option strike price and the current market price, so you don’t need to pay the strike price. But with new share issuance (where new shares are issued and given to you) and treasury stock delivery (where the company gives you shares it already owns), you’re exercising stock options to purchase stock, so you need to pay the strike price to the company.&lt;/p&gt;
&lt;p&gt;If you thought stock options were just stock, you might not have the cash on hand to pay the strike price even after your options vest. This could prevent you from exercising the desired amount of stock options or even force you to take out an emergency loan. So always remember your stock options are “the right to purchase stock.”&lt;/p&gt;
&lt;h3 id=&quot;income-means-taxes&quot; style=&quot;position:relative;&quot;&gt;Income means taxes!&lt;a href=&quot;#income-means-taxes&quot; aria-label=&quot;income means taxes permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Taxes on stock options can vary slightly by situation, so what I’m explaining here isn’t 100% accurate in all cases.&lt;/p&gt;
&lt;p&gt;This is just to give you a rough idea of how they’re calculated - for accurate information, ask your company when you exercise your stock options.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Actually, the most important thing to understand about exercising stock options is &lt;strong&gt;taxes&lt;/strong&gt;. Unfortunately, stock you receive from exercising stock options counts as income, so naturally you have to pay income tax on it. &lt;small&gt;&lt;del&gt;(No idea why they count unsold stock as income, but whatever…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2923ebd94179d5db9428479351befdbb/4a359/poor.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 71.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQT/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAYYtAuYUs//EABsQAAIDAAMAAAAAAAAAAAAAAAECAAMTERQi/9oACAEBAAEFAkrznPnriB9FUASxyH//xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAwEBPwGI/8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8Bqv/EABsQAQACAgMAAAAAAAAAAAAAAAEAERAhUXGR/9oACAEBAAY/Amj2KBd8Yt11hJ//xAAdEAEAAgICAwAAAAAAAAAAAAABABEhMUFRcZGh/9oACAEBAAE/IQwyPJl8ltI7FHq55XYhVp9mvsHlUT//2gAMAwEAAgADAAAAEKA//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERUf/aAAgBAwEBPxBMTZ//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxCH/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFBUWFx/9oACAEBAAE/EJOGKJ0cSmuXLrdixEXUOucFBQbYafMalTxmQ+3v8y0z2UYejF5ywZLrzP/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;poor&quot; title=&quot;&quot; src=&quot;/static/2923ebd94179d5db9428479351befdbb/c08c5/poor.jpg&quot; srcset=&quot;/static/2923ebd94179d5db9428479351befdbb/0913d/poor.jpg 160w,
/static/2923ebd94179d5db9428479351befdbb/cb69c/poor.jpg 320w,
/static/2923ebd94179d5db9428479351befdbb/c08c5/poor.jpg 640w,
/static/2923ebd94179d5db9428479351befdbb/4a359/poor.jpg 719w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;After year-end tax settlement...&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Income from exercising stock options is calculated as &lt;code class=&quot;language-text&quot;&gt;(market price - strike price) * number of shares&lt;/code&gt;, and the taxes vary depending on whether you’re still employed at that company, how much income you earn from exercising, and whether your company is a venture company.&lt;/p&gt;
&lt;p&gt;For startups, since they’re usually unlisted with few stock transactions, they use a &lt;strong&gt;supplementary valuation method&lt;/strong&gt; that calculates market price based on net asset value per share and net income value per share. As you know, startups often aren’t focused on operating profit - they just burn money to generate revenue growth. So when you calculate market price using the supplementary valuation method, it might actually be lower than the strike price.&lt;/p&gt;
&lt;p&gt;When market price is lower than strike price, exercising stock options to acquire stock is actually a loss, so income is calculated as negative and you don’t pay income tax. &lt;small&gt;(In this case you’re hoping the next funding round will bring a higher valuation from VCs)&lt;/small&gt;&lt;/p&gt;
&lt;h4 id=&quot;if-youre-still-employed-earned-income&quot; style=&quot;position:relative;&quot;&gt;If you’re still employed: earned income&lt;a href=&quot;#if-youre-still-employed-earned-income&quot; aria-label=&quot;if youre still employed earned income permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;First, taxes on stock option exercise differ depending on whether you’re still employed at the company.&lt;/p&gt;
&lt;p&gt;If you’re still employed when exercising stock options, all profits from exercising are evaluated as &lt;strong&gt;earned income&lt;/strong&gt; and added to your annual comprehensive income. So the taxes you pay are determined by &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%86%8C%EB%93%9D%EC%84%B8%EB%B2%95/%EC%A0%9C55%EC%A1%B0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Article 55 of the Income Tax Act&lt;/a&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Income bracket&lt;/th&gt;
&lt;th&gt;Tax rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Up to 12 million won&lt;/td&gt;
&lt;td&gt;6% of taxable base&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12 million - 46 million won&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;46 million - 88 million won&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;88 million - 150 million won&lt;/td&gt;
&lt;td&gt;35%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;150 million - 300 million won&lt;/td&gt;
&lt;td&gt;38%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300 million - 500 million won&lt;/td&gt;
&lt;td&gt;40%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500 million - 1 billion won&lt;/td&gt;
&lt;td&gt;42%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Over 1 billion won&lt;/td&gt;
&lt;td&gt;45%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you probably know, this is a progressive tax applied only to the amount exceeding each bracket, not to the entire amount. So if my total income this year is 100 million won, I don’t pay 35% on the full 100 million. Instead, I pay 6% up to 12 million, 15% on the portion exceeding 12 million, 24% on the portion exceeding 46 million, and so on - the higher rate only applies to the portion exceeding each bracket.&lt;/p&gt;
&lt;p&gt;The problem is that with just your salary, you often won’t exceed 35%, but once stock options are added, your income bracket suddenly jumps way up. So if you thoughtlessly exercise all your stock options at once, you could face a tax bomb of tens of millions of won.&lt;/p&gt;
&lt;p&gt;That’s why when exercising stock options, it’s generally better to do it in batches rather than all at once for tax optimization.&lt;/p&gt;
&lt;p&gt;However, according to &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%A1%B0%EC%84%B8%ED%8A%B9%EB%A1%80%EC%A0%9C%ED%95%9C%EB%B2%95/(20211123,18521,20211123)/%EC%A0%9C16%EC%A1%B0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Article 16 of the Restriction of Special Taxation Act&lt;/a&gt;, if your company qualifies for venture exemptions, there are some benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[Article 16-2] No tax on profits up to 30 million won per year (raised to 50 million won for stock options granted from 2022 onwards)&lt;/li&gt;
&lt;li&gt;[Article 16-3] If the company applies for tax payment exemption, earned income tax isn’t withheld. You can pay income tax in 1/5 installments over 5 years&lt;/li&gt;
&lt;li&gt;[Article 16-4] If total exercise price over 3 years is under 500 million won, you don’t pay income tax at exercise - instead you pay capital gains tax when you sell the stock&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simply put, the government is using tax breaks on stock option exercise at venture companies to encourage venture company growth. Many decently-sized startups still qualify for venture exemptions, so definitely look into this.&lt;/p&gt;
&lt;p&gt;If your company qualifies for venture exemptions, you could pay zero income tax by only exercising 30 million won worth of stock options per year. But if your profits are in the hundreds of millions, this approach would take too long, so you might want to consider other strategies.&lt;/p&gt;
&lt;h4 id=&quot;if-youre-no-longer-employed-other-income&quot; style=&quot;position:relative;&quot;&gt;If you’re no longer employed: other income&lt;a href=&quot;#if-youre-no-longer-employed-other-income&quot; aria-label=&quot;if youre no longer employed other income permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Many companies only allow you to exercise stock options while still employed, but some companies let you exercise even after leaving.&lt;/p&gt;
&lt;p&gt;In this case, since you’re exercising stock options after the employment relationship has ended, profits are evaluated as other income rather than earned income. At exercise, 22% total tax (including 2% local income tax) is withheld from the profits.&lt;/p&gt;
&lt;p&gt;Also, if other income exceeds 3 million won per year, you need to include it in comprehensive income and file a final tax return. At that point, taxes are recalculated using the comprehensive income tax rate table above. If other income is under 3 million won you could just end it with withholding, but since stock options almost never earn less than 3 million won, you should pretty much always expect to file a comprehensive income final tax return.&lt;/p&gt;
&lt;p&gt;Taxes are complicated and vary based on your company’s current status and your earned income, so you can’t know exactly how much tax you’ll owe until you actually exercise.&lt;/p&gt;
&lt;p&gt;But you should prepare for tax payments before exercising to avoid cash flow problems later. So definitely be aware that you have to pay taxes when exercising stock options.&lt;/p&gt;
&lt;h2 id=&quot;ready-to-sell-that-stock&quot; style=&quot;position:relative;&quot;&gt;Ready to sell that stock?&lt;a href=&quot;#ready-to-sell-that-stock&quot; aria-label=&quot;ready to sell that stock permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Even after exercising stock options to buy stock, it’s not your money yet. You need to sell your stock to actually realize the profit.&lt;/p&gt;
&lt;p&gt;So who do you sell these shares to? If your company is publicly traded, selling stock is easy. But most stock options are granted when companies are still small and growing, so even when your vesting plan ends and you actually buy the stock, the company is often still private.&lt;/p&gt;
&lt;p&gt;When trading unlisted stock, you use OTC platforms like &lt;a href=&quot;https://www.seoulexchange.kr/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Seoul Exchange&lt;/a&gt; or &lt;a href=&quot;https://www.ustockplus.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Ustock Plus Unlisted&lt;/a&gt;, or you trade directly with a buyer through a contract.&lt;/p&gt;
&lt;p&gt;But here’s an important point: stock received from stock options often has &lt;strong&gt;right of first refusal&lt;/strong&gt; provisions, or might be completely locked from selling before IPO (initial public offering) or M&amp;#x26;A (merger &amp;#x26; acquisition).&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 400px&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f78708042d7eb6fa950c8953c131c193/1ef88/messi.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 88.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwIE/9oADAMBAAIQAxAAAAFNVCk3J1xo5gaaIzt//8QAHxAAAAUEAwAAAAAAAAAAAAAAAAECAxEEEhMhIjJE/9oACAEBAAEFAi21mhZOyN4GCuXySPJT9x//xAAaEQABBQEAAAAAAAAAAAAAAAAAAQIQEiEy/9oACAEDAQE/AesKKNj/xAAaEQACAgMAAAAAAAAAAAAAAAAAAQIhEBJB/9oACAECAQE/AajZuh9x/8QAHhAAAQMEAwAAAAAAAAAAAAAAAAECERIhUXEQMpH/2gAIAQEABj8CqVJgqydXeDtWL4IQdrn/xAAbEAEBAQACAwAAAAAAAAAAAAABABEhMWFxgf/aAAgBAQABPyENgAn0MhGjHi76TgJ2iOhpIdN4HJ7v/9oADAMBAAIAAwAAABCM2L//xAAYEQEBAAMAAAAAAAAAAAAAAAABABAxQf/aAAgBAwEBPxAUCk3Vxj//xAAXEQEBAQEAAAAAAAAAAAAAAAABEQAQ/9oACAECAQE/EAocOW9v/8QAHBABAQACAwEBAAAAAAAAAAAAAREAQSExcVGx/9oACAEBAAE/EKDC1jKG8HHQBOK/cqlN8H7gAqD2k9yDuzXhnKk6LlTFnWAjBaMwmhn/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;messi&quot; title=&quot;&quot; src=&quot;/static/f78708042d7eb6fa950c8953c131c193/c08c5/messi.jpg&quot; srcset=&quot;/static/f78708042d7eb6fa950c8953c131c193/0913d/messi.jpg 160w,
/static/f78708042d7eb6fa950c8953c131c193/cb69c/messi.jpg 320w,
/static/f78708042d7eb6fa950c8953c131c193/c08c5/messi.jpg 640w,
/static/f78708042d7eb6fa950c8953c131c193/6a068/messi.jpg 960w,
/static/f78708042d7eb6fa950c8953c131c193/1ef88/messi.jpg 1242w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;You have to offer your shares to that person over there first before selling to anyone else&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;Right of first refusal means &lt;strong&gt;the right to purchase shares before anyone else&lt;/strong&gt;, and in most cases the holder of this right is the company (corporation) or someone designated by the company (individual).&lt;/p&gt;
&lt;p&gt;The reason companies bother us like this is simple - whether it’s newly issued shares or treasury stock distributed, they’re wary of these shares ending up in hostile hands.&lt;/p&gt;
&lt;p&gt;When you exercise stock options, existing investors’ equity gets diluted. By buying back these shares or redistributing them to existing investors, they’re trying to maintain friendly ownership.&lt;/p&gt;
&lt;p&gt;So when you transfer stock acquired from exercising stock options, read the original grant agreement carefully and check whether you need to give written notice to the company, whether there’s a right of first refusal holder, and whether you can actually sell the stock.&lt;/p&gt;
&lt;h3 id=&quot;sold-your-stock-time-to-pay-taxes&quot; style=&quot;position:relative;&quot;&gt;Sold your stock? Time to pay taxes!&lt;a href=&quot;#sold-your-stock-time-to-pay-taxes&quot; aria-label=&quot;sold your stock time to pay taxes permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So once you’ve sold all your stock, are you done? Nope. You also have to pay taxes on the profits from selling the stock. In the US, you don’t pay separate taxes at exercise - you just pay 20% capital gains tax when you sell the stock. But in Korea, you pay income tax when exercising stock options AND income tax again when selling the stock. &lt;small&gt;&lt;del&gt;(Stop taking my money!)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This tax is called &lt;strong&gt;capital gains tax&lt;/strong&gt;, which will be familiar to anyone who trades foreign stocks. You have to pay 22% capital gains tax annually on profits from foreign stock trading.&lt;/p&gt;
&lt;p&gt;So many people think there are no taxes beyond securities transaction tax when trading domestic stocks. But this depends on whether the stock you’re selling is from a listed company or an unlisted company.&lt;/p&gt;
&lt;p&gt;If you’re selling stock when your company is still unlisted and is a small to medium enterprise, you pay 11% total capital gains tax (including local income tax) on profits from selling the stock. If it’s a mid-sized or larger company, you pay 22%. &lt;small&gt;(Local income tax is 10% of the tax owed)&lt;/small&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company size&lt;/th&gt;
&lt;th&gt;Capital gains tax rate (including local tax)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Small to medium enterprise&lt;/td&gt;
&lt;td&gt;11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mid-sized/large enterprise&lt;/td&gt;
&lt;td&gt;22%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If your ownership is 4% or more or your shares are worth over 1 billion won, you’re classified as a major shareholder and pay more capital gains tax. But since we’re rarely major shareholders, just think of it as 11% or 22% including local income tax.&lt;/p&gt;
&lt;p&gt;The silver lining is that there’s a 2.5 million won capital gains tax exemption. So if your total profit from selling stock is 10 million won, you only pay 11% tax on 7.5 million won (after deducting the 2.5 million won exemption). But since stock option profits are usually at least in the tens of millions, it’s easier to just assume you’ll pay capital gains tax from the start.&lt;/p&gt;
&lt;p&gt;If your company is publicly traded, as long as you’re not a major shareholder, you won’t pay capital gains tax - it’s just like regular stock trading.&lt;/p&gt;
&lt;h2 id=&quot;stock-option-expiration&quot; style=&quot;position:relative;&quot;&gt;Stock option expiration&lt;a href=&quot;#stock-option-expiration&quot; aria-label=&quot;stock option expiration permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is another thing many people miss - even vested stock options don’t give you rights that last forever. In other words, under certain conditions your stock option grant can be cancelled or you might lose the ability to exercise.&lt;/p&gt;
&lt;p&gt;Stock option expiration terms vary by company, but here are some common cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quit your job? Stock option grant cancelled&lt;/li&gt;
&lt;li&gt;Quit your job? You must exercise all vested stock options at the time you leave&lt;/li&gt;
&lt;li&gt;You must exercise within 4 years of being granted stock options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is also in the stock option grant agreement, so read the agreement very carefully when receiving stock options.&lt;/p&gt;
&lt;h2 id=&quot;how-can-you-make-a-good-choice&quot; style=&quot;position:relative;&quot;&gt;How can you make a good choice?&lt;a href=&quot;#how-can-you-make-a-good-choice&quot; aria-label=&quot;how can you make a good choice permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b19e4452b9c863d23502a510a26ae493/d7854/zzal.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUDBAb/xAAXAQADAQAAAAAAAAAAAAAAAAABAgME/9oADAMBAAIQAxAAAAFZoETQrQIimf8A/8QAGxAAAQQDAAAAAAAAAAAAAAAAAgABAxIEERP/2gAIAQEAAQUCZPAPJRlWQ8ka7X//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREC/9oACAEDAQE/AcYbVhD/xAAWEQADAAAAAAAAAAAAAAAAAAABAhD/2gAIAQIBAT8BYz//xAAcEAABBQADAAAAAAAAAAAAAAABABAREiECMUH/2gAIAQEABj8CUegdsOR2EaWGN//EABwQAAICAgMAAAAAAAAAAAAAAAABEVEQITFBYf/aAAgBAQABPyFmRketY1QpUg3FjSNiCXuH/9oADAMBAAIAAwAAABDIL//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxB0dE6v/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREA/9oACAECAQE/EBIXXf/EABsQAQEAAgMBAAAAAAAAAAAAAAERADEhUYFh/9oACAEBAAE/EAPG7xjH6ykVt1v3Fp+u8LnQsphZ7qHS9YYQRuf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;zzal&quot; title=&quot;&quot; src=&quot;/static/b19e4452b9c863d23502a510a26ae493/d7854/zzal.jpg&quot; srcset=&quot;/static/b19e4452b9c863d23502a510a26ae493/0913d/zzal.jpg 160w,
/static/b19e4452b9c863d23502a510a26ae493/cb69c/zzal.jpg 320w,
/static/b19e4452b9c863d23502a510a26ae493/d7854/zzal.jpg 550w&quot; sizes=&quot;(max-width: 550px) 100vw, 550px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;So when faced with choices like “stock options vs. salary increase,” what should you consider? Personally, I’d recommend looking not just at the stock option amount, but also at things like the vesting plan and tax optimization benefits.&lt;/p&gt;
&lt;h3 id=&quot;calculate-actual-profit-from-stock-options&quot; style=&quot;position:relative;&quot;&gt;Calculate actual profit from stock options&lt;a href=&quot;#calculate-actual-profit-from-stock-options&quot; aria-label=&quot;calculate actual profit from stock options permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you’ve read this far, you know that receiving 100 million won worth of stock options doesn’t mean your actual profit will be 100 million won.&lt;/p&gt;
&lt;p&gt;When exercising stock options, you have to pay the strike price to the company and also pay income tax. When selling stock acquired from stock options, you pay capital gains tax again. Of course, we’re not tax accountants, so we can’t predict future taxes precisely. But you can roughly estimate how much you’ll owe based on tax rate information already available online.&lt;/p&gt;
&lt;p&gt;Depending on acquisition value, you might pay up to 45% of your profits in taxes, so definitely calculate and recalculate before choosing stock options.&lt;/p&gt;
&lt;h3 id=&quot;you-must-stay-at-the-company-until-the-cliff&quot; style=&quot;position:relative;&quot;&gt;You must stay at the company until the cliff&lt;a href=&quot;#you-must-stay-at-the-company-until-the-cliff&quot; aria-label=&quot;you must stay at the company until the cliff permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As I mentioned, Korean law requires at least 2 years of employment before you can vest stock options. But depending on the company’s vesting plan, the cliff might be 2 years or 3 years, so think of &lt;strong&gt;cliff === period I can’t quit the company&lt;/strong&gt; when making your decision.&lt;/p&gt;
&lt;p&gt;You need to pass at least the cliff period before you have any exercisable stock options. So if you don’t plan to stick around that long, it might be better to just take cash like a signing bonus and invest it separately.&lt;/p&gt;
&lt;h3 id=&quot;consider-company-size-and-growth-potential&quot; style=&quot;position:relative;&quot;&gt;Consider company size and growth potential&lt;a href=&quot;#consider-company-size-and-growth-potential&quot; aria-label=&quot;consider company size and growth potential permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Stock options are financial instruments that benefit you more when your company grows and the gap between strike price and market price widens. In other words, your potential gain depends on “how much more this company will grow.”&lt;/p&gt;
&lt;p&gt;For example, a startup that just finished Series A funding has such a low current valuation that it’s common for valuations to increase 20x or 30x with each funding round. Well-performing companies sometimes get valuations over 100x higher.&lt;/p&gt;
&lt;p&gt;That’s why you hear about stock option jackpot stories in the tens of millions - they mostly come from this space. But the flip side is these companies might not have found product-market fit yet and have no market influence, so there’s also a high probability your stock options become worthless.&lt;/p&gt;
&lt;p&gt;But if your company has already grown to Series D or E funding rounds, the chance of the company failing and your stock options becoming worthless is low - but growth potential might not be as huge as a tiny startup.&lt;/p&gt;
&lt;p&gt;Plus, large companies like Naver or Kakao don’t qualify for venture exemptions. So even if you get stock options now, you’ll barely get any tax benefits, and the stock option strike price will be set at market value at grant time, so when you run the numbers it might not be such a huge amount.&lt;/p&gt;
&lt;p&gt;Of course, even if the company is large, if they’re planning promising new business ventures that could skyrocket the company’s value, the stock options could be almost as safe as guaranteed assets. So before accepting stock options, try to gather as much information as possible about the company’s future plans to make a good decision.&lt;/p&gt;
&lt;h3 id=&quot;plan-your-personal-cash-flow&quot; style=&quot;position:relative;&quot;&gt;Plan your personal cash flow&lt;a href=&quot;#plan-your-personal-cash-flow&quot; aria-label=&quot;plan your personal cash flow permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When explaining stock options earlier, I talked a lot about cash flow. People usually only think about corporate cash flow, but cash flow is extremely important for individuals too.&lt;/p&gt;
&lt;p&gt;Once cash flow gets blocked, you might have to take out unplanned loans or sell stocks at a loss just to raise cash.&lt;/p&gt;
&lt;p&gt;If you haven’t thought about or planned for the strike price and taxes you’ll need to pay when exercising stock options, you might not be able to exercise when the time comes due to lack of funds, or you might have to take out loans to pay taxes - a truly tearful situation.&lt;/p&gt;
&lt;p&gt;So before choosing stock options, ask about the company’s vesting plan ahead of time and think about whether you’ll have major expenses like lease renewal when your cliff hits and vesting periods come around.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I mentioned at the start, I wrote this post because many people holding stock options simply think of them as regular stock.&lt;/p&gt;
&lt;p&gt;Especially for people receiving stock options for the first time, when I tell them “that’s not free, you have to pay money when you exercise,” they sometimes ask why they have to pay money to sell stock - showing how many people really don’t understand stock options. &lt;small&gt;(Surprisingly many people thought vesting stock options meant selling stock)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;But stock options are financial instruments paid as compensation, so it’s very important to know exactly how much compensation you’re receiving and what process you need to go through to realize that compensation as profit.&lt;/p&gt;
&lt;p&gt;Also, many people think stock options are granted for free, but by choosing stock options you might be accepting a lower salary increase rate or even freezing your salary, and you might be giving up cash benefits like signing bonuses. So it’s not really free.&lt;/p&gt;
&lt;p&gt;The salary increase or cash benefits you’re giving up become an opportunity cost, and this opportunity cost is effectively the premium you’re paying to receive stock options as a financial instrument.&lt;/p&gt;
&lt;p&gt;I hope that going forward, when you encounter choices like ”&lt;span class=&quot;math math-inline&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;5K raise or &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;Kr&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;seor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;50K in stock options,” you’ll consider all these factors and make decisions that maximize your potential gains.&lt;/p&gt;
&lt;p&gt;That wraps up my post on everything developers need to know about stock options.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[개발자가 알아야 할 스톡옵션의 모든 것]]></title><description><![CDATA[이번 포스팅에서는 평소와는 조금 다르게 필자의 철학이나 기술적인 내용이 아닌 내용을 이야기해보려고 한다. 바로 IT 업계에서 일하는 사람이라면 한번쯤은 들어보았을만한 그 녀석, **스톡옵션(Stock Option)**에 대한 이야기이다. 최근 계속 되는 개발자 채용난으로 인해 꽤나 많은 기업들이 채용에 대한 보상으로 사이닝 보너스나 스톡옵션을 내거는 경우가 많아지고 있는데, 정작 스톡옵션이 무엇인지, 어떻게 나에게 이익을 가져다 줄 수 있는 녀석인지, 세금을 얼마나 내야하는지에 대해서는 잘 모르고 덥썩 받는 경우가 왕왕 있다.]]></description><link>https://evan-moon.github.io/2021/12/04/what-is-stock-options/</link><guid isPermaLink="false">20211204-what-is-stock-options</guid><pubDate>Sat, 04 Dec 2021 02:31:02 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 평소와는 조금 다르게 필자의 철학이나 기술적인 내용이 아닌 내용을 이야기해보려고 한다. 바로 IT 업계에서 일하는 사람이라면 한번쯤은 들어보았을만한 그 녀석, **스톡옵션(Stock Option)**에 대한 이야기이다.&lt;/p&gt;
&lt;p&gt;최근 계속 되는 개발자 채용난으로 인해 꽤나 많은 기업들이 채용에 대한 보상으로 사이닝 보너스나 스톡옵션을 내거는 경우가 많아지고 있는데, 정작 스톡옵션이 무엇인지, 어떻게 나에게 이익을 가져다 줄 수 있는 녀석인지, 세금을 얼마나 내야하는지에 대해서는 잘 모르고 덥썩 받는 경우가 왕왕 있다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;심지어는 “내가 1억원 어치 스톡옵션 100주를 받았을 때 우리 회사 밸류에이션이 1천억이었는데, 지금은 5천억이니까 내 돈도 5배가 되었네”라고 생각하시는 경우도 있는데, 스톡옵션의 가치는 이렇게 단순하게 계산되는 것이 아니고 수익에 대한 세금도 내야하기 때문에 실제로 이거보다 낮은 이익을 얻기도 할 뿐더러, 행사가나 세금을 내기위한 현금을 마련하지 못해서 당황스러운 경험을 하는 경우도 발생한다.&lt;/p&gt;
&lt;p&gt;사이닝 보너스는 대부분 입사한 이후 첫 월급날에 일정량의 현금을 일시 지급하는, 말 그대로 일반적으로 생각하는 인센티브이기 때문에 이해하기가 어렵지 않지만, 스톡옵션의 경우에는 금융 파생 상품이다보니 금융에 대한 지식이 없는 분들은 스톡옵션이 정확히 무엇인지 조금 이해하기 어려울 수가 있다.&lt;/p&gt;
&lt;p&gt;물론 그냥 주식이라고 생각해도 큰 문제가 발생하지는 않겠지만, 엄연히 스톡옵션은 주식과 다르기 때문에 이 차이를 이해하지 못한다면 여러분이 미리 계획해둔 개인적인 현금 흐름에 좋지 않은 영향이 갈 수도 있다.&lt;/p&gt;
&lt;h2 id=&quot;연봉-5백만원-올릴래-스톡옵션-5천만원-어치-받을래&quot; style=&quot;position:relative;&quot;&gt;연봉 5백만원 올릴래? 스톡옵션 5천만원 어치 받을래?&lt;a href=&quot;#%EC%97%B0%EB%B4%89-5%EB%B0%B1%EB%A7%8C%EC%9B%90-%EC%98%AC%EB%A6%B4%EB%9E%98-%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98-5%EC%B2%9C%EB%A7%8C%EC%9B%90-%EC%96%B4%EC%B9%98-%EB%B0%9B%EC%9D%84%EB%9E%98&quot; aria-label=&quot;연봉 5백만원 올릴래 스톡옵션 5천만원 어치 받을래 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자 일단은 이 스톡옵션이라고 하는 녀석이 정확히 무엇인지부터 살펴보도록 하자. 개발자로 일을 하다보면 대부분 한번 쯤은 이런 제안들을 받아볼 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;연봉을 5백만원 높히기 vs 연봉은 동결하고 5천만원 가치의 스톡옵션 받기&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;사이닝 보너스 5천만원 vs 1억원 가치의 스톡옵션(혹은 RSU)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;물론 이 바닥에서 몇 년 굴러본 사람들이야 자기 상황에 맞게 좋은 선택을 할 수 있겠지만, 이런 제안을 처음 받아본 입장에서는 여러모로 골치가 아프다. 이때 스톡옵션에 대해서 잘 모른다면 이렇게 생각할 수도 있겠다.&lt;/p&gt;
&lt;center&gt;
  &lt;img src=&quot;/61beca707059c9a6222de21b1eda6779/good.gif&quot; width=&quot;100%&quot;&gt;
  &lt;br&gt;
  &lt;small&gt;연봉 5백만원을 내주고 5천만원 어치 주식을 준다고? 완전 대박이자너~&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;주변에서 스톡옵션이 대박나서 10억을 벌었대니, 집을 샀대니 하는 소식도 간혹 들려오고, 고작 연봉 5백만원을 높혀봤자 세금 떼고 차 떼고 포 떼고 나면 매달 받는 실수령액이 크게 느는 것도 아닐테니, 회사 주식을 5천만원 어치나 주겠다는 제안이 크게 나쁘지 않아보이기는 한다.&lt;/p&gt;
&lt;p&gt;하지만 여기서 중요한 사실은 “스톡옵션(Stock Option)은 주식(Stock)이 아니라는 것”이다.&lt;/p&gt;
&lt;p&gt;엥 스톡옵션이 주식이 아니라니? 하지만 회사들은 마치 스톡옵션이 주식인 것처럼 “스톡옵션 100주 부여”라고 하고 있지 않은가?&lt;/p&gt;
&lt;p&gt;우리가 주식과 스톡옵션의 정확한 차이를 알기 위해서는 이 **옵션(Option)**이라는 녀석이 도대체 뭐하는 금융 상품인지부터 알아야 한다.&lt;/p&gt;
&lt;h2 id=&quot;시간-가치를-가지고-있는-금융-상품-옵션option&quot; style=&quot;position:relative;&quot;&gt;시간 가치를 가지고 있는 금융 상품, 옵션(Option)&lt;a href=&quot;#%EC%8B%9C%EA%B0%84-%EA%B0%80%EC%B9%98%EB%A5%BC-%EA%B0%80%EC%A7%80%EA%B3%A0-%EC%9E%88%EB%8A%94-%EA%B8%88%EC%9C%B5-%EC%83%81%ED%92%88-%EC%98%B5%EC%85%98option&quot; aria-label=&quot;시간 가치를 가지고 있는 금융 상품 옵션option permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;옵션은 &lt;strong&gt;어떠한 기초자산을 만기 시점에 특정한 가격으로 사고 팔 수 있는 권리를 거래하는 계약&lt;/strong&gt;을 의미한다. 쉽게 말하면 미래의 가격이 어떻게 변할지에 배팅하는 파생상품이라고 생각해도 된다.&lt;/p&gt;
&lt;p&gt;평소 투자에 관심이 많지 않으셨던 분이라면 이게 도대체 무슨 뜻인지 이해가 잘 안 가실 수 있으니 하나하나 천천히 살펴보도록 하자.&lt;/p&gt;
&lt;p&gt;먼저, &lt;strong&gt;기초자산&lt;/strong&gt;이라는 것은 주식, 채권, 달러, 금, 비트코인처럼 그 자체만으로 경제적인 가치를 가지고 있는 자산을 의미한다. 그리고 이 기초자산의 거래를 편하게 하거나, 가격 변동성을 방어해주는 등의 시장 니즈로 인해 탄생한 녀석들이 옵션(Option), 선물(Future), 스왑(Swap) 같은 파생상품들이다.&lt;/p&gt;
&lt;p&gt;스톡옵션의 경우에는 말 그대로 주식(Stock)에 대한 옵션이라는 뜻이니까 이때의 기초자산은 우리 회사의 주식이 되는 것이다.&lt;/p&gt;
&lt;p&gt;그리고 &lt;strong&gt;만기 시점에 특정한 가격으로 사고 팔 수 있는 권리&lt;/strong&gt;라는 것은 말 그대로 미래에 어떤 시점에 미리 정해둔 가격으로 기초자산을 사거나 팔 수 있는 권리를 의미한다. 이것도 말로만 설명하면 이해하기 쉽지 않을테니, 한번 옥수수를 기초자산으로 하는 옵션이 어떤 식으로 돌아가는지 살펴보도록 하자.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;12월 4일 (현재 옥수수 가격 1개 당 500원)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;필자: 한 달 뒤인 1월 4일에 옥수수 한 개를 600원에 사고 싶소.&lt;/p&gt;
&lt;p&gt;상인: ㅇㅋㅇㅋ. 그럼 한 달 뒤에 옥수수 가격이 얼마가 되었든 600원에 사실 수 있는 권리를 100원에 팔게요. 진짜 살지 말지는 그때 가서 결정하세요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1월 4일 (현재 옥수수 가격 1개 당 1000원)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;필자: 오 옥수수가 많이 올랐네? 자 이제 내가 가진 옵션(살 수 있는 권리)을 행사해서 옥수수를 한 개당 600원에 사야겠다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위 예시에서는 옥수수를 살 수 있는 권리를 사고 파는 것, 즉 콜옵션(Call Option)을 설명하고 있다. 필자는 옥수수의 가격이 현재 얼마든 간에 예전에 사둔 콜옵션을 행사해서 무조건 600원에 살 수 있으니, 한달 동안 옥수수의 가격이 많이 오를수록 더 큰 차익을 얻게 되는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ff68626a0dad3dd5b48e34a969701d5d/9cac8/call-option.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 33.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABJ0lEQVR42mNgwATCQMzEQAT4z8DA+P//f0Z8ajiAmA+IGYk15H99PdOxwkJOkNh/BkzDxYFYkqAhQPbz4mLu19nZUq+ys9XO5DYrE3IlE1ZD09K4XqWlSb7MSlb5kJmo9DQtTeR/KAPzwop1wktqtuqubdkOdowAEPOC6DTjNFZ1dSteYyANdAbjqlWrmE/k1vPdLiqSvZ+ZqXk3JVvtflaJxCqgFxkY6pkY6v8zhYauYp6cvVB4Zv0mrpkzz7CCDFQAYhkgVpyYO5Hd3z5e4FBupeiz4mr5RxnFOvfyS9VvFlZJ78+q50lLO8NaX3+FbWLuNvZtEyF4fv1+jt7CVZy4vCuSrKWlcig0VGuWh4eMvagoD1CMGYhZgJgdGhwcWNggzA8yAQBQZWpop7Fk2AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;call option&quot; title=&quot;&quot; src=&quot;/static/ff68626a0dad3dd5b48e34a969701d5d/6af66/call-option.png&quot; srcset=&quot;/static/ff68626a0dad3dd5b48e34a969701d5d/69538/call-option.png 160w,
/static/ff68626a0dad3dd5b48e34a969701d5d/72799/call-option.png 320w,
/static/ff68626a0dad3dd5b48e34a969701d5d/6af66/call-option.png 640w,
/static/ff68626a0dad3dd5b48e34a969701d5d/d9199/call-option.png 960w,
/static/ff68626a0dad3dd5b48e34a969701d5d/21b4d/call-option.png 1280w,
/static/ff68626a0dad3dd5b48e34a969701d5d/9cac8/call-option.png 2288w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    옥수수 가격이 아무리 올라도 콜옵션을 행사하면&lt;br&gt;
    무조건 600원에 살 수 있으니 옥수수가 비싸질수록 이득이다
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;살 수 있는 권리가 있다는 것은 반대로 팔 수 있는 권리도 있다는 것이며, 이때 기초자산을 팔 수 있는 권리를 매매하는 옵션은 풋옵션(Put Option)이라고 한다.&lt;/p&gt;
&lt;p&gt;만약 필자가 상인에게 구매한 옵션이 콜옵션이 아니라, 옥수수를 600원에 팔 수 있는 권리인 풋옵션이었다면, 현재 옥수수의 가격이 100원으로 떨어져도 그대로 600원에 팔 수 있으니, 이 경우에는 옥수수의 가격이 한달 동안 많이 떨어질 수록 큰 차익을 얻게 된다. &lt;small&gt;(그래서 콜옵션은 상승 배팅, 풋옵션은 하락 배팅이라고 하는 것이다)&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/65f5c9330f73b05984b596d7b5354bbe/9cac8/put-option.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 33.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABFUlEQVR42mNgQAWMQCzEEBrK/P//f0YGKgA2GQs3IY/ciezIgmDDybRASNsqQDl34hEwzp58Urhw1TFOUl3LBcQgF3H+r//PJCMjw1kY2suZVb+Kp6jnoGxRz261/P696jndBxUzp20RrK/fz/EfGDT/Gf6D8f79+1lWrVrFjGygChDLArHyRKBXvb2jBGNiirnPzDzDOjNtJitIrL5+MV9l6zZRsOGde9XzuvbolXdskquv3yTSW9jLubBinfBSIHsK0BHorhUAYlF83gF5f9X//8y5Ew+JFs85Kp8+/bxCS8tOg+X1u9UW1e8UQ49hNiDmA2JuUBBAMRcES3JJSkpyQcU4gJgViJlVzDz4rKz8eKF6GAA3A2GQZ1XiaQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;put option&quot; title=&quot;&quot; src=&quot;/static/65f5c9330f73b05984b596d7b5354bbe/6af66/put-option.png&quot; srcset=&quot;/static/65f5c9330f73b05984b596d7b5354bbe/69538/put-option.png 160w,
/static/65f5c9330f73b05984b596d7b5354bbe/72799/put-option.png 320w,
/static/65f5c9330f73b05984b596d7b5354bbe/6af66/put-option.png 640w,
/static/65f5c9330f73b05984b596d7b5354bbe/d9199/put-option.png 960w,
/static/65f5c9330f73b05984b596d7b5354bbe/21b4d/put-option.png 1280w,
/static/65f5c9330f73b05984b596d7b5354bbe/9cac8/put-option.png 2288w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    옥수수 가격이 아무리 떨어져도 풋옵션을 행사하면&lt;br&gt;
    무조건 300원에 팔 수 있으니 옥수수 가격이 떨어질수록 이득이다
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;결국 옵션이라는 것은 미래에 기초자산의 가격이 오를지 떨어질지를 고려해서 미리 “나중에 이 가격에 거래할거야!”라고 정해놓는 것이라고 생각할 수 있다.&lt;/p&gt;
&lt;p&gt;그럼 내가 옥수수를 600원에 살 수 있는 콜옵션을 보유하고 있는데, 막상 한 달 뒤의 옥수수의 가격이 그대로 500원이거나 오히려 500원보다 더 떨어진다면 어떻게 해야할까? 이러면 굳이 옵션을 행사해봤자 얻는 이득이 없지 않은가?&lt;/p&gt;
&lt;p&gt;그렇다면 그냥 살 수 있는 권리나 팔 수 있는 권리를 포기하면 된다. 이렇게 권리를 행사하거나 포기할 수 있는 상품이기 때문에 옵션(Option)이라고 부르는 것이다. 이렇게 옵션 행사를 포기하는 경우 옵션 구매자는 옵션을 구매할 때 지불했던 옵션 자체의 가격에 한해서만 손해를 보게 된다.&lt;/p&gt;
&lt;h3 id=&quot;일상-속의-옵션-아파트-분양권-거래&quot; style=&quot;position:relative;&quot;&gt;일상 속의 옵션, 아파트 분양권 거래&lt;a href=&quot;#%EC%9D%BC%EC%83%81-%EC%86%8D%EC%9D%98-%EC%98%B5%EC%85%98-%EC%95%84%ED%8C%8C%ED%8A%B8-%EB%B6%84%EC%96%91%EA%B6%8C-%EA%B1%B0%EB%9E%98&quot; aria-label=&quot;일상 속의 옵션 아파트 분양권 거래 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;옵션의 대표적인 예로는 바로 아파트 분양권 거래가 있다. 아파트 청약에 성공하면 아파트 분양권을 취득할 수 있는데, 이때 분양가는 매매가보다 훨씬 싼 경우가 일반적이다.&lt;/p&gt;
&lt;p&gt;하지만 결국 3억에 아파트를 분양받을 수 있는 분양권을 들고 있다는 의미는 현재 나에게 3억이라는 돈이 있어야 분양권을 쓸 수 있다는 의미이기 때문에, 이 돈을 마련하기 어렵거나 혹은 굳이 분양을 받을 의사가 없는 경우 사람들은 이 분양권을 다른 사람에게 팔기도 한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 604px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7b2452ff1dcab002720732bbd4d3b4f3/efa6e/option.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 136.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHskUaCBXlRYg//xAAaEAABBQEAAAAAAAAAAAAAAAAAAQIQETFB/9oACAEBAAEFArnHCF3Kbw//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAXEAEAAwAAAAAAAAAAAAAAAAAQASAx/9oACAEBAAY/ArYy/wD/xAAaEAADAQEBAQAAAAAAAAAAAAAAAREhUWEQ/9oACAEBAAE/IVSbdxie+lfR6Qje6JgqRCwopdefP//aAAwDAQACAAMAAAAQIwkA/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHRABAAICAwEBAAAAAAAAAAAAAQARMVEhQYGx4f/aAAgBAQABPxBUqEsmIB2IfohGXPYJEh1bEPUNQFbJe2OC2iO8IYzz9lt+0AM//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;option&quot; title=&quot;&quot; src=&quot;/static/7b2452ff1dcab002720732bbd4d3b4f3/efa6e/option.jpg&quot; srcset=&quot;/static/7b2452ff1dcab002720732bbd4d3b4f3/0913d/option.jpg 160w,
/static/7b2452ff1dcab002720732bbd4d3b4f3/cb69c/option.jpg 320w,
/static/7b2452ff1dcab002720732bbd4d3b4f3/efa6e/option.jpg 604w&quot; sizes=&quot;(max-width: 604px) 100vw, 604px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;분양권 거래는 아파트 자체를 사고 파는 것이 아니라, 아파트를 살 수 있는 권리를 사고 파는 것이다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;즉, 아파트 분양권은 “n월 n일까지 3억에 아파트를 분양받을 수 있는 권리”를 담고 있는 계약이기 때문에, 분양권 매매를 하는 사람들은 아파트라는 기초 자산이 아니라 이 “아파트를 살 수 있는 권리”를 사고 팔고 있는 것이다. 이것이 바로 옵션이다.&lt;/p&gt;
&lt;h3 id=&quot;번외-옵션option과-선물future의-차이는-무엇일까&quot; style=&quot;position:relative;&quot;&gt;번외: 옵션(Option)과 선물(Future)의 차이는 무엇일까?&lt;a href=&quot;#%EB%B2%88%EC%99%B8-%EC%98%B5%EC%85%98option%EA%B3%BC-%EC%84%A0%EB%AC%BCfuture%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C&quot; aria-label=&quot;번외 옵션option과 선물future의 차이는 무엇일까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;번외로 많은 분들이 선물(Future)과 옵션(Option)에 대해서 헷갈려 하시는 경우가 있어서 그냥 토막 상식 차원으로 조금 더 설명을 해보려고 한다.&lt;/p&gt;
&lt;p&gt;이 두 상품이 헷갈리는 이유는 두 상품 모두 미래의 어떤 시점에 기초자산의 가격이 오를지 떨어질지를 예측해서 현재 거래를 하는 상품이기 때문인데, 쉽게 말하자면 선물이 더 큰 개념이고, 옵션은 선물의 종류 중 하나라고 보면 된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;선물(Future)은 미래의 거래를 현재 시점으로 땡겨와서 하는 것&lt;/strong&gt;이다. 즉, 옥수수 선물 거래라면 “한 달뒤에 내가 600원에 옥수수를 거래할거임! 도장 쾅쾅”이라는 계약을 하는 것이기 때문에 선물 계약 만기일이 되면 그대로 결제가 진행되고 거래가 이행된다.&lt;/p&gt;
&lt;p&gt;말 그대로 미래의 거래에 대해서 지금 미리 계약을 해놓는 것이므로 선물 거래에는 옵션처럼 권리를 행사하거나 포기할 수 있는 선택권이 없는 것이다.&lt;/p&gt;
&lt;p&gt;이때 옵션과 마찬가지로 미래에 옥수수 가격이 1000원으로 오른다면, 옥수수를 선물 거래로 산 사람은 400원의 차익을 얻는 것이고 만약 옥수수의 가격이 300원으로 떨어진다면 옥수수를 선물 거래로 600원에 팔았던 사람이 300원의 차익을 얻는 원리이다. &lt;small&gt;(선물 거래는 산 사람과 판 사람, 둘 중에 한 명은 반드시 손해를 보는 제로썸 게임이다)&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5ae794732187196080a4074fd043ebe6/41099/future.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 63.74999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABw7mRFiQv/8QAGhAAAwEAAwAAAAAAAAAAAAAAAAECEQMSIf/aAAgBAQABBQJLSpfUmsXJ4M//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAwADAAAAAAAAAAAAAAAAAAEQESFx/9oACAEBAAY/AjcSwdn/xAAbEAADAAIDAAAAAAAAAAAAAAAAAREhMVFhcf/aAAgBAQABPyFzQQfgXC8JqkTNU7Gx/9oADAMBAAIAAwAAABDT3//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxAEO3//xAAWEQEBAQAAAAAAAAAAAAAAAAABEQD/2gAIAQIBAT8Qjck3/8QAHBABAQACAgMAAAAAAAAAAAAAAREAITFBYYGR/9oACAEBAAE/EDQvMWWYmABho3h8TF3hWiXXeQJSvXxkNAGuDP/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;future&quot; title=&quot;&quot; src=&quot;/static/5ae794732187196080a4074fd043ebe6/41099/future.jpg&quot; srcset=&quot;/static/5ae794732187196080a4074fd043ebe6/0913d/future.jpg 160w,
/static/5ae794732187196080a4074fd043ebe6/cb69c/future.jpg 320w,
/static/5ae794732187196080a4074fd043ebe6/41099/future.jpg 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;오징어게임의 조상우가 60억 날려먹은 그 선물이 이거다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;하지만 선물 거래를 하는 대부분의 사람들은 진짜로 기초자산을 사고 싶어서 선물 거래를 한 것이 아니라 단지 가격 변동성으로 인해 발생하는 차익을 먹고 싶은 것 뿐이므로, 계약 만기가 되어 실제로 상품 대금이 결제되고 배송되기 전에 진짜로 이 기초자산을 싼 값에 사고 싶어하는 사람에게 선물 계약을 팔아버리고, 다음 달이 만기인 선물 계약으로 다시 갈아타는 &lt;a href=&quot;https://survivalinvestment.tistory.com/35&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;롤오버(Roll Over)&lt;/a&gt;를 한다.&lt;/p&gt;
&lt;h4 id=&quot;2020년-3월-코로나가-만든-충격의-마이너스-유가의-추억&quot; style=&quot;position:relative;&quot;&gt;2020년 3월 코로나가 만든 충격의 마이너스 유가의 추억&lt;a href=&quot;#2020%EB%85%84-3%EC%9B%94-%EC%BD%94%EB%A1%9C%EB%82%98%EA%B0%80-%EB%A7%8C%EB%93%A0-%EC%B6%A9%EA%B2%A9%EC%9D%98-%EB%A7%88%EC%9D%B4%EB%84%88%EC%8A%A4-%EC%9C%A0%EA%B0%80%EC%9D%98-%EC%B6%94%EC%96%B5&quot; aria-label=&quot;2020년 3월 코로나가 만든 충격의 마이너스 유가의 추억 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;그렇다면 만약 선물 만기가 거의 다 되었는데, 기초자산을 싼 값에 사고 싶은 사람이 아무도 없어서 이번 달 선물 계약을 롤오버 하지 못 했다면 어떻게 되는 걸까?&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3e32591136ab104e94bd94d2dee99f11/72e01/container_ship.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 73.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMFAf/EABUBAQEAAAAAAAAAAAAAAAAAAAID/9oADAMBAAIQAxAAAAF2T1o0SaOf/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECEhMh/9oACAEBAAEFAnaNGx0dBV5//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAS/9oACAEDAQE/ATLP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAh/9oACAECAQE/AaF//8QAGBAAAgMAAAAAAAAAAAAAAAAAARAgITL/2gAIAQEABj8CqGiv/8QAGxABAAEFAQAAAAAAAAAAAAAAAQAQESFhgTH/2gAIAQEAAT8hurBxuPRR1jZkF2DML2f/2gAMAwEAAgADAAAAEI/f/8QAFxEBAAMAAAAAAAAAAAAAAAAAAQARIf/aAAgBAwEBPxCjuMWmf//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAgEBPxBYMv/EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQXFRobH/2gAIAQEAAT8QRQkW3ZeiMFnYRHmLi8DhjpBtfRx7itDpt5n/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;container ship&quot; title=&quot;&quot; src=&quot;/static/3e32591136ab104e94bd94d2dee99f11/c08c5/container_ship.jpg&quot; srcset=&quot;/static/3e32591136ab104e94bd94d2dee99f11/0913d/container_ship.jpg 160w,
/static/3e32591136ab104e94bd94d2dee99f11/cb69c/container_ship.jpg 320w,
/static/3e32591136ab104e94bd94d2dee99f11/c08c5/container_ship.jpg 640w,
/static/3e32591136ab104e94bd94d2dee99f11/6a068/container_ship.jpg 960w,
/static/3e32591136ab104e94bd94d2dee99f11/72e01/container_ship.jpg 1024w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;에반님 저번 달에 계약해놓으신 원유 10만 배럴 배달왔어요 뿌우~&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;선물 계약 만기일이 되면 실제로 나한테 기초자산인 상품의 소유권이 넘어오게 되는데, 이게 주식 같은 자산이면 크게 문제가 되지 않을 수 있겠지만 만약 원유나 옥수수같은 현물을 기초자산으로 하는 선물 계약이라면 만기가 되는 순간 실제로 미국 어딘가의 이름 모를 항구로 실제로 &lt;strong&gt;이 물건이 내 이름을 달고 배송되는 대참사&lt;/strong&gt;가 발생한다. &lt;small&gt;(이래서 선물에 대해서 제대로 모르고 건드리면 진짜 큰일난다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;작년인 2020년 3월 코로나가 처음 터졌을 때 원유 선물 가격이 -37달러까지 떨어진 것도 이런 선물 계약의 특성 때문이다. 참고로 이렇게 가격이 마이너스라는 소리는 선물 계약을 팔기 위해서 오히려 내가 돈을 얹어줘야 한다는 뜻이다. 필자 기억으로는 이때 즈음에 WHO에서 팬데믹 선언을 했던 것 같은데, 이 당시 시장의 분위기는 이랬다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;헐 팬데믹이라고? 사람들의 소비가 줄겠네? 👉 소비가 줄었으니 물건들의 공급량도 줄겠네? 👉 어 그러면…물건 만들고 배송할 때 쓰는 원유도 당분간 별로 안 쓰겠네…?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 300px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/15ec7/mang.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 121.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAYABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAMEBQH/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAG7Ja4Yq8NGMMkH/8QAHBAAAgICAwAAAAAAAAAAAAAAAQMAEgIQESEz/9oACAEBAAEFAlKsGIFZiKY9ThWhGen/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAbEAABBQEBAAAAAAAAAAAAAAAAAhAREiExcf/aAAgBAQAGPwKVcJS1TDat4KP/xAAdEAACAwACAwAAAAAAAAAAAAABEQAhMRBRQWFx/9oACAEBAAE/IRgc3uMjpWnwMDUMJhcK3jJ1xP0cYQF4i1dz/9oADAMBAAIAAwAAABATDzz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAgEAEAAgIBBAMAAAAAAAAAAAABABEhQTEQUWFxgaGx/9oACAEBAAE/ED6VlBQo7waJDJYTowbDWwS2ASJrgcNeIAGGYKPx9x4gRINjY5qE16M/nf3P/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;mang&quot; title=&quot;&quot; src=&quot;/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/c08c5/mang.jpg&quot; srcset=&quot;/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/0913d/mang.jpg 160w,
/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/cb69c/mang.jpg 320w,
/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/c08c5/mang.jpg 640w,
/static/0ce6a4f4f89b2f1a8f2c5f4a548030af/15ec7/mang.jpg 690w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;&quot;빨리 선물 계약 다 던져야겠다...&quot;&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;이렇게 원유에 대한 수요 자체가 줄어버리면 자연스럽게 원유 가격이 떨어지게 되는데, 이 당시 러시아랑 사우디아라비아가 서로 원유 가격 전쟁을 한답시고 원유 생산량을 늘려버려서 원유 현물 가격 자체가 말 그대로 대떡락했었다.&lt;/p&gt;
&lt;p&gt;문제는 대떡락 하기 전에 사놓은 선물 계약들은 원유 대떡락 이전의 가격인 20달러 언저리의 가격을 가지고 있었다는 것이다. 미래에 원유 현물 가격이 더 올라줘야 이 선물 계약을 사용해서 원유를 살 때 얻는 이득이 있는데, 원유 가격이 떡락할 수 밖에 없는 상황들이 다 겹쳐버리니까 아무도 이 선물 계약들을 사주지 않았다. 이러면 굳이 선물 계약을 사서 원유를 구매하는 것보다 그냥 현재 가격으로 구매하는 것이 훨씬 싸기 때문이다.&lt;/p&gt;
&lt;p&gt;즉, 선물 계약을 사줄 사람은 없는데 파는 사람은 넘쳐나는 눈물나는 시장 상황이 발생해버렸다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1335a33be53bfd1691c01d192a5e32cc/6aca1/oil-future.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB5LbEcqWf/8QAFxABAQEBAAAAAAAAAAAAAAAAAQIQEv/aAAgBAQABBQKFa6ygwgT/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwFX/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BR//EABcQAAMBAAAAAAAAAAAAAAAAAAAQMRH/2gAIAQEABj8Cwij/AP/EABgQAQEBAQEAAAAAAAAAAAAAAAEAERBR/9oACAEBAAE/IR+pCeJgaAMOE1W//9oADAMBAAIAAwAAABDg7//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxCxh//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCNP//EABoQAQEBAQEBAQAAAAAAAAAAAAERACExYfD/2gAIAQEAAT8QAA8bYcC6KRx+7ppCCeXG9YBDuuscScfu/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;oil future&quot; title=&quot;&quot; src=&quot;/static/1335a33be53bfd1691c01d192a5e32cc/c08c5/oil-future.jpg&quot; srcset=&quot;/static/1335a33be53bfd1691c01d192a5e32cc/0913d/oil-future.jpg 160w,
/static/1335a33be53bfd1691c01d192a5e32cc/cb69c/oil-future.jpg 320w,
/static/1335a33be53bfd1691c01d192a5e32cc/c08c5/oil-future.jpg 640w,
/static/1335a33be53bfd1691c01d192a5e32cc/6aca1/oil-future.jpg 650w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;이게 바로 &quot;37.63달러 드릴테니까 제발 누가 제 계약 좀 사주세요...&quot;라는 상황이다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이렇게 선물 계약은 안 팔리는데 점점 계약 만기일이 다가오자, 실제로 원유가 배송될 것에 패닉이 온 선물 투자자들이 오히려 계약 당 37달러를 얹어주면서까지 선물 계약을 던져버리는 상황으로 이어진 것이다. &lt;small&gt;&lt;del&gt;(패닉셀의 끝판왕은 싸게 파는 것이 아니라 돈을 주고 파는 것이었…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이것이 바로 옵션과 다른 선물의 특성인, “만기가 되면 거래를 무를 수 없다”로 인해 발생하는 무서운 상황이다.&lt;/p&gt;
&lt;p&gt;반면 &lt;strong&gt;옵션(Option)은 미래에 거래할 수 있는 권리를 사고 파는 것&lt;/strong&gt;이다. 즉, 선물의 일종이기는 하지만 “물건을 거래하겠다”라는 계약을 하는 것이 아니라 “물건을 거래할 수 있는 권리”만을 계약했으므로, 만기 시점에 권리를 행사하거나 행사하지 않는 선택권이 생기는 것이다. 쉽게 말해서 옵션은 일반 선물 거래에 비해서 최종 결정을 할 수 있는 기회가 1번 더 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;상품&lt;/th&gt;
&lt;th&gt;주고받는 것&lt;/th&gt;
&lt;th&gt;만기가 되면?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;선물(Future)&lt;/td&gt;
&lt;td&gt;기초자산 거래 계약&lt;/td&gt;
&lt;td&gt;아묻따 거래가 이행된다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;옵션(Option)&lt;/td&gt;
&lt;td&gt;기초자산을 거래할 수 있는 권리에 대한 계약&lt;/td&gt;
&lt;td&gt;권리를 행사할 수도 있고 안 할수도 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;또한 선물은 만기 시점에 거래를 무조건 이행해야하기 때문에 둘 중에 한 명은 무조건 이득을 보고 한 명은 손해를 보는 제로섬 게임이지만, 옵션은 옵션을 구매한 사람이 권리 행사를 포기해버릴 수 있기 때문에, 이 경우 옵션을 판매한 사람은 손해만 보는 장사를 하게 된다.&lt;/p&gt;
&lt;p&gt;그래서 옵션 거래를 할 때는 옵션을 사는 사람이 옵션을 파는 사람에게 옵션 자체가 가진 가격을 따로 지불해야하고, 이 옵션의 가격은 &lt;a href=&quot;https://namu.wiki/w/%EB%B8%94%EB%9E%99-%EC%88%84%EC%A6%88%20%EB%AA%A8%ED%98%95&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;블랙 앤 숄츠 방정식&lt;/a&gt;과 같은 방법을 통해 계산하게 된다.&lt;/p&gt;
&lt;h2 id=&quot;주식을-구매할-수-있는-권리-스톡옵션stock-option&quot; style=&quot;position:relative;&quot;&gt;주식을 구매할 수 있는 권리, 스톡옵션(Stock Option)&lt;a href=&quot;#%EC%A3%BC%EC%8B%9D%EC%9D%84-%EA%B5%AC%EB%A7%A4%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B6%8C%EB%A6%AC-%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98stock-option&quot; aria-label=&quot;주식을 구매할 수 있는 권리 스톡옵션stock option permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자 이제 옵션이 무엇인지 알았으니 스톡옵션에 대한 설명도 쉬워졌다. 스톡옵션은 말 그대로 스톡옵션은 주식(Stock)을 기초자산으로 하는 옵션(Option)이므로, 주식을 만기 시점에 특정한 가격으로 사고 팔 수 있는 권리를 가진 계약을 의미하는 것이다.&lt;/p&gt;
&lt;p&gt;다만 우리가 일반적으로 접하는 인센티브 스톡옵션은 애초에 주식이 없는 상태에서 추가적인 인센티브를 주는 것이니, 주식을 사고 팔 수 있는 권리가 아니라 주식을 살 수 있는 권리만을 의미한다. 그래서 스톡옵션을 한국말로는 “주식매수선택권”이라고 한다.&lt;/p&gt;
&lt;p&gt;결국 여러분이 스톡옵션을 받는 것은 주식을 받는 것이 아니라, “주식을 매수할 수 있는 권리”를 받는 것이고, 이 “스톡옵션을 사용해서 주식을 살게!”라는 행위는 내가 가지고 있는 주식을 살 권리를 행사해서 주식을 매수하는 것이므로, “스톡옵션을 행사한다”라고 하는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;스톡옵션의-부여grant&quot; style=&quot;position:relative;&quot;&gt;스톡옵션의 부여(Grant)&lt;a href=&quot;#%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98%EC%9D%98-%EB%B6%80%EC%97%ACgrant&quot; aria-label=&quot;스톡옵션의 부여grant permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;만약 우리가 어떤 회사에 입사를 할 때 스톡옵션을 부여받는다면, 근로계약서를 쓰는 입사 첫날에 스톡옵션을 받을 수 있는 것일까?&lt;/p&gt;
&lt;p&gt;아니다. 스톡옵션은 딸랑 계약서 한 장 쓴다고 줄 수 있는 것이 아니기 때문이다. 주식회사에서 누군가에게 스톡옵션을 부여하기 위해서는 반드시 주주총회를 열고 이 사람에게 스톡옵션을 부여하겠다는 승인 절차를 거쳐야한다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 78.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABumprSpigf//EABoQAAIDAQEAAAAAAAAAAAAAAAACAQMTBBL/2gAIAQEAAQUCzQwgzrF71gZva2dC1v8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAgEFAQAAAAAAAAAAAAAAAAECETEyQZEi/9oACAEBAAY/AsFwwiWXDBnmSVdjhem0f//EABwQAQEBAAEFAAAAAAAAAAAAAAERABAhMVGhsf/aAAgBAQABPyEZhkj8ocfbfRNKZDs6zQw+YI7/2gAMAwEAAgADAAAAEGjf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EFtL/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Qh//EABwQAQADAQADAQAAAAAAAAAAAAEAESExUWGR0f/aAAgBAQABPxAAmvAP5Ddtq0Mk518cfn0UCnh2BrQhBaY9ORaLqWmE/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;meeting&quot; title=&quot;&quot; src=&quot;/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg&quot; srcset=&quot;/static/783da1105578e0f9950fffb6d49bf961/0913d/meeting.jpg 160w,
/static/783da1105578e0f9950fffb6d49bf961/cb69c/meeting.jpg 320w,
/static/783da1105578e0f9950fffb6d49bf961/c08c5/meeting.jpg 640w,
/static/783da1105578e0f9950fffb6d49bf961/6a068/meeting.jpg 960w,
/static/783da1105578e0f9950fffb6d49bf961/eea4a/meeting.jpg 1280w,
/static/783da1105578e0f9950fffb6d49bf961/d6e5c/meeting.jpg 1685w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;주식회사는 주주총회의 승인이 있어야만 특정인에게 스톡옵션을 부여할 수 있다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;주주총회에서 스톡옵션의 부여와 권리 행사 시 발행하거나 양도할 주식에 대해서 결의를 하고 승인이 나면, 그 이후에 부여 대상자와 스톡옵션 부여 계약을 체결하는 것이다.&lt;/p&gt;
&lt;p&gt;주주총회야 회사에서 알아서 해주는 건데 이걸 왜 우리가 알아야 할까? 바로 여러분의 스톡옵션 부여일이 주주총회가 얼마나 자주 열리느냐에 따라 달라질 수 있기 때문이다. 만약 2021년 1월에 입사했더라도 주주총회가 그 해 12월에 열린다면, 여러분의 스톡옵션 부여일은 그 이후가 될 수 있다.&lt;/p&gt;
&lt;p&gt;그리고 여러분이 스톡옵션을 언제 얼마나 행사해서 얼마 만큼의 주식을 살 수 있냐에 대한 기준은 여러분의 입사일이 아니라 이 주주총회에서 정한 &lt;strong&gt;스톡옵션 부여일&lt;/strong&gt;을 기준으로 계산되기 때문에, 우리 회사에 주주총회가 언제 열리는지 알고 있어야 내 스톡옵션 부여일이 대충 언제쯤일지 계산해볼 수 있다.&lt;/p&gt;
&lt;p&gt;자 어쨌든 이렇게 주주총회에서 여러분에게 스톡옵션을 부여하겠다는 승인이 나면 이제 스톡옵션 계약서를 쓰게 된다. 이 계약서에는 대충 다음과 같은 정보들이 들어가있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;받을 주식 수&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;스톡옵션 부여 방법과 부여일&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;스톡옵션의 행사 가격&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;클리프, 베스팅 기간&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;스톡옵션 행사 방법&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 모든 내용이 중요하기는 하지만, 이 계약서를 받았을 때 우리가 가장 눈여겨 보아야 할 부분들은 스톡옵션의 &lt;strong&gt;행사가&lt;/strong&gt;와 &lt;strong&gt;클리프&lt;/strong&gt;, 그리고 &lt;strong&gt;베스팅&lt;/strong&gt;이다.&lt;/p&gt;
&lt;h3 id=&quot;행사가strike-price&quot; style=&quot;position:relative;&quot;&gt;행사가(Strike Price)&lt;a href=&quot;#%ED%96%89%EC%82%AC%EA%B0%80strike-price&quot; aria-label=&quot;행사가strike price permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;앞서 필자는 스톡옵션이 특정한 시점에 미리 정해놓은 가격으로 주식을 살 수 있는 권리라고 이야기했다. 이때 “미리 정해놓은 가격”을 &lt;strong&gt;행사가&lt;/strong&gt;라고 부른다.&lt;/p&gt;
&lt;p&gt;즉, 말 그대로 스톡옵션을 사용해서 주식을 살 때 내야하는 돈이다. 만약 스톡옵션이 주식이라고만 생각했다면 스톡옵션을 행사할 때 갑자기 회사에서 돈을 내라고 하는 당황스러운 경험을 하게 될 수도 있다.&lt;/p&gt;
&lt;p&gt;스톡옵션은 말 그대로 주식을 공짜로 주는 게 아니라 “주식을 살 수 있는 권리”를 주는 것이기 때문에 당연히 돈을 내야 한다. 이때 행사가는 &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%83%81%EB%B2%95/%EC%A0%9C340%EC%A1%B0%EC%9D%982&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;상법 제340조의2&lt;/a&gt;에 따라 회사의 첫 자본금을 발행 주식의 수로 나눈 가격인 액면가와 현재 주식의 시장가 중 높은 가격으로 정해야한다.&lt;/p&gt;
&lt;p&gt;다만, &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EB%B2%A4%EC%B2%98%EA%B8%B0%EC%97%85%EC%9C%A1%EC%84%B1%EC%97%90%EA%B4%80%ED%95%9C%ED%8A%B9%EB%B3%84%EC%A1%B0%EC%B9%98%EB%B2%95%EC%8B%9C%ED%96%89%EB%A0%B9/%EC%A0%9C11%EC%A1%B0%EC%9D%983&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;벤처 특례&lt;/a&gt;를 적용받는 기업의 경우 몇 가지 조건을 충족하면 시장가보다 낮은 가격으로 행사가를 책정할 수 있는데, 스타트업은 벤처 특례를 적용받는 경우가 대부분이므로 행사가를 시장가보다 낮게 책정하는 경우가 많다. &lt;small&gt;(카카오 같은 경우가 벤처 특례 적용을 받지 못 했기 때문에 부여 시점의 시장가로 행사가를 정했던 대표적인 케이스이다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;우리가 스톡옵션으로 얻을 수 있는 실질적인 세전 수익은 &lt;code class=&quot;language-text&quot;&gt;(시장가 - 행사가) * 주식수&lt;/code&gt;으로 정해지기도 하고, 스톡옵션 행사를 하기 위해서는 미리 행사가를 납부하기위한 현금을 마련해둬야 할 수도 있기 때문에, 내가 가진 스톡옵션의 행사가가 얼마인지는 반드시 알고 있어야 한다.&lt;/p&gt;
&lt;h3 id=&quot;베스팅vesting&quot; style=&quot;position:relative;&quot;&gt;베스팅(Vesting)&lt;a href=&quot;#%EB%B2%A0%EC%8A%A4%ED%8C%85vesting&quot; aria-label=&quot;베스팅vesting permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;이미 알고 계신 분들이 많겠지만, 스톡옵션은 부여받았다고 해서 바로 행사할 수 있는 것이 아니다.&lt;/p&gt;
&lt;p&gt;대한민국 같은 경우는 &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%83%81%EB%B2%95/(20190916,14096,20160322)/%EC%A0%9C340%EC%A1%B0%EC%9D%984&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;상법 제340조의4&lt;/a&gt;에 최소 “주주총회 결의일로부터 2년 이상 재임 또는 재직”하여야 스톡옵션을 행사할 수 있다고 명시되어있다. 하지만 주주총회 결의일보다 부여일을 기준으로 2년을 세는 경우가 일반적이기는 하다. &lt;small&gt;(어차피 주총 결의일보다 부여일이 미래일수밖에 없으므로 법적으로도 아무 문제가 없다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이런 조건이 없을 경우, 직원이 스톡옵션을 부여받자마자 행사해서 주식을 전부 구매하고 퇴사해버리는, 이른바 먹튀를 해도 회사에서는 아무런 제재를 가할 수 없기 때문에 최소한의 방어책을 펴놓은 것이다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 보통 스톡옵션 계약서에는 &lt;strong&gt;부여일로부터 24개월 이상 재직한 경우 n% 행사가능&lt;/strong&gt;이라는 말이 꼭 들어가있다.&lt;/p&gt;
&lt;p&gt;이때 24개월 후에 몇 %를 행사할 수 있는지는 그 회사의 베스팅 플랜에 따라 달라지게 되는데, 보통 초기 스타트업의 경우에는 부여일로부터 2년 후에 100% 전량을 행사할 수 있게 해주는 경우도 있지만, 어느 정도 덩치가 커진 기업들은 보통 “2년 후에 50%, 3년 째에 25%, 4년 째에 25%“와 같이 행사 가능한 스톡옵션의 수를 나눠놓기도 한다.&lt;/p&gt;
&lt;p&gt;여기서 헷갈리면 안되는 것은 이 기간들이 지나면 내가 받은 스톡옵션이 행사 불가능한 상태에서 행사 가능한 상태로 전환되는 것이지, 이때 스톡옵션을 부여하는 것이나 행사하고 주식을 받는 것이 아니라는 것이다. 그리고 이렇게 내가 받은 스톡옵션이 “행사 불가능한 상태에서 행사 가능한 상태로 전환되는 것”을 **베스팅(Vesting)**이라고 한다.&lt;/p&gt;
&lt;p&gt;그리고 우리가 스톡옵션을 부여받은 이후 행사할 수 있게 되기까지 걸리는 첫 순간을 **클리프(Cliff)**라고 한다. 클리프는 직역하면 절벽이라는 뜻인데, 이 기간이 되면 행사할 수 있는 스톡옵션의 양이 0이었다가 갑자기 증가하기 때문에, 행사 가능 수량을 그래프로 그려보면 절벽처럼 보인다고 해서 이렇게 부르는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/830230ebe0f0489c89ca66d73e19a1a9/2adcb/cliff.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 46.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABKElEQVR42mNggABmIBYHYmkgZmdAA/8Z/jMykAi4gJgDivGC/wwMjHAcGsr8v76eCZs6TiQMA2BXrSpfxb+8aYvm/Pr9HMiGgun6fIH/lbmiyGLILuTC5sL9QIMWt2yXBNIsIP7LrHiJZ1lZ8o9TUmSe5+QoPi8u5sbmQlZo2GH18triRWIgjf9nprH+yEtXPRYaynklNJTtTFoaK66g4cPmQpg3HuXl6bzIzFR6k5si8yIvWZzYiGFBC0O4ge/S0uSAgc9Cakwzx+jpcf8HegPkHZABtzw82EEx+T4nRXEbkA1Uw1QPxAwIzAjFIMvYoDQEcHNzi9dYWhr+y82VuR4fr7A1IEDtK5D9LClJvsfeXgOkBOoDUWgQgYJHGIj5gVgAiOWAWAgAQQdW2jCQZooAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cliff&quot; title=&quot;&quot; src=&quot;/static/830230ebe0f0489c89ca66d73e19a1a9/6af66/cliff.png&quot; srcset=&quot;/static/830230ebe0f0489c89ca66d73e19a1a9/69538/cliff.png 160w,
/static/830230ebe0f0489c89ca66d73e19a1a9/72799/cliff.png 320w,
/static/830230ebe0f0489c89ca66d73e19a1a9/6af66/cliff.png 640w,
/static/830230ebe0f0489c89ca66d73e19a1a9/d9199/cliff.png 960w,
/static/830230ebe0f0489c89ca66d73e19a1a9/21b4d/cliff.png 1280w,
/static/830230ebe0f0489c89ca66d73e19a1a9/2adcb/cliff.png 1984w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;부여일로부터 2년 째 되는 날 행사가능한 스톡옵션의 수가 급증하는 구간이 생긴다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;위 그래프는 전체 베스팅 기간은 4년, 클리프는 2년짜리 베스팅 플랜을 보여주고 있다.&lt;/p&gt;
&lt;p&gt;만약 필자가 이 회사에 입사하자마자 주주총회가 열려서 스톡옵션 100주를 부여받았다고 상상해보면 대략 다음과 같은 과정을 거치게 된다.&lt;/p&gt;
&lt;p&gt;필자는 스톡옵션 100주를 가지고는 있지만 부여일로부터 첫 2년 동안은 행사할 수 없는 상태이다. 스톡옵션을 행사할 수 없다는 것은 “주식을 싸게 살 수 있는 권리”를 행사할 수 없다는 뜻이니, 첫 2년 동안은 그냥 스톡옵션을 들고만 있는 것이다. &lt;small&gt;&lt;del&gt;(하지만 이때부터 이미 회사 주가는 계속 트래킹하고 있…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그리고 부여일로부터 2년이 지났을 때, 필자는 필자가 가지고 있는 스톡옵션 100주의 50%인 50주에 대해서만 회사 주식을 행사가로 살 수 있는 권리가 생긴다. 물론 아직 베스팅 플랜이 끝나려면 멀었기 때문에, 이때 행사하고 말고는 필자의 마음이다. 밑에서 후술하겠지만 절세를 하기 위해서는 한번에 행사하는 것보다 나눠서 행사하는 것이 유리하므로, 이때 행사하는 것도 나쁜 선택지는 아니다.&lt;/p&gt;
&lt;p&gt;3년이 지났을 때는 나머지 50%의 절반인 25%에 대해서 행사 권리가 생긴다. 즉, 이때 필자는 받았던 전체 스톡옵션 100주 중 75%인 75주를 행사할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;마지막으로 4년이 되면 필자가 받았던 모든 스톡옵션에 대해서 행사 권리가 생기고 베스팅 기간이 끝난다. 이렇게 2년 클리프에 &lt;code class=&quot;language-text&quot;&gt;50%/25%/25%&lt;/code&gt; 형태의 베스팅 플랜은 굉장히 일반적인 플랜인데, 경우에 따라서 2년 클리프 이후에는 매달 베스팅해주는 등 다양한 베스팅 플랜이 존재할 수도 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🧐  스톡옵션을 1년 클리프 시켜준다는 곳도 있던데요?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;앞서 이야기한대로 최소 2년 클리프라는 규칙은 대한민국의 상법에 정해져있는 것이다.&lt;/p&gt;
&lt;p&gt;그래서 외국계 기업, 특히 미국 같이 클리프에 대한 별도의 법이 정해져있지 않은 국가의 기업들은 “1년 클리프, 그리고 그 후로는 매달 n빵으로 베스팅”과 같은 베스팅 플랜을 제시할 수도 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;스톡옵션을-행사해서-주식-매수하기&quot; style=&quot;position:relative;&quot;&gt;스톡옵션을 행사해서 주식 매수하기&lt;a href=&quot;#%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98%EC%9D%84-%ED%96%89%EC%82%AC%ED%95%B4%EC%84%9C-%EC%A3%BC%EC%8B%9D-%EB%A7%A4%EC%88%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;스톡옵션을 행사해서 주식 매수하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자 이제 내가 스톡옵션을 회사로부터 언제 어떻게 받고 언제 권리를 행사할 수 있는지도 알게 되었으니, 이제는 제일 중요한 “스톡옵션을 돈으로 바꿀 수 있는 과정”에 대한 이야기를 해보도록 하자.&lt;/p&gt;
&lt;p&gt;스톡옵션을 돈으로 바꾸는 과정의 가장 첫 번째는 바로 스톡옵션을 행사해서 주식을 매수하는 것인데, 앞서 여러 번 이야기 한 것처럼 스톡옵션을 행사한다는 것은 “이제 내가 가지고 있는 주식을 싸게 살 권리를 이용해서 주식을 사겠다”라고 하는 것과 동일하다.&lt;/p&gt;
&lt;p&gt;행사하는 방법은 보통 회사에게 서면 통보하는 식으로 진행되지만, 회사마다 자세한 방법이 조금 다를 수는 있으니 회사의 담당자에게 물어보거나 스톡옵션 계약서를 잘 읽어보도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;스톡옵션-행사가-납입하기&quot; style=&quot;position:relative;&quot;&gt;스톡옵션 행사가 납입하기&lt;a href=&quot;#%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98-%ED%96%89%EC%82%AC%EA%B0%80-%EB%82%A9%EC%9E%85%ED%95%98%EA%B8%B0&quot; aria-label=&quot;스톡옵션 행사가 납입하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;스톡옵션은 크게 신주발행형, 자기주식교부형, 차액정산형 3가지로 나누어지는데, 이때 내가 받은 스톡옵션이 어떤 종류이냐에 따라 행사가를 내냐 마냐가 달라진다.&lt;/p&gt;
&lt;p&gt;차액정산형 같은 경우는 내 스톡옵션의 행사가와 현재 우리 회사의 주식의 시장가 간의 차액을 현급으로 지급해주는 방식이기 때문에 별도의 행사가를 납입하지 않아도 되지만, 새로운 주식을 발행해서 넘겨주는 신주발행형과 회사가 이미 가지고 있는 주식을 나눠주는 자기주식교부형 같은 경우는 스톡옵션을 행사해서 주식을 구매하는 것이므로, 이 주식의 가격인 행사가를 회사에 납입해야한다.&lt;/p&gt;
&lt;p&gt;만약 스톡옵션이 그냥 주식이라고 생각하고 있었다면, 정작 스톡옵션이 베스팅되어도 수중에 행사가를 지불할 현금이 없어서 원하는 수량의 스톡옵션을 행사하지 못 하거나 심지어 급하게 대출을 하게 되는 상황이 발생할 수도 있으니, 항상 내 스톡옵션은 “주식을 구매할 수 있는 권리”라는 것을 유념하도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;소득이-생겼네-세금내셔야죠&quot; style=&quot;position:relative;&quot;&gt;소득이 생겼네? 세금내셔야죠!&lt;a href=&quot;#%EC%86%8C%EB%93%9D%EC%9D%B4-%EC%83%9D%EA%B2%BC%EB%84%A4-%EC%84%B8%EA%B8%88%EB%82%B4%EC%85%94%EC%95%BC%EC%A3%A0&quot; aria-label=&quot;소득이 생겼네 세금내셔야죠 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;스톡옵션에 대한 세금은 상황마다 조금씩 다를 수 있으므로 필자가 이야기한 내용이 100% 정확한 것은 아니다.&lt;/p&gt;
&lt;p&gt;대충 이런 식으로 계산된다는 것 정도만 알아두고, 정확한 내용은 스톡옵션을 행사할 때 회사에 물어보도록 하자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;사실 스톡옵션을 행사할 때 우리가 가장 잘 알고 있어야 하는 부분은 다름 아닌 &lt;strong&gt;세금&lt;/strong&gt;이다. 슬프게도 스톡옵션을 행사해서 받은 주식은 소득으로 잡히기 때문에, 당연히 이 소득에 대한 소득세를 내야한다. &lt;small&gt;&lt;del&gt;(왜 팔지도 않은 주식을 소득으로 잡는지는 모르겠지만…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2923ebd94179d5db9428479351befdbb/4a359/poor.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 71.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQT/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAYYtAuYUs//EABsQAAIDAAMAAAAAAAAAAAAAAAECAAMTERQi/9oACAEBAAEFAkrznPnriB9FUASxyH//xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAwEBPwGI/8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8Bqv/EABsQAQACAgMAAAAAAAAAAAAAAAEAERAhUXGR/9oACAEBAAY/Amj2KBd8Yt11hJ//xAAdEAEAAgICAwAAAAAAAAAAAAABABEhMUFRcZGh/9oACAEBAAE/IQwyPJl8ltI7FHq55XYhVp9mvsHlUT//2gAMAwEAAgADAAAAEKA//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERUf/aAAgBAwEBPxBMTZ//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxCH/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFBUWFx/9oACAEBAAE/EJOGKJ0cSmuXLrdixEXUOucFBQbYafMalTxmQ+3v8y0z2UYejF5ywZLrzP/Z&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;poor&quot; title=&quot;&quot; src=&quot;/static/2923ebd94179d5db9428479351befdbb/c08c5/poor.jpg&quot; srcset=&quot;/static/2923ebd94179d5db9428479351befdbb/0913d/poor.jpg 160w,
/static/2923ebd94179d5db9428479351befdbb/cb69c/poor.jpg 320w,
/static/2923ebd94179d5db9428479351befdbb/c08c5/poor.jpg 640w,
/static/2923ebd94179d5db9428479351befdbb/4a359/poor.jpg 719w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;연말정산이 끝난 후...&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이때 스톡옵션을 행사해서 얻는 소득은 &lt;code class=&quot;language-text&quot;&gt;(시장가 - 행사가) * 주식수&lt;/code&gt;로 계산되며, 내가 현재 그 회사에 다니고 있는 상태인지 아닌지, 행사하고 얻은 소득이 얼마인지, 우리 회사가 벤처기업인지 아닌지에 따라서 세금이 조금씩 달라지게 된다.&lt;/p&gt;
&lt;p&gt;다만 스타트업의 경우에는 비상장인데다가 주식 매매사례가 많지 않은 경우가 대부분이라 1주당 순자산가치 및 1주당 순손익가치를 기준으로 시장가를 계산하는 &lt;strong&gt;보충적 평가방법&lt;/strong&gt;을 사용하게 되는데, 다들 아시다시피 스타트업은 영업이익을 남기는 것이 목표가 아니라 그냥 돈을 활활 태워서 매출 Growth를 만드는 것이 목표인 경우가 많기 때문에 보충적 평가방법을 사용하여 시장가를 계산하면 오히려 행사가보다 낮게 나올 수도 있다.&lt;/p&gt;
&lt;p&gt;이렇게 시장가가 행사가보다 낮다는 것은 스톡옵션을 행사해서 주식을 취득하는 것이 오히려 손해라는 의미이기 때문에 이로 인한 소득도 마이너스로 잡히고, 소득세 또한 내지 않는다. &lt;small&gt;(이런 경우는 다음 투자 라운드 때 VC로부터 평가받을 밸류에이션이 높아지는 것을 기대하고 행사하는 것이다)&lt;/small&gt;&lt;/p&gt;
&lt;h4 id=&quot;내가-아직-회사에-다니고-있는-경우에는-근로소득으로&quot; style=&quot;position:relative;&quot;&gt;내가 아직 회사에 다니고 있는 경우에는 근로소득으로&lt;a href=&quot;#%EB%82%B4%EA%B0%80-%EC%95%84%EC%A7%81-%ED%9A%8C%EC%82%AC%EC%97%90-%EB%8B%A4%EB%8B%88%EA%B3%A0-%EC%9E%88%EB%8A%94-%EA%B2%BD%EC%9A%B0%EC%97%90%EB%8A%94-%EA%B7%BC%EB%A1%9C%EC%86%8C%EB%93%9D%EC%9C%BC%EB%A1%9C&quot; aria-label=&quot;내가 아직 회사에 다니고 있는 경우에는 근로소득으로 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;먼저, 스톡옵션 행사에 대한 세금은 내가 그 회사에 아직 재직중이냐 아니냐에 따라 달라지게 된다.&lt;/p&gt;
&lt;p&gt;만약 스톡옵션을 행사하는 시점에 그 회사에 재직 중이라면 스톡옵션을 행사함으로써 얻는 차익은 모두 &lt;strong&gt;근로소득&lt;/strong&gt;으로 평가되어 1년 종합소득에 합산되기 때문에, 이때 내야하는 세금은 &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%86%8C%EB%93%9D%EC%84%B8%EB%B2%95/%EC%A0%9C55%EC%A1%B0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;소득세법 제55조&lt;/a&gt;에 따라 결정된다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;소득구간&lt;/th&gt;
&lt;th&gt;세율&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,200만원 이하&lt;/td&gt;
&lt;td&gt;과세 표준의 6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,200만원 초과 ~ 4,600만원 이하&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4,600만원 초과 ~ 8,800만원 이하&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8,800만원 초과 ~ 1억 5,000만원 이하&lt;/td&gt;
&lt;td&gt;35%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1억 5,000만원 초과 ~ 3억원 이하&lt;/td&gt;
&lt;td&gt;38%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3억원 초과 ~ 5억원 이하&lt;/td&gt;
&lt;td&gt;40%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5억원 초과 ~ 10억원 이하&lt;/td&gt;
&lt;td&gt;42%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10억원 초과&lt;/td&gt;
&lt;td&gt;45%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;다들 아시겠지만, 이 세금은 전체 구간이 아니라 해당 구간을 넘어선 만큼에 대해서만 적용되는 누진세이다. 즉, 만약 필자의 올해 소득이 1억원이라면 전체 소득 1억원에 대해서 35%를 때리는 것이 아니라 1,200만원까지는 6%로 계산하고, 1,200만원을 초과하는 부분은 15%, 4,600만원을 초과하는 부분은 24%로 각각의 구간을 넘어선 부분에 대해서만 초과 세율을 먹이는 것이다.&lt;/p&gt;
&lt;p&gt;문제는 이게 내 연봉으로만 평가되는 경우라면 통상 35% 이상을 넘어가는 경우가 많지 않지만, 여기에 스톡옵션이 얹어지는 순간 소득구간이 갑자기 팍팍 점프하게 된다는 것이다. 즉 아무 생각없이 스톡옵션 전량을 한 번에 행사해버릴 경우에는 세금만 몇 천만원을 납부해야하는 세금폭탄을 맞을 수도 있다.&lt;/p&gt;
&lt;p&gt;그래서 기본적으로 스톡옵션을 행사할 때는 한번에 하는 것보다 나눠서 하는 것이 세금을 절세할 수 있는 길이다.&lt;/p&gt;
&lt;p&gt;단, &lt;a href=&quot;https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%A1%B0%EC%84%B8%ED%8A%B9%EB%A1%80%EC%A0%9C%ED%95%9C%EB%B2%95/(20211123,18521,20211123)/%EC%A0%9C16%EC%A1%B0&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;조세특례제한법 제16조&lt;/a&gt;에 따라 우리 회사가 벤처 특례를 적용받는 기업인 경우에는 몇 가지 혜택이 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[제16조의 2] 연 3천만원의 이익까지는 세금 안 내도 됨(2022년에 부여받은 스톡옵션부터는 5천만원으로 바뀜)&lt;/li&gt;
&lt;li&gt;[제16조의 3] 회사에서 납부특례 적용을 신청해놓은 경우에는 근로소득세를 원천징수 하지 않음. 스톡옵션을 행사한 사람은 총 5년 동안 1/5씩 소득세를 분할납부할 수 있다.&lt;/li&gt;
&lt;li&gt;[제16조의 4] 행사가액의 합계가 3년 동안 5억 이하라면, 행사 시 소득세를 내지 않고 주식을 팔 때 양도세에 합산해서 내도록 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;쉽게 말해서 나라에서 벤처기업육성을 위해 벤처기업의 스톡옵션을 행사 할 때 세금을 깎아주는 방식을 쓰고 있는 것인데, 어느 정도 규모가 되는 스타트업들도 의외로 벤처특례를 적용받고 있는 경우가 많으므로 꼭 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;만약 우리 회사가 벤처 특례 대상 기업인 경우에는 1년에 3천만원어치씩만 스톡옵션을 행사하면 소득세를 아예 내지 않을 수도 있지만, 수익이 억 단위가 넘어가는 상황에서 이 방법을 쓰면 행사기간이 너무 길어지게 되므로 다른 전략을 고민해보는 것이 좋다.&lt;/p&gt;
&lt;h4 id=&quot;내가-회사에-다니고-있지-않은-경우에는-기타소득으로&quot; style=&quot;position:relative;&quot;&gt;내가 회사에 다니고 있지 않은 경우에는 기타소득으로&lt;a href=&quot;#%EB%82%B4%EA%B0%80-%ED%9A%8C%EC%82%AC%EC%97%90-%EB%8B%A4%EB%8B%88%EA%B3%A0-%EC%9E%88%EC%A7%80-%EC%95%8A%EC%9D%80-%EA%B2%BD%EC%9A%B0%EC%97%90%EB%8A%94-%EA%B8%B0%ED%83%80%EC%86%8C%EB%93%9D%EC%9C%BC%EB%A1%9C&quot; aria-label=&quot;내가 회사에 다니고 있지 않은 경우에는 기타소득으로 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;많은 기업들이 재직 중일 때만 스톡옵션을 행사할 수 있도록 제한하고 있기는 하지만, 간혹 퇴사를 한 이후에도 스톡옵션을 행사할 수 있게 해주는 기업들도 있다.&lt;/p&gt;
&lt;p&gt;이 경우에는 이미 고용관계가 끝난 상태에서 스톡옵션을 행사하여 소득을 얻게 되므로 근로소득이 아닌 기타소득으로 평가되고, 행사시점에 얻은 차익에 대하여 지방소득세 2%를 포함하여 총 22%의 세금이 원천징수된다.&lt;/p&gt;
&lt;p&gt;또한 기타소득이 연 300만원이 넘어가게 되는 경우에는 따로 종합소득에 합산해서 확정신고를 해야 하는데, 이때 위에서 봤던 종합소득세율표에 의해 세금이 다시 계산된다. 만약 기타소득이 300만원 이하라면 그냥 원천징수로 끝낼 수도 있기는 하지만 스톡옵션으로 300만원 이하를 버는 경우는 거의 없으므로 거의 무조건 종합소득확정신고를 해야 한다고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;사실 세금에 대한 내용은 워낙 복잡하기도 하고, 현재 우리 회사의 상태, 그리고 내 근로소득에 따라 달라지는 부분도 있기 때문에 스톡옵션을 행사할 때 세금을 정확히 얼마나 내야하는지는 그 때 가봐야 알 수 있다.&lt;/p&gt;
&lt;p&gt;다만 행사하기 전에 미리 세금 납부에 대한 준비를 어느 정도 해둬야 나중에 현금 흐름이 꼬이는 경우가 없으므로, 스톡옵션을 행사할 때도 세금을 내야한다는 사실 자체는 확실히 인지를 하고 있도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;이제-주식을-팔아볼까&quot; style=&quot;position:relative;&quot;&gt;이제 주식을 팔아볼까?&lt;a href=&quot;#%EC%9D%B4%EC%A0%9C-%EC%A3%BC%EC%8B%9D%EC%9D%84-%ED%8C%94%EC%95%84%EB%B3%BC%EA%B9%8C&quot; aria-label=&quot;이제 주식을 팔아볼까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;어찌어찌 스톡옵션을 행사해서 주식을 구매했다고 해도 아직 이게 내 돈이 된 것은 아니다. 내가 가지고 있는 주식을 매도해야 진짜 수익이 되는 것이다.&lt;/p&gt;
&lt;p&gt;그럼 이 주식을 누구한테 팔아야 하는 것일까? 만약에 우리 회사가 상장사인 경우에는 주식 거래가 수월하겠지만, 대부분의 스톡옵션은 회사가 아직 성장하기 전 작은 단계일때 교부가 되는 경우가 많기 때문에, 베스팅 플랜이 끝나서 실제로 주식을 매수할 때에도 여전히 회사가 비상장 상태인 경우가 많다.&lt;/p&gt;
&lt;p&gt;이런 장외주식을 거래할 때는 &lt;a href=&quot;https://www.seoulexchange.kr/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;서울거래소&lt;/a&gt;나 &lt;a href=&quot;https://www.ustockplus.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;증권플러스 비상장&lt;/a&gt;같은 장외주식 거래 플랫폼을 사용해서 거래를 하거나 직접 매수를 원하는 사람과의 계약을 통해 매매를 하게 된다.&lt;/p&gt;
&lt;p&gt;하지만 여기서 중요한 점은 스톡옵션으로 받은 주식의 경우, &lt;strong&gt;우선매수권자&lt;/strong&gt;를 지정해놓는 경우나 아예 IPO(기업공개/상장)나 M&amp;#x26;A(인수합병) 전에는 주식을 매도하지 못 하게 막아놓는 경우도 있다는 것이다.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 400px&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f78708042d7eb6fa950c8953c131c193/1ef88/messi.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 88.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwIE/9oADAMBAAIQAxAAAAFNVCk3J1xo5gaaIzt//8QAHxAAAAUEAwAAAAAAAAAAAAAAAAECAxEEEhMhIjJE/9oACAEBAAEFAi21mhZOyN4GCuXySPJT9x//xAAaEQABBQEAAAAAAAAAAAAAAAAAAQIQEiEy/9oACAEDAQE/AesKKNj/xAAaEQACAgMAAAAAAAAAAAAAAAAAAQIhEBJB/9oACAECAQE/AajZuh9x/8QAHhAAAQMEAwAAAAAAAAAAAAAAAAECERIhUXEQMpH/2gAIAQEABj8CqVJgqydXeDtWL4IQdrn/xAAbEAEBAQACAwAAAAAAAAAAAAABABEhMWFxgf/aAAgBAQABPyENgAn0MhGjHi76TgJ2iOhpIdN4HJ7v/9oADAMBAAIAAwAAABCM2L//xAAYEQEBAAMAAAAAAAAAAAAAAAABABAxQf/aAAgBAwEBPxAUCk3Vxj//xAAXEQEBAQEAAAAAAAAAAAAAAAABEQAQ/9oACAECAQE/EAocOW9v/8QAHBABAQACAwEBAAAAAAAAAAAAAREAQSExcVGx/9oACAEBAAE/EKDC1jKG8HHQBOK/cqlN8H7gAqD2k9yDuzXhnKk6LlTFnWAjBaMwmhn/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;messi&quot; title=&quot;&quot; src=&quot;/static/f78708042d7eb6fa950c8953c131c193/c08c5/messi.jpg&quot; srcset=&quot;/static/f78708042d7eb6fa950c8953c131c193/0913d/messi.jpg 160w,
/static/f78708042d7eb6fa950c8953c131c193/cb69c/messi.jpg 320w,
/static/f78708042d7eb6fa950c8953c131c193/c08c5/messi.jpg 640w,
/static/f78708042d7eb6fa950c8953c131c193/6a068/messi.jpg 960w,
/static/f78708042d7eb6fa950c8953c131c193/1ef88/messi.jpg 1242w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;니 주식은 무조건 저~기 있는 저 친구한테 먼저 가서 살 건지 물어보고 팔아야해요&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;우선매수권자는 말 그대로 &lt;strong&gt;주식을 우선적으로 매수할 수 있는 권리를 가진 사람&lt;/strong&gt;을 의미하며, 대부분의 경우 우선매수권자는 회사(법인) 혹은 회사에서 지정해준 사람(자연인)인 경우가 많다.&lt;/p&gt;
&lt;p&gt;이렇게 회사가 우리를 귀찮게 하는 이유는 간단한데, 신주를 발행해서 교부한 주식이든 회사가 가지고 있던 주식을 나누어 준 것이든 이 주식이 회사에 우호적이지 않은 사람에게 넘어가는 것을 경계하는 것이다.&lt;/p&gt;
&lt;p&gt;아무래도 스톡옵션을 행사하게 되면 기존 투자자들의 지분가치가 희석될 수 밖에 없는데, 이때 이 주식을 다시 회수해서 회사가 가지고 있거나 기존 투자자들에게 다시 부여하는 식으로 회사에 우호적인 지분을 지키려고 하는 것이다.&lt;/p&gt;
&lt;p&gt;그래서 스톡옵션을 행사한 주식을 양도할 때는 부여 당시의 계약서를 잘 읽어보고, 내가 회사에 주식 매도에 대해 서면 통보를 해야하는지, 우선매수권자가 정해져 있지는 않는지, 주식을 매도할 수 있는 게 맞는지 확인해야한다.&lt;/p&gt;
&lt;h3 id=&quot;주식-파셨어요-세금내셔야죠&quot; style=&quot;position:relative;&quot;&gt;주식 파셨어요? 세금내셔야죠!&lt;a href=&quot;#%EC%A3%BC%EC%8B%9D-%ED%8C%8C%EC%85%A8%EC%96%B4%EC%9A%94-%EC%84%B8%EA%B8%88%EB%82%B4%EC%85%94%EC%95%BC%EC%A3%A0&quot; aria-label=&quot;주식 파셨어요 세금내셔야죠 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;자, 이제 주식을 다 팔았으면 다 끝난 것일까? 아니다. 여러분은 주식을 팔아서 얻은 수익에 대한 세금도 내야 한다. 미국의 경우에는 행사할 때 따로 세금을 내지 않기 때문에 주식을 매도할 때에만 20%의 양도소득세를 내지만, 우리나라는 스톡옵션을 행사할 때도 소득세를 내고 주식을 매도할 때도 다시 소득세를 내야한다. &lt;small&gt;&lt;del&gt;(그만 가져가 이 놈들아)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이때 부과되는 세금은 &lt;strong&gt;양도소득세&lt;/strong&gt;라고 불리는 녀석인데, 해외주식을 즐겨 하시는 분들에게는 이미 익숙한 녀석일 것이다. 해외주식매매로 인해 얻은 이익에 대해서는 매년 22%의 양도소득세를 내야하기 때문이다.&lt;/p&gt;
&lt;p&gt;그래서 국내주식을 매매할 때는 증권거래세 외 세금이 없다고 생각하시는 분들이 많은데, 이건 매매하려는 주식이 상장된 회사의 주식이냐, 비상장 회사의 주식이냐에 따라 다르다.&lt;/p&gt;
&lt;p&gt;만약 내가 주식을 매도할 때 아직 우리 회사가 비상장 회사이고 중소기업이라면 주식을 매도해서 얻은 지방소득세를 포함해서 총 11%의 양도소득세를 납부해야하며, 중견기업 이상이라면 22%를 납부해야한다. &lt;small&gt;(지방소득세는 납부 세금의 10%이다.)&lt;/small&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;회사규모&lt;/th&gt;
&lt;th&gt;양도소득세율(지방세포함)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;중소기업&lt;/td&gt;
&lt;td&gt;11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;중견/대기업&lt;/td&gt;
&lt;td&gt;22%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;만약 지분율이 4% 이상이거나 주식이 10억원 어치 이상인 경우에는 대주주로 분류되어서 양도소득세를 더 많이 내게 되는데, 우리가 대주주인 경우는 거의 없으므로 그냥 지방소득세까지 포함해서 11%, 22%라고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;불행 중 다행인 것은 양도소득세는 250만원까지 공제가 되어서 세금을 안 내도 된다는 것이다. 즉, 내가 주식 매도로 인해 얻은 수익이 총 1천만원이라면 공제 대상인 250만원을 제외한 750만원에 대해서만 11%의 세금을 내면 된다는 것이다. 하지만 스톡옵션으로 얻은 수익은 최소 몇 천만원 단위인 경우가 대부분이므로 그냥 처음부터 양도소득세를 낸다고 생각하는 게 마음이 편하다.&lt;/p&gt;
&lt;p&gt;만약 우리 회사가 상장되어있는 상태라면, 대주주가 아닌 이상 양도소득세를 낼 일은 없고, 그냥 일반적인 주식 매매랑 똑같다고 생각하면 된다.&lt;/p&gt;
&lt;h2 id=&quot;스톡옵션-행사-만료&quot; style=&quot;position:relative;&quot;&gt;스톡옵션 행사 만료&lt;a href=&quot;#%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98-%ED%96%89%EC%82%AC-%EB%A7%8C%EB%A3%8C&quot; aria-label=&quot;스톡옵션 행사 만료 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이것 또한 많은 분들이 놓치고 있는 부분인데, 아무리 베스팅이 된 스톡옵션이라고 해도 스톡옵션을 행사할 수 있는 권리는 영원불멸한 것이 아니다. 즉, 특정 조건에 따라서 스톡옵션 부여가 취소되거나 행사를 하지 못 하게 되는 경우들이 있다는 것이다.&lt;/p&gt;
&lt;p&gt;스톡옵션 행사 만료에 대한 내용은 당연히 회사마다 조금씩 다르겠지만, 대충 이런 케이스들이 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;퇴사했어? 스톡옵션 부여 취소할거임&lt;/li&gt;
&lt;li&gt;퇴사했어? 그럼 베스팅된 스톡옵션들은 무조건 퇴사 시점에 행사해야함&lt;/li&gt;
&lt;li&gt;스톡옵션을 부여받은 이후로 4년 안에는 무조건 행사해야함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이것도 스톡옵션 부여 계약서에 적혀있는 내용이기 때문에, 스톡옵션을 받을 때는 계약서를 아주아주 꼼꼼히 읽어봐야 한다.&lt;/p&gt;
&lt;h2 id=&quot;어떻게-하면-좋은-선택을-할-수-있을까&quot; style=&quot;position:relative;&quot;&gt;어떻게 하면 좋은 선택을 할 수 있을까?&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EC%A2%8B%EC%9D%80-%EC%84%A0%ED%83%9D%EC%9D%84-%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;어떻게 하면 좋은 선택을 할 수 있을까 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b19e4452b9c863d23502a510a26ae493/d7854/zzal.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUDBAb/xAAXAQADAQAAAAAAAAAAAAAAAAABAgME/9oADAMBAAIQAxAAAAFZoETQrQIimf8A/8QAGxAAAQQDAAAAAAAAAAAAAAAAAgABAxIEERP/2gAIAQEAAQUCZPAPJRlWQ8ka7X//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREC/9oACAEDAQE/AcYbVhD/xAAWEQADAAAAAAAAAAAAAAAAAAABAhD/2gAIAQIBAT8BYz//xAAcEAABBQADAAAAAAAAAAAAAAABABAREiECMUH/2gAIAQEABj8CUegdsOR2EaWGN//EABwQAAICAgMAAAAAAAAAAAAAAAABEVEQITFBYf/aAAgBAQABPyFmRketY1QpUg3FjSNiCXuH/9oADAMBAAIAAwAAABDIL//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxB0dE6v/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREA/9oACAECAQE/EBIXXf/EABsQAQEAAgMBAAAAAAAAAAAAAAERADEhUYFh/9oACAEBAAE/EAPG7xjH6ykVt1v3Fp+u8LnQsphZ7qHS9YYQRuf/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;zzal&quot; title=&quot;&quot; src=&quot;/static/b19e4452b9c863d23502a510a26ae493/d7854/zzal.jpg&quot; srcset=&quot;/static/b19e4452b9c863d23502a510a26ae493/0913d/zzal.jpg 160w,
/static/b19e4452b9c863d23502a510a26ae493/cb69c/zzal.jpg 320w,
/static/b19e4452b9c863d23502a510a26ae493/d7854/zzal.jpg 550w&quot; sizes=&quot;(max-width: 550px) 100vw, 550px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;자, 그렇다면 나에게 스톡옵션 vs 연봉 인상과 같은 선택지가 왔을 때 어떤 점들을 고려해야할까? 필자는 개인적으로 스톡옵션의 부여량도 좋지만, 스톡옵션의 베스팅 플랜이나 절세 혜택 같은 것들을 고려해보라고 권하고 싶다.&lt;/p&gt;
&lt;h3 id=&quot;스톡옵션으로-얻을-수-있는-실질적인-이익-계산해보기&quot; style=&quot;position:relative;&quot;&gt;스톡옵션으로 얻을 수 있는 실질적인 이익 계산해보기&lt;a href=&quot;#%EC%8A%A4%ED%86%A1%EC%98%B5%EC%85%98%EC%9C%BC%EB%A1%9C-%EC%96%BB%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%8B%A4%EC%A7%88%EC%A0%81%EC%9D%B8-%EC%9D%B4%EC%9D%B5-%EA%B3%84%EC%82%B0%ED%95%B4%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;스톡옵션으로 얻을 수 있는 실질적인 이익 계산해보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;여기까지 읽었다면 이제 다들 아시겠지만, 여러분이 스톡옵션을 1억원 어치 받았다고 해서 여러분의 실질적인 이익이 1억원이 되는 것이 아니다.&lt;/p&gt;
&lt;p&gt;스톡옵션을 행사할 때는 행사가를 회사에 납부해야 함과 동시에 소득세도 납부해야하고, 스톡옵션으로 취득한 주식을 매도할 때도 양도소득세를 또 내야한다. 물론 세무사도 아닌 우리가 미래에 납부할 세금을 정확하게 예측하는 것은 거의 불가능하지만, 이미 인터넷에 나와있는 세율 정보를 토대로 대충 어느 정도 내야할지는 계산해볼 수 있다.&lt;/p&gt;
&lt;p&gt;취득가액에 따라서 이익의 최대 45% 정도까지 세금을 내야하는 경우도 있으니 꼭 두번 세번 계산해보고 스톡옵션을 선택하도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;클리프까지는-무조건-회사를-다녀야한다&quot; style=&quot;position:relative;&quot;&gt;클리프까지는 무조건 회사를 다녀야한다&lt;a href=&quot;#%ED%81%B4%EB%A6%AC%ED%94%84%EA%B9%8C%EC%A7%80%EB%8A%94-%EB%AC%B4%EC%A1%B0%EA%B1%B4-%ED%9A%8C%EC%82%AC%EB%A5%BC-%EB%8B%A4%EB%85%80%EC%95%BC%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;클리프까지는 무조건 회사를 다녀야한다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;앞서 이야기한 것처럼 대한민국은 최소 2년 간 그 직장에 재직해야 스톡옵션을 베스팅받을 수 있도록 법으로 정해놓고 있다.  하지만 회사의 베스팅 플랜에 따라 클리프가 2년인 경우도 있고 3년인 경우도 있기 때문에, &lt;strong&gt;클리프 === 내가 회사를 못 그만두는 기간&lt;/strong&gt;이라고 생각하고 의사결정을 해야한다.&lt;/p&gt;
&lt;p&gt;적어도 클리프 기간은 넘겨야 행사할 수 있는 스톡옵션이라는 것이 생기기 때문에, 애초에 이 기간을 넘길 생각이 없다면 그냥 처음부터 사이닝 보너스 같은 현금을 받고 따로 투자를 하는 게 더 나을 수도 있다.&lt;/p&gt;
&lt;h3 id=&quot;회사의-규모와-성장-가능성-고려하기&quot; style=&quot;position:relative;&quot;&gt;회사의 규모와 성장 가능성 고려하기&lt;a href=&quot;#%ED%9A%8C%EC%82%AC%EC%9D%98-%EA%B7%9C%EB%AA%A8%EC%99%80-%EC%84%B1%EC%9E%A5-%EA%B0%80%EB%8A%A5%EC%84%B1-%EA%B3%A0%EB%A0%A4%ED%95%98%EA%B8%B0&quot; aria-label=&quot;회사의 규모와 성장 가능성 고려하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;스톡옵션은 우리 회사가 많이 성장해서 행사가와 시장가의 차이가 벌어질수록 나에게 큰 이득을 안겨다주는 금융상품이다. 즉, “이 회사가 앞으로 얼마나 더 성장할 것인지”에 내가 먹을 수 있는 이득이 결정된다는 것이다.&lt;/p&gt;
&lt;p&gt;예를 들어 이제 막 시리즈 A 정도의 투자 라운드를 뛴 스타트업은 현재 가치 자체가 너무 작기 때문에 투자 라운드를 한번 뛸 때마다 20배, 30배씩 밸류에이션이 올라가는 경우가 흔하다. 잘 나가는 회사의 경우에는 100배 이상의 기업 가치를 평가받는 경우도 있다.&lt;/p&gt;
&lt;p&gt;그래서 흔히들 스톡옵션 대박 신화라고 하는 몇 십억 단위의 주인공들은 주로 이 쪽 동네에서 나온다. 하지만 그 만큼 아직 PMF(Product Market Fit)을 찾지 못 했을 가능성도 있고, 시장 영향력도 없기 때문에 스톡옵션이 휴지 쪼가리가 될 확률도 높다.&lt;/p&gt;
&lt;p&gt;하지만 우리 회사가 이미 시리즈 D, E 정도의 투자 라운드를 뛸 정도로 성장해있는 회사라면, 회사가 망해서 내 스톡옵션이 휴지가 될 가능성은 적지만 작은 스타트업에 비해 앞으로의 성장 여력이 그렇게 크지는 않을 수도 있다.&lt;/p&gt;
&lt;p&gt;게다가 네이버나 카카오 처럼 덩치가 큰 기업은 벤처 특례를 받지 못 한다. 그래서 지금 스톡옵션을 받는다해도 세금 혜택도 거의 받지 못하고, 스톡옵션의 행사가도 부여 당시의 시장가로 정해지기 때문에 막상 계산기 두드려보면 그렇게 큰 금액이 아닐수도 있다.&lt;/p&gt;
&lt;p&gt;물론 회사의 규모가 크더라도 장래가 유망한 새로운 사업을 벌일 계획이 있다던가 해서 회사의 가치가 떡상할 가능성이 있다면, 거의 안전자산 수준의 스톡옵션이 될 수도 있으니 스톡옵션을 부여받기 전에 최대한 회사의 향후 계획에 대한 정보를 많이 알아내야 좋은 결정을 내릴 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;내-현금흐름에-대해-계획해보기&quot; style=&quot;position:relative;&quot;&gt;내 현금흐름에 대해 계획해보기&lt;a href=&quot;#%EB%82%B4-%ED%98%84%EA%B8%88%ED%9D%90%EB%A6%84%EC%97%90-%EB%8C%80%ED%95%B4-%EA%B3%84%ED%9A%8D%ED%95%B4%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;내 현금흐름에 대해 계획해보기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;앞서 필자는 스톡옵션에 대해서 설명할 때 현금흐름에 대한 이야기를 많이 했었다. 보통 현금흐름이라고 하면 기업의 현금흐름에 대해서만 생각하는데, 사실 개인에게도 현금흐름은 굉장히 중요한 요소이다.&lt;/p&gt;
&lt;p&gt;현금흐름이 한번 막히기 시작하면 계획에도 없던 대출을 땡겨야 할 수도 있고, 수익률이 마이너스인 주식을 팔아서라도 현금을 마련해야 하는 경우가 생기기 때문이다.&lt;/p&gt;
&lt;p&gt;만약 스톡옵션을 행사할 때 납부해야하는 행사가나 세금에 대한 고민과 계획이 없었다면, 정작 내가 스톡옵션을 행사하려고 할 때 돈이 없어서 행사하지 못 하거나, 대출을 발생시켜서 세금을 내야하는 눈물나는 경우가 발생할 수도 있다.&lt;/p&gt;
&lt;p&gt;그러니 스톡옵션을 선택하기 전에 미리 회사의 베스팅 플랜에 대해서 물어보고, 클리프가 되었을 때 그리고 베스팅 주기가 다가올 때 전세기간 만료와 같은 이벤트 때문에 큰 돈을 써야할 일이 있을지 미리 한번쯤 생각해봐야 한다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;서두에서 이야기했지만, 필자가 이런 포스팅을 쓰게 된 이유는 스톡옵션을 보유한 사람들이 생각보다 스톡옵션을 그냥 주식이라고 생각하는 경우가 많기 때문이었다.&lt;/p&gt;
&lt;p&gt;특히 스톡옵션을 처음 받아보시는 분의 경우, 필자가 “선생님 그거 공짜아님. 행사할 때 돈 내셔야해요”라는 이야기를 해주었을 때, 왜 주식을 파는데 돈을 내야 하냐고 반문하는 경우도 있을 정도로 스톡옵션에 대해서 잘 모르시는 분들이 많았다. &lt;small&gt;(스톡옵션 베스팅이 주식을 파는 행위라고 생각하시는 분들이 은근히 많았다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;하지만 스톡옵션은 내가 받아야 하는 보상의 수단으로 지급되는 금융상품이기 때문에, 정확히 내가 얼마 정도의 보상을 받는 것이고 그 보상을 이익으로 실현하기까지 어떤 과정을 거쳐야 하는 지를 알고 있는 것은 매우 중요하다.&lt;/p&gt;
&lt;p&gt;또한 많은 분들이 스톡옵션이라는 것을 공짜로 부여받는다고 생각하지만, 스톡옵션을 선택함으로써 내 연봉의 상승률을 조금 깎거나 심지어 동결하는 경우도 있고 사이닝 보너스와 같은 현금성 이익을 포기해야하는 경우도 있기 때문에 사실 공짜가 아니다.&lt;/p&gt;
&lt;p&gt;여러분이 포기한 연봉 상승률이나 현금성 이익이 그대로 기회비용이 되기 때문에 사실상 이 기회비용이 여러분이 스톡옵션이라는 금융상품을 받기 위해 지불해야하는 프리미엄인 것이다.&lt;/p&gt;
&lt;p&gt;앞으로 여러분이 이런 모든 것들을 고려하여 “연봉 500만원 올릴래 vs 스톡옵션 5천만원 어치 받을래”와 같은 선택지와 만나게 되었을 때 최대한 짱구를 굴려서 여러분이 얻을 수 있는 이익을 최대화하는 의사결정을 내릴 수 있기를 바란다.&lt;/p&gt;
&lt;p&gt;이상으로 개발자가 알아야 할 스톡옵션의 모든 것 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[All About tsconfig] Compiler options / Emit]]></title><description><![CDATA[In this post, following the previous [All About tsconfig] Compiler options / Modules post, I’ll introduce options that control output files among ’s compilation options.]]></description><link>https://evan-moon.github.io/2021/10/30/tsconfig-compiler-options-modules-emit/en/</link><guid isPermaLink="false">20211030-tsconfig-compiler-options-modules-emit-en</guid><pubDate>Sat, 30 Oct 2021 12:38:24 GMT</pubDate><content:encoded>&lt;p&gt;In this post, following the previous &lt;a href=&quot;/20210808-tsconfig-compiler-options-modules&quot;&gt;[All About tsconfig] Compiler options / Modules&lt;/a&gt; post, I’ll introduce options that control output files among &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt;’s compilation options.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;These options determine the appearance of JavaScript code generated after compiling code written in TypeScript, such as how to express syntax supported only in TypeScript in JavaScript, or how to express it when transpiling ES6 or higher syntax to ES5.&lt;/p&gt;
&lt;p&gt;Of course, since there are parts that overlap with features provided by transpilers like Babel, if using TSC and Babel together, there may be cases where you don’t need to meticulously set all options in tsconfig.&lt;/p&gt;
&lt;h2 id=&quot;declaration&quot; style=&quot;position:relative;&quot;&gt;declaration&lt;a href=&quot;#declaration&quot; aria-label=&quot;declaration permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate type declaration files together when compiling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Generate only JavaScript files when compiling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;declaration&lt;/code&gt; option is an option that decides whether to output TypeScript’s &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; files or not. Since this option is off by default, if you compile TypeScript without separate settings, you can see only &lt;code class=&quot;language-text&quot;&gt;*.js&lt;/code&gt; files generated alone.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But if you turn on the &lt;code class=&quot;language-text&quot;&gt;declaration&lt;/code&gt; option, in addition to the generated JavaScript file, it also generates &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; files containing type declarations.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you want modules you made to support TypeScript, you must allow users to directly get the module’s source code or provide JavaScript files but also provide type declaration files &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt;, so if developing TypeScript-targeted libraries, I recommend using this option to generate type declaration files together during compilation.&lt;/p&gt;
&lt;h2 id=&quot;declarationdir&quot; style=&quot;position:relative;&quot;&gt;declarationDir&lt;a href=&quot;#declarationdir&quot; aria-label=&quot;declarationdir permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Path to directory to output type declaration files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;declarationDir&lt;/code&gt; option, as its name suggests, is an option to set the path to output type declaration files. At this time, the current path that &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; means refers to where the &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; file is located, so if you want to output type declaration files inside the directory where compiled files are located, you must directly specify directories like &lt;code class=&quot;language-text&quot;&gt;./{outDir}/types&lt;/code&gt; rather than paths like &lt;code class=&quot;language-text&quot;&gt;./types&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you don’t separately set the &lt;code class=&quot;language-text&quot;&gt;declarationDir&lt;/code&gt; option, type declaration files are created in the same location as their original JavaScript files.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;When declarationDir option is not set

myProject
├── math.ts
├── dist
│   ├── math.d.ts &amp;lt;
│   └── math.js
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;When declarationDir option is set to &quot;./dist/types&quot;

myProject
├── math.ts
├── dist
│   ├── math.js
│   └── types
│       └── math.d.ts &amp;lt;
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Gathering type declaration files in one directory like this lets you conveniently specify the location of that package’s type declaration files later using &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;’s &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; property, so I tend to use the &lt;code class=&quot;language-text&quot;&gt;declarationDir&lt;/code&gt; option to gather type declarations in one place.&lt;/p&gt;
&lt;h2 id=&quot;declarationmap&quot; style=&quot;position:relative;&quot;&gt;declarationMap&lt;a href=&quot;#declarationmap&quot; aria-label=&quot;declarationmap permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate mapping files connecting type declarations with source code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Don’t generate mapping files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;declarationMap&lt;/code&gt; option decides whether to generate mapping files that help developers navigate to original source files through navigation features provided by IDEs like “Go to Definition.”&lt;/p&gt;
&lt;p&gt;As learned earlier, if you generate type declaration files using the &lt;code class=&quot;language-text&quot;&gt;declaration&lt;/code&gt; option, the following results are compiled:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.ts (original source file)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js (JavaScript)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts (type declaration)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this time, if there’s no mapping file defining the relationship between JavaScript code containing actually executed code and type declaration files containing type declarations, when using navigation features in IDEs, you navigate to type declarations in &lt;code class=&quot;language-text&quot;&gt;math.d.ts&lt;/code&gt; files, not source code.&lt;/p&gt;
&lt;p&gt;But since information about type declarations is already exposed in developers’ own source code anyway, when using navigation, most cases want to see actual internal implementation of functions rather than wanting to know type declaration definitions.&lt;/p&gt;
&lt;p&gt;In this situation, using the &lt;code class=&quot;language-text&quot;&gt;declarationMap&lt;/code&gt; option, when developers use navigation features, you can generate separate mapping files together so they can navigate to source code, not type declarations.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts (type declaration)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=math.d.ts.map&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts.map&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;math.d.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../../../utils/math.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AAAA,eAAO,MAAM,GAAG,MAAO,MAAM,SAAS,MAAM,WAAU,CAAC&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mapping files are composed in JSON format and created in the same path as files where type declarations are defined. Since these mapping files have original source code paths, when using IDE navigation features, they can inform “source code is not here but at this path.”&lt;/p&gt;
&lt;p&gt;In other words, to fully utilize this feature, source code must necessarily be included when deploying modules to npm registry. Generally when deploying to npm registry, only build results are deployed rather than source code. In this case, since source code isn’t included in the library anyway, including mapping files becomes meaningless.&lt;/p&gt;
&lt;p&gt;Simply including source code when deploying to npm registry doesn’t increase bundle size of applications using modules you made, so to greatly improve productivity and convenience of developers using libraries you made, I recommend turning on &lt;code class=&quot;language-text&quot;&gt;declarationMap&lt;/code&gt; and deploying to npm registry including source code.&lt;/p&gt;
&lt;h2 id=&quot;downleveliteration&quot; style=&quot;position:relative;&quot;&gt;downlevelIteration&lt;a href=&quot;#downleveliteration&quot; aria-label=&quot;downleveliteration permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate clear implementations for iteration features added in ES6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Perform only basic transpiling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;downlevelIteration&lt;/code&gt; option is an option that can make TypeScript transpile features added in ES6 like &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Spread&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Symbol.iterator&lt;/code&gt; more clearly.&lt;/p&gt;
&lt;p&gt;If the JavaScript version as compilation target is ES6 or higher, this option isn’t very meaningful, but when targeting ES5 or lower versions for cross-browsing, etc., you can prevent iterators from operating differently from developers’ intentions during JavaScript runtime.&lt;/p&gt;
&lt;p&gt;For example, if transpiling TypeScript code using &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt; to ES5, you can see results like below:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;use strict&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; str_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; _i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; str_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; _i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str_1&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt; is a feature not in ES5, TypeScript transpiled &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt; into a general &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;Looking up to here seems no problems, but actually code transpiled like this doesn’t show behavior exactly matching original code. Because of code like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;🙏&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The 🙏 emoji used in the above code is an emoji I personally use a lot. Since the number of visibly seen characters is one, you might naturally think this emoji’s length is also &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;, but actually emojis’ lengths aren’t &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;🙏&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&apos;👩‍❤️‍💋‍👩&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token comment&quot;&gt;// 11&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In other words, writing general &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; statements using this emoji’s length can make it difficult to extract proper characters. If you don’t quite understand what this means, try copy-pasting and executing the code below in Chrome developer tools.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🙏&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;for문 &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;for/of문 &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;s&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for문 &gt; �
for문 &gt; �

for/of문 &gt; 🙏&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is exactly why you shouldn’t just transpile &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt; statements into &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; statements.&lt;/p&gt;
&lt;p&gt;To simply explain why emoji lengths aren’t 1 like this - first because emojis are multibyte characters, and also because new emojis keep being added and emojis combining existing emojis appear, methods of expressing emojis have become crazy. For details about emoji lengths, read &lt;a href=&quot;https://blog.jonnew.com/posts/poo-dot-length-equals-two&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;this post&lt;/a&gt; which explains it well.&lt;/p&gt;
&lt;p&gt;Anyway, the important point here is that such disasters can occur if you transpile them buried together just because &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; operations are similar.&lt;/p&gt;
&lt;p&gt;So TypeScript separately provides an option called &lt;code class=&quot;language-text&quot;&gt;downlevelIteration&lt;/code&gt; so iteration features like &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Spread&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Symbol.iterator&lt;/code&gt; don’t operate differently from developers’ intentions - it can check whether features like &lt;code class=&quot;language-text&quot;&gt;Symbol.iterator&lt;/code&gt; exist or even add polyfills implementing such features.&lt;/p&gt;
&lt;h2 id=&quot;emitbom&quot; style=&quot;position:relative;&quot;&gt;emitBOM&lt;a href=&quot;#emitbom&quot; aria-label=&quot;emitbom permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TypeScript marks BOM when generating output files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;TypeScript doesn’t mark BOM when generating output files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;emitBOM&lt;/code&gt; option is an option to decide whether TypeScript marks &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%ED%8A%B8_%EC%88%9C%EC%84%9C_%ED%91%9C%EC%8B%9D&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;BOM (Byte Order Mark)&lt;/a&gt; when generating output files.&lt;/p&gt;
&lt;p&gt;Byte Order Mark is a method of indicating what encoding method this file used by adding special Unicode at the very front part of files.&lt;/p&gt;
&lt;p&gt;Since BOM is used only to inform computers about current file’s encoding information, not for humans to read originally, text editors or places like vim don’t show BOM even when opening files.&lt;/p&gt;
&lt;p&gt;However, generally in runtime environments where JavaScript executes, cases needing BOM are rare, and since Unicode 3.2 recommends not using BOM, it’s an option you don’t really need to turn on. &lt;small&gt;(TypeScript official documentation also says you don’t need to turn it on)&lt;/small&gt;&lt;/p&gt;
&lt;h2 id=&quot;emitdeclarationonly&quot; style=&quot;position:relative;&quot;&gt;emitDeclarationOnly&lt;a href=&quot;#emitdeclarationonly&quot; aria-label=&quot;emitdeclarationonly permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Output only type declaration files without JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Output including JavaScript files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;emitDeclarationOnly&lt;/code&gt; option, as its name Declaration only suggests, is an option deciding whether to output only type declaration files without JavaScript files when proceeding with compilation.&lt;/p&gt;
&lt;p&gt;Usually used when using separate tools rather than TypeScript compiler when converting TypeScript to JavaScript, or when needing to provide only type declarations to modules already made in JavaScript.&lt;/p&gt;
&lt;h2 id=&quot;importhelpers&quot; style=&quot;position:relative;&quot;&gt;importHelpers&lt;a href=&quot;#importhelpers&quot; aria-label=&quot;importhelpers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use helper functions provided by tslib in output files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Don’t use helper functions provided by tslib and implement helpers directly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; option is an option to decide whether to directly write helper functions occurring when transpiling TypeScript to JavaScript versions ES5 or lower in output files, or allow replacement with helper functions provided by the &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;Let’s understand by looking at source code and output files together.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;fn&lt;/code&gt; function is a simple function that adds the element &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; at the very front of the array received as an argument and returns it. As you know, since the Spread feature usable with syntax like &lt;code class=&quot;language-text&quot;&gt;[...arr]&lt;/code&gt; isn’t included in ES5, TypeScript adds a helper function called &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; in output files to transpile the Spread feature.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __spreadArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__spreadArray&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;to&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pack &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; arguments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ar &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;from&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      ar&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ar &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__spreadArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s important here is that implementation of the function &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; was included together in output files to implement ES6’s Spread feature. Actually including such implementations in output files may not be a big problem, but if you need to use that &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; again elsewhere, implementation of the &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; function is added again to that module, causing duplicate code.&lt;/p&gt;
&lt;p&gt;At this time, using the &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; option, you can change to get these helper functions from the &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; library to remove code duplication.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; __spreadArray &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;tslib&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__spreadArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This way, since the &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; function is imported from &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; and used, the need to declare the &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; function every time disappears, so code duplication can be removed. But code transpiled using this option naturally needs the &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; package installed to work properly, so carefully weigh pros and cons of allowing duplicate implementation of helper functions versus installing &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; in your application and use the option.&lt;/p&gt;
&lt;h2 id=&quot;importsnotusedasvalues&quot; style=&quot;position:relative;&quot;&gt;importsNotUsedAsValues&lt;a href=&quot;#importsnotusedasvalues&quot; aria-label=&quot;importsnotusedasvalues permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;remove&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove import statements not needed at runtime from output files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;preserve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove type information from output files but keep import statements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate errors when using import statements that only get type information&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;importsNotUsedAsValues&lt;/code&gt; option is an option to control how TypeScript processes unnecessary import statements when generating output files. To understand the meaning this option has, you need to know a bit about how TypeScript processes import statements.&lt;/p&gt;
&lt;p&gt;Basically, when TypeScript generates JavaScript files through compilation, it erases information related to types. Let’s understand by looking at code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; classBar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; classBar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at the above code, you can see the import statement getting the &lt;code class=&quot;language-text&quot;&gt;InterfaceFoo&lt;/code&gt; interface disappeared in JavaScript output files. Because JavaScript doesn’t have features like TypeScript’s types or interfaces, so leaving type information is meaningless.&lt;/p&gt;
&lt;p&gt;Of course, as mentioned earlier, since type information can’t be used in JavaScript anyway, removing such information is correct, but if the &lt;code class=&quot;language-text&quot;&gt;../utils/foo&lt;/code&gt; module includes intentional side effects, problems can occur.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils/foo.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InterfaceFoo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;utils/foo.ts&lt;/code&gt; module is a module only exposing interfaces, but internally includes side effects of &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt;. In this example it’s simple console output, but actually Angular includes side effects of explicitly injecting and registering modules inside such modules.&lt;/p&gt;
&lt;p&gt;The problem is that even in such cases, TypeScript erases the statement itself that imported the &lt;code class=&quot;language-text&quot;&gt;utils/foo&lt;/code&gt; module when outputting JavaScript. Then naturally the side effect of &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt; doesn’t execute in JavaScript runtime. So in such cases, developers must add one more import statement that can deceive TypeScript to intentionally execute side effects.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; classBar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../utils/bar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; classBar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So TypeScript version 3.8 added &lt;code class=&quot;language-text&quot;&gt;import type&lt;/code&gt; functionality to explicitly express “this import statement is a statement that only gets type information,” and provides the &lt;code class=&quot;language-text&quot;&gt;importsNotUsedAsValues&lt;/code&gt; option to control leaving import statements even if getting only type information using general import statements.&lt;/p&gt;
&lt;h2 id=&quot;inlinesourcemap&quot; style=&quot;position:relative;&quot;&gt;inlineSourceMap&lt;a href=&quot;#inlinesourcemap&quot; aria-label=&quot;inlinesourcemap permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate source map files separately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Encode source map file contents in Base64 and add to source files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; option is an option deciding how TypeScript will generate source maps during compilation. Basically TypeScript provides source maps in the form of &lt;code class=&quot;language-text&quot;&gt;*.js.map&lt;/code&gt; files, but if &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; is &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;, it adds source maps as comments inside source files.&lt;/p&gt;
&lt;p&gt;Let’s directly compile modules having simple functions and see what differences there are.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; option is off, TypeScript generates separate source map files and generates source maps by writing only that source map’s path in compiled JS files.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=math.js.map&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js.map&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;math.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;sources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../../utils/math.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;mappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AAAA,MAAM,CAAC,IAAM,GAAG,GAAG,UAAC,CAAS,IAAK,OAAA,UAAC,CAAS,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAApB,CAAoB,CAAC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this time, you can confirm that source map file paths are added to compiled JS files in the form of &lt;code class=&quot;language-text&quot;&gt;#sourceMappingURL=math.js.map&lt;/code&gt;, and source map files have original TypeScript source file paths written like &lt;code class=&quot;language-text&quot;&gt;&quot;sources&quot;: [&quot;../../utils/math.ts&quot;]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you turn on the &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; option, TypeScript no longer generates source map files and directly encodes source map file contents in Base64 and adds them inside compiled JS files.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3V0aWxzL21hdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sR0FBRyxHQUFHLFVBQUMsQ0FBUyxJQUFLLE9BQUEsVUFBQyxDQUFTLElBQUssT0FBQSxDQUFDLEdBQUcsQ0FBQyxFQUFMLENBQUssRUFBcEIsQ0FBb0IsQ0FBQyJ9&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;inlinesources&quot; style=&quot;position:relative;&quot;&gt;inlineSources&lt;a href=&quot;#inlinesources&quot; aria-label=&quot;inlinesources permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Don’t include source code contents in inline source maps.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Include source code contents together in inline source maps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;inlineSources&lt;/code&gt; option decides whether to also include original source code contents in inline source maps made using the &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;If this option’s value is &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;, a field called &lt;code class=&quot;language-text&quot;&gt;sourceContent&lt;/code&gt; is added to inline source maps and source code contents are included together in that field.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3V0aWxzL21hdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sR0FBRyxHQUFHLFVBQUMsQ0FBUyxJQUFLLE9BQUEsVUFBQyxDQUFTLElBQUssT0FBQSxDQUFDLEdBQUcsQ0FBQyxFQUFMLENBQUssRUFBcEIsQ0FBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBhZGQgPSAoeDogbnVtYmVyKSA9PiAoeTogbnVtYmVyKSA9PiB4ICsgeTtcbiJdfQ==&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Decoded source map&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;math.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../../utils/math.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AAAA,MAAM,CAAC,IAAM,GAAG,GAAG,UAAC,CAAS,IAAK,OAAA,UAAC,CAAS,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAApB,CAAoB,CAAC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sourcesContent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;export const add = (x: number) =&gt; (y: number) =&gt; x + y;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Originally in &lt;a href=&quot;https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/preview#&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;source map specs&lt;/a&gt;, the &lt;code class=&quot;language-text&quot;&gt;sourceContent&lt;/code&gt; field is close to a kind of exception handling to handle cases where original source files can’t be accessed, so it’s an option without big problems even if not turned on.&lt;/p&gt;
&lt;h2 id=&quot;noemit&quot; style=&quot;position:relative;&quot;&gt;noEmit&lt;a href=&quot;#noemit&quot; aria-label=&quot;noemit permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export output files after compilation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Don’t export output files after compilation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noEmit&lt;/code&gt; option, as its name suggests, decides behavior about whether TypeScript will export output files after compilation. Just hearing the explanation makes you wonder if such cases are needed, but it’s an option used surprisingly frequently and usefully.&lt;/p&gt;
&lt;p&gt;Representative examples include registering commands like &lt;code class=&quot;language-text&quot;&gt;tsc --noEmit&lt;/code&gt; as NPM scripts when needing to only proceed with static type checking at timings like CI or Git Hook, or when using tools like Webpack, Parcel, Rollup for compilation, many cases use this option to only have TSC do static type checking.&lt;/p&gt;
&lt;h2 id=&quot;noemithelpers&quot; style=&quot;position:relative;&quot;&gt;noEmitHelpers&lt;a href=&quot;#noemithelpers&quot; aria-label=&quot;noemithelpers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Include helper functions like &lt;code class=&quot;language-text&quot;&gt;__awaiter&lt;/code&gt; in compiled files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Don’t include helper functions like &lt;code class=&quot;language-text&quot;&gt;__awaiter&lt;/code&gt; in compiled files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; option decides whether to include helper functions like &lt;code class=&quot;language-text&quot;&gt;__awaiter&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;__generator&lt;/code&gt; in output files where compilation completed.&lt;/p&gt;
&lt;p&gt;Since the &lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; option’s operation is similar to &lt;a href=&quot;#importhelpers&quot;&gt;importHelpers&lt;/a&gt;, it can be a bit confusing. If the &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; option decides whether to “include in source” or “import from elsewhere” implementations of helper functions, the &lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; option decides whether to “include in source” or “not do at all” implementations of helper functions.&lt;/p&gt;
&lt;p&gt;Let’s understand this difference by looking at compiled code directly.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// When both importHelpers and noEmitHelpers are off, output files include helper implementations too&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __awaiter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__awaiter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _arguments&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __generator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__generator&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__awaiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/*return*/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// When importHelper is on, helpers are imported externally&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; __awaiter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; __generator &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tslib&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__awaiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/*return*/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// When noEmitHelpers is on, there&apos;s no code even getting or declaring helpers at all&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&apos;use strict&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__awaiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/*return*/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If both &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; options are on, settings of whether to “get helper functions externally” or “not include in output files” conflict. In this case, &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt;’ operation is followed preferentially, so be careful of this point.&lt;/p&gt;
&lt;h2 id=&quot;noemitonerror&quot; style=&quot;position:relative;&quot;&gt;noEmitOnError&lt;a href=&quot;#noemitonerror&quot; aria-label=&quot;noemitonerror permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export output files even if errors occur during compilation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Don’t export output files if errors occur during compilation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noEmitOnError&lt;/code&gt; option, as its name suggests, decides whether to export output files if errors occur due to various factors during compilation. If this option is on, output files aren’t exported if errors occur during compilation.&lt;/p&gt;
&lt;p&gt;Just looking like this, you might think “naturally shouldn’t output files be not made if errors occur?”, but development environments using TSC’s Watch option can be more convenient to generate output files even if errors occur during compilation and also observe side effects occurring from that, so I recommend turning this option off in development environments and turning it on at build time for production environment deployment.&lt;/p&gt;
&lt;h2 id=&quot;preserveconstenums&quot; style=&quot;position:relative;&quot;&gt;preserveConstEnums&lt;a href=&quot;#preserveconstenums&quot; aria-label=&quot;preserveconstenums permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove Enum declarations using &lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; keyword at compile time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Don’t remove Enum declarations using &lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; keyword at compile time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;preserveConstEnums&lt;/code&gt; option is an option about whether to remove Enum declarations using &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/enums.html#const-enums&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;const enum&lt;/a&gt; keyword at compile time. To save memory costs at runtime, TypeScript replaces parts referencing values of Enums declared with &lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; keyword with that Enum’s values.&lt;/p&gt;
&lt;p&gt;Unlike Enums declared using only &lt;code class=&quot;language-text&quot;&gt;enum&lt;/code&gt; keyword, Enums using &lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; keyword are guaranteed to only have constant values, so referential transparency is also guaranteed, and ultimately there’s no problem just replacing values at compile time.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; Foo &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Foo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; Foo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Foo &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* A */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;= Replaced with value, not Foo.A&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this time, looking closely at compiled code, a variable called &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; is declared to express Enum and values are assigned to that variable using IIFE, but you can see there are no parts accessing this variable. In other words, in runtime environments where this JS code executes, there’s no problem even without the variable &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At this time, setting the &lt;code class=&quot;language-text&quot;&gt;preserveConstEnums&lt;/code&gt; option’s value to &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; can remove Enum declarations meaningless at runtime like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* A */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id=&quot;closing&quot; style=&quot;position:relative;&quot;&gt;Closing&lt;a href=&quot;#closing&quot; aria-label=&quot;closing permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I’ve wrapped up the fourth &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; series, the &lt;code class=&quot;language-text&quot;&gt;Emit&lt;/code&gt; edition. Options playing roles related to Emit are mainly touched when using TSC combined with other tools or when needing to optimize bundle size. Since I also studied these options after quite a while, even though there were options I’d used before, my memory seemed hazy.&lt;/p&gt;
&lt;p&gt;That’s all for this post on [All About tsconfig] Compiler options / Emit.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[tsconfig의 모든 것] Compiler options / Emit]]></title><description><![CDATA[이번 포스팅에서는 지난 [tsconfig의 모든 것] Compiler options / Modules 포스팅에 이어 의 컴파일 옵션 중 출력 파일을 컨트롤 하는 옵션들을 소개할 예정이다.]]></description><link>https://evan-moon.github.io/2021/10/30/tsconfig-compiler-options-modules-emit/</link><guid isPermaLink="false">20211030-tsconfig-compiler-options-modules-emit</guid><pubDate>Sat, 30 Oct 2021 12:38:24 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 지난 &lt;a href=&quot;/20210808-tsconfig-compiler-options-modules&quot;&gt;[tsconfig의 모든 것] Compiler options / Modules&lt;/a&gt; 포스팅에 이어 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt;의 컴파일 옵션 중 출력 파일을 컨트롤 하는 옵션들을 소개할 예정이다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;이 옵션들은 타입스크립트에서만 지원되는 문법들을 자바스크립트로 어떻게 표현할 것인지, 혹은 ES6 이상의 문법을 ES5로 트랜스파일링할 때 어떻게 표현할 것인지와 같이 타입스크립트로 작성된 코드를 컴파일한 이후에 생성되는 자바스크립트 코드의 모습을 결정하는 옵션들이다.&lt;/p&gt;
&lt;p&gt;물론 Babel과 같은 트랜스파일러가 제공해주는 기능과 중복되는 부분이 있기 때문에, TSC와 Babel을 함께 사용하는 경우에는 tsconfig에서 모든 옵션을 섬세하게 설정해주지 않아도 되는 경우도 있다.&lt;/p&gt;
&lt;h2 id=&quot;declaration&quot; style=&quot;position:relative;&quot;&gt;declaration&lt;a href=&quot;#declaration&quot; aria-label=&quot;declaration permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일 할 때 타입 선언 파일도 함께 생성한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;컴파일 할 때 자바스크립트 파일만을 생성한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;declaration&lt;/code&gt; 옵션은 타입스크립트의 &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; 파일을 내보낼지 말지를 결정하는 옵션이다. 만약 기본적으로 이 옵션은 꺼져있기 때문에, 별도의 설정 없이 타입스크립트를 컴파일하게 되면 &lt;code class=&quot;language-text&quot;&gt;*.js&lt;/code&gt; 파일만 덩그러니 생성되는 모습을 볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;하지만 &lt;code class=&quot;language-text&quot;&gt;declaration&lt;/code&gt; 옵션을 켜게 되면, 생성된 자바스크립트 파일 외에도 타입 선언을 담고 있는 &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; 파일을 함께 생성하게된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 여러분이 만든 모듈이 타입스크립트를 지원하도록 하고 싶다면, 사용자가 직접 모듈의 소스코드를 가져올 수 있도록 허용하거나 자바스크립트 파일을 제공하되 타입 선언 파일인 &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; 파일을 함께 제공해줘야 하기 때문에, 타입스크립트 대상의 라이브러리를 개발한다면 이 옵션을 사용하여 컴파일 시 타입 선언 파일까지 함께 생성하는 것을 추천한다.&lt;/p&gt;
&lt;h2 id=&quot;declarationdir&quot; style=&quot;position:relative;&quot;&gt;declarationDir&lt;a href=&quot;#declarationdir&quot; aria-label=&quot;declarationdir permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;타입&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;타입 선언 파일을 내보낼 디렉토리의 경로&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;declarationDir&lt;/code&gt; 옵션은 이름 그대로 타입 선언 파일을 내보낼 경로를 설정할 수 있는 옵션이다. 이때 &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt;가 의미하는 현재 경로는 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; 파일이 위치한 곳을 의미하기 때문에, 만약 컴파일된 파일들이 위치한 디렉토리 안 쪽에 타입 선언 파일을 내보내고 싶다면 &lt;code class=&quot;language-text&quot;&gt;./types&lt;/code&gt;와 같은 경로가 아닌, &lt;code class=&quot;language-text&quot;&gt;./{outDir}/types&lt;/code&gt;와 같이 디렉토리를 직접 지정해줘야 한다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;declarationDir&lt;/code&gt; 옵션을 별도로 설정해주지 않는다면 타입 선언 파일은 자신의 원본 자바스크립트 파일과 동일한 위치에 생성된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;declarationDir 옵션을 설정하지 않은 경우

myProject
├── math.ts
├── dist
│   ├── math.d.ts &amp;lt;
│   └── math.js
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;declarationDir 옵션을 &quot;./dist/types&quot;로 설정한 경우

myProject
├── math.ts
├── dist
│   ├── math.js
│   └── types
│       └── math.d.ts &amp;lt;
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 하나의 디렉토리에 타입 선언 파일을 모아두게 되면 추후 &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 프로퍼티를 사용하여 편하게 해당 패키지의 타입 선언 파일들의 위치를 지정할 수 있으므로 필자는 &lt;code class=&quot;language-text&quot;&gt;declarationDir&lt;/code&gt; 옵션을 사용하여 타입 선언을 한 곳에 모아두는 편이다.&lt;/p&gt;
&lt;h2 id=&quot;declarationmap&quot; style=&quot;position:relative;&quot;&gt;declarationMap&lt;a href=&quot;#declarationmap&quot; aria-label=&quot;declarationmap permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;타입 선언과 소스 코드를 연결하는 매핑 파일을 생성한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;매핑 파일을 생성하지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;declarationMap&lt;/code&gt; 옵션은 개발자가 IDE에서 제공하는 “Go to Definition” 같은 네비게이션 기능을 통해 원본 소스 파일로 이동할 수 있도록 도와주는 맵핑 파일을 함께 생성할 것인지에 대한 여부를 결정한다.&lt;/p&gt;
&lt;p&gt;앞서 알아보았듯이 &lt;code class=&quot;language-text&quot;&gt;declaration&lt;/code&gt; 옵션을 사용하여 타입 선언 파일을 생성하게 되면 다음과 같은 결과물이 컴파일된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.ts (원본 소스 파일)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js (자바스크립트)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts (타입 선언)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 실제로 실행되는 코드를 담고 있는 자바스크립트 코드와 타입 선언을 담고 있는 타입 선언 파일의 연관 관계를 정의한 매핑 파일이 없다면, IDE에서 네비게이팅 기능을 사용했을 때 소스 코드가 아닌, &lt;code class=&quot;language-text&quot;&gt;math.d.ts&lt;/code&gt; 파일의 타입 선언으로 이동하게 된다.&lt;/p&gt;
&lt;p&gt;하지만 어차피 개발자 자신의 소스 코드에도 타입 선언에 대한 정보는 다 노출되고 있기 때문에, 네비게이팅을 사용하는 경우는 타입 선언 정의를 알고 싶다기 보다는 실제로 함수의 내부 구현을 보고 싶은 경우가 대부분일 것이다.&lt;/p&gt;
&lt;p&gt;이런 상황에서 &lt;code class=&quot;language-text&quot;&gt;declarationMap&lt;/code&gt; 옵션을 사용하면 개발자가 네비게이팅 기능을 사용했을 때 타입 선언이 아닌 소스 코드로 이동할 수 있도록 별도의 매핑 파일을 함께 생성해줄 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts (타입 선언)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=math.d.ts.map&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.d.ts.map&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;math.d.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../../../utils/math.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AAAA,eAAO,MAAM,GAAG,MAAO,MAAM,SAAS,MAAM,WAAU,CAAC&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;매핑 파일은 JSON 포맷으로 구성되어 있으며, 타입 선언이 정의된 파일과 같은 경로에 생성된다. 이 매핑 파일은 원본 소스 코드의 경로를 가지고 있기 때문에, IDE의 네비게이팅 기능을 사용했을 때 “소스코드는 여기가 아니라 이 경로에 있음”이라고 알려줄 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;즉, 이 기능을 100% 활용하고 싶다면 npm 레지스트리에 모듈을 배포할 때 반드시 소스 코드가 함께 포함되어야 한다. 일반적으로 npm 레지스트리에 배포할 때 소스코드가 아닌 빌드 결과물만을 배포하는 경우가 많은데, 이렇게 되면 어차피 라이브러리 내에 소스코드가 포함되어 있지 않기 때문에 매핑 파일을 함께 넣어줘도 의미가 없어지는 것이다.&lt;/p&gt;
&lt;p&gt;단순히 npm 레지스트리에 소스코드까지 포함해서 배포한다고 해서 내가 만든 모듈을 사용한 어플리케이션의 번들 사이즈가 늘어나는 것도 아니니, 내가 만든 라이브러리를 사용하는 개발자들의 생산성과 편의성을 많이 높혀주기 위해 &lt;code class=&quot;language-text&quot;&gt;declarationMap&lt;/code&gt;을 켜고 소스코드까지 포함해서 npm 레지스트리에 배포하는 것을 추천한다.&lt;/p&gt;
&lt;h2 id=&quot;downleveliteration&quot; style=&quot;position:relative;&quot;&gt;downlevelIteration&lt;a href=&quot;#downleveliteration&quot; aria-label=&quot;downleveliteration permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ES6에 추가된 이터레이션 기능에 대한 명확한 구현을 함께 생성한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;기본적인 트랜스파일링만을 수행한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;downlevelIteration&lt;/code&gt; 옵션은 타입스크립트가 ES6에서 추가된 &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Spread&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Symbol.iterator&lt;/code&gt; 등의 기능을 보다 명확하게 트랜스파일링을 하도록 만들 수 있는 옵션이다.&lt;/p&gt;
&lt;p&gt;컴파일 타겟인 자바스크립트 버전이 ES6 이상이라면 이 옵션은 크게 의미가 없지만, 크로스 브라우징 등을 위해 ES5 이하의 버전을 컴파일 타겟으로 삼는 경우에는 자바스크립트가 실행되는 런타임 때 이터레이터들이 개발자의 의도와 다르게 동작하는 것을 방지할 수 있다.&lt;/p&gt;
&lt;p&gt;예를 들어 &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;를 사용한 타입스크립트 코드를 ES5로 트랜스파일링한다면, 아래와 같은 결과물을 만나볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;use strict&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; str_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; _i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; str_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; _i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str_1&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;는 ES5에는 없는 기능이므로 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;를 일반적인 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt;문으로 트랜스파일링 한 것이다.&lt;/p&gt;
&lt;p&gt;여기까지 보면 별로 문제가 없는 것 같지만, 사실 이렇게 트랜스파일링된 코드는 원본 코드와 정확히 일치하는 동작을 보여주지는 않는다. 바로 이런 코드 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;🙏&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드에서 사용된 🙏 이모지는 필자가 개인적으로도 아주 애용하고 있는 이모지이다. 단순히 눈에 보이는 문자의 수가 한 개이기 때문에 이 이모지의 길이도 당연히 &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;이라고 생각할 수 있지만, 사실 이모지들의 길이는 &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;이 아니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;🙏&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&apos;👩‍❤️‍💋‍👩&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token comment&quot;&gt;// 11&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 이 이모지의 길이를 사용하여 일반적인 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; 문을 작성하게 되면 제대로 된 문자를 뽑아내기가 어려울 수 있다는 것이다. 무슨 말인지 잘 이해가 안 된다면, 아래 코드를 크롬 개발자도구에 복붙해서 한번 실행시켜보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🙏&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;for문 &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;for/of문 &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;s&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for문 &gt; �
for문 &gt; �

for/of문 &gt; 🙏&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이것이 바로 &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt; 문을 그냥 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt;문으로 트랜스파일링하면 안 되는 이유이다.&lt;/p&gt;
&lt;p&gt;이처럼 이모지의 길이가 1이 아닌 이유를 간단히만 설명하자면, 일단 이모지가 멀티바이트 문자이기 때문이기도 하고 계속 해서 새로운 이모지가 추가되기도 하고 기존 이모지들을 결합한 이모지들이 나오면서 이모지를 표현하는 방법이 괴랄해져서 그렇기도 하다. 이모지 길이에 대한 자세한 내용은 &lt;a href=&quot;https://blog.jonnew.com/posts/poo-dot-length-equals-two&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;이 포스팅&lt;/a&gt;에 잘 설명되어있으니 한번 읽어보도록 하자.&lt;/p&gt;
&lt;p&gt;어찌됐던 여기서 중요한 포인트는 &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt;의 동작이 유사하다고 해서 묻어놓고 트랜스파일링을 했다가는 이런 참사가 발생할 수도 있다는 것이다.&lt;/p&gt;
&lt;p&gt;그래서 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;downlevelIteration&lt;/code&gt;이라는 옵션을 별도로 제공해서 &lt;code class=&quot;language-text&quot;&gt;for/of&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Spread&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Symbol.iterator&lt;/code&gt;와 같은 이터레이션 기능이 개발자의 의도와 다르게 동작하지 않도록 &lt;code class=&quot;language-text&quot;&gt;Symbol.iterator&lt;/code&gt; 같은 기능이 있는지 검사하거나, 아예 이런 기능을 구현해놓은 폴리필까지 함께 추가할 수 있도록 만들어 두었다.&lt;/p&gt;
&lt;h2 id=&quot;emitbom&quot; style=&quot;position:relative;&quot;&gt;emitBOM&lt;a href=&quot;#emitbom&quot; aria-label=&quot;emitbom permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;타입스크립트가 출력 파일을 생성할 때 BOM을 표시한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;타입스크립트가 출력 파일을 생성할 때 BOM을 표시하지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;emitBOM&lt;/code&gt; 옵션은 타입스크립트가 출력 파일을 생성할 때 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%ED%8A%B8_%EC%88%9C%EC%84%9C_%ED%91%9C%EC%8B%9D&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;BOM(Bite Order Mark)&lt;/a&gt;를 표시할지 말지를 결정할 수 있는 옵션이다.&lt;/p&gt;
&lt;p&gt;Bite Order Mark는 특별한 유니코드를 파일의 가장 앞 부분에 추가해서 이 파일이 어떤 인코딩 방식을 사용했는지를 나타내는 방법이다.&lt;/p&gt;
&lt;p&gt;BOM은 애초에 사람이 읽을 목적이 아니라 컴퓨터에게 현재 파일의 인코딩 정보를 알리기 위해서만 사용하기 때문에, 텍스트 에디터나 vim 같은 곳에서 파일을 열어보아도 BOM을 보여주지는 않는다.&lt;/p&gt;
&lt;p&gt;그러나 일반적으로 자바스크립트가 실행되는 런타임 환경에서 굳이 BOM까지 필요한 경우가 흔치 않기도 하고, 유니코드 3.2부터는 BOM을 사용하지 않을 것을 권장하고 있기도 해서, 굳이 켤 필요가 없는 옵션이기도 하다. &lt;small&gt;(타입스크립트 공식 문서에서도 굳이 안 켜도 된다고 하고 있다)&lt;/small&gt;&lt;/p&gt;
&lt;h2 id=&quot;emitdeclarationonly&quot; style=&quot;position:relative;&quot;&gt;emitDeclarationOnly&lt;a href=&quot;#emitdeclarationonly&quot; aria-label=&quot;emitdeclarationonly permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;자바스크립트 없이 타입 선언 파일만을 출력한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;자바스크립트 파일을 포함하여 출력한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;emitDeclarationOnly&lt;/code&gt; 옵션은 Declaration only라는 이름 그대로, 컴파일을 진행할 때 자바스크립트 파일 없이 타입 선언 파일만을 출력할지에 대한 여부를 결정하는 옵션이다.&lt;/p&gt;
&lt;p&gt;보통 타입스크립트를 자바스크립트로 변환할 때 타입스크립트 컴파일러가 아닌 별도의 도구를 사용하는 경우나, 기존에 자바스크립트로 만들어진 모듈에 타입 선언만을 제공해야하는 경우에 사용하게 된다.&lt;/p&gt;
&lt;h2 id=&quot;importhelpers&quot; style=&quot;position:relative;&quot;&gt;importHelpers&lt;a href=&quot;#importhelpers&quot; aria-label=&quot;importhelpers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;출력 파일 내에서 tslib가 제공하는 헬퍼 함수들을 사용한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;tslib가 제공하는 헬퍼 함수를 사용하지 않고 직접 헬퍼를 구현하도록 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; 옵션은 타입스크립트를 자바스크립트 ES5 이하의 버전으로 트랜스파일링할 때 발생하는 헬퍼 함수들을 출력 파일 내에 직접 작성할 것이냐, 아니면 &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; 라이브러리가 제공하는 헬퍼 함수로 대체할 수 있도록 할 것이냐를 결정할 수 있는 옵션이다.&lt;/p&gt;
&lt;p&gt;한번 소스 코드와 출력 파일을 함께 보면서 이해해보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;fn&lt;/code&gt; 함수는 인자로 받은 배열의 맨 앞에 &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;이라는 원소를 추가해서 반환하는 간단한 함수이다. 여러분도 아시다시피 &lt;code class=&quot;language-text&quot;&gt;[...arr]&lt;/code&gt;라는 문법으로 사용할 수 있는 Spread 기능은 ES5에 포함되어있지 않으므로, 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; 라는 헬퍼 함수를 출력 파일 내에 추가하여 Spread 기능을 트랜스파일링한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __spreadArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__spreadArray&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;to&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pack &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; arguments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ar &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;ar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;from&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      ar&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; from&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ar &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__spreadArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 중요한 것은 ES6의 Spread 기능을 구현하기 위해 &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt;라는 함수의 구현이 출력 파일 내에 함께 포함되었다는 것이다. 사실 이런 구현이 출력 파일내에 포함되는 것이 큰 문제는 아닐 수 있지만, 만약 저 &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt;를 다른 곳에서 또 사용해야하는 경우에는 그 모듈에 또 다시 &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; 함수의 구현이 추가되기 때문에 중복된 코드가 발생하게 된다.&lt;/p&gt;
&lt;p&gt;이때 &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; 옵션을 사용하게 되면 이러한 헬퍼 함수들을 &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; 라이브러리에서 가져오도록 변경하여 코드의 중복을 제거할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; __spreadArray &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;tslib&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__spreadArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 되면 &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; 함수를 &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt;에서 불러와서 사용하게 되므로, 매번 &lt;code class=&quot;language-text&quot;&gt;__spreadArray&lt;/code&gt; 함수를 선언할 필요가 사라지기 때문에 코드의 중복을 제거할 수 있다. 하지만 이 옵션을 사용하여 트랜스파일링된 코드는 당연히 &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt; 패키지를 설치되어있어야 제대로 작동하므로, 헬퍼 함수의 중복된 구현을 허용하는 것과 &lt;code class=&quot;language-text&quot;&gt;tslib&lt;/code&gt;를 내 어플리케이션에 설치하는 것의 득과 실을 잘 따져보고 옵션을 사용하도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;importsnotusedasvalues&quot; style=&quot;position:relative;&quot;&gt;importsNotUsedAsValues&lt;a href=&quot;#importsnotusedasvalues&quot; aria-label=&quot;importsnotusedasvalues permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;remove&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;출력 파일에서 런타임 때 필요없는 import 문을 제거한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;preserve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;출력 파일에서 타입 정보는 제거하되, import 문은 유지한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;타입 정보만 가져오는 import 문을 사용했을 때 에러를 발생시킨다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;importsNotUsedAsValues&lt;/code&gt; 옵션은 타입스크립트가 출력 파일을 생성할 때 필요없는 import 구문을 처리하는 방법을 제어할 수 있는 옵션이다. 이 옵션이 가지는 의미를 알기 위해서는 타입스크립트가 import 문을 처리하는 방법에 대해서 조금 알아야 한다.&lt;/p&gt;
&lt;p&gt;기본적으로 타입스크립트가 컴파일을 통해 자바스크립트 파일을 생성할 때, 타입과 관련된 정보는 지워버린다. 코드를 보면서 한번 이해해보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; classBar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; classBar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드를 보면 &lt;code class=&quot;language-text&quot;&gt;InterfaceFoo&lt;/code&gt; 인터페이스를 가져오는 import 문이 자바스크립트 출력 파일 내에서는 사라진 것을 볼 수 있다. 왜냐하면 자바스크립트에는 타입스크립트의 타입이나 인터페이스 같은 기능이 없으니, 타입 정보를 남겨놔봤자 의미가 없기 때문이다.&lt;/p&gt;
&lt;p&gt;물론 앞서 이야기한대로 타입 정보는 어차피 자바스크립트에서 사용할 수 없으니, 이런 정보는 제거하는 것이 맞지만, 만약 &lt;code class=&quot;language-text&quot;&gt;../utils/foo&lt;/code&gt; 모듈이 의도적인 사이드이펙트를 포함하고 있을 경우에는 문제가 발생할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils/foo.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InterfaceFoo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;utils/foo.ts&lt;/code&gt; 모듈은 인터페이스만을 노출하고 있는 모듈이지만, 내부에는 &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt;라는 사이드 이펙트를 포함하고 있다. 이 예시에서는 단순한 콘솔 출력이지만, 실제로 Angular 같은 경우는 이런 모듈 내부에서 명시적으로 모듈을 주입하고 등록하는 사이드 이펙트가 포함되기도 한다.&lt;/p&gt;
&lt;p&gt;문제는 이런 경우에도 타입스크립트는 자바스크립트를 출력할 때 &lt;code class=&quot;language-text&quot;&gt;utils/foo&lt;/code&gt; 모듈을 import 했던 구문 자체를 지워버린다는 것이다. 그러면 당연히 &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt;라는 사이드 이펙트는 자바스크립트 런타임에서 실행되지 않는다. 그래서 이런 경우 개발자들은 의도적으로 사이드 이펙트를 실행시키기 위해 타입스크립트를 속일 수 있는 import 문을 하나 더 추가해야한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; classBar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InterfaceFoo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ClassBar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../utils/bar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; classBar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그래서 타입스크립트 3.8버전에는 “이 import문이 타입 정보만을 가져오는 구문이다”라는 것을 명시적으로 표현할 수 있는 &lt;code class=&quot;language-text&quot;&gt;import type&lt;/code&gt; 기능을 추가했고, 혹여나 일반적인 import 문을 사용하여 타입 정보만을 가져오더라도 import문을 남겨둘 수 있도록 제어할 수 있는 &lt;code class=&quot;language-text&quot;&gt;importsNotUsedAsValues&lt;/code&gt; 옵션을 제공하는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;inlinesourcemap&quot; style=&quot;position:relative;&quot;&gt;inlineSourceMap&lt;a href=&quot;#inlinesourcemap&quot; aria-label=&quot;inlinesourcemap permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;소스맵 파일을 따로 생성한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;소스맵 파일의 내용을 Base64로 인코딩하여 소스 파일에 추가한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; 옵션은 타입스크립트가 컴파일 시 어떤 방식으로 소스맵을 생성할 것인지를 결정하는 옵션이다. 기본적으로 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;*.js.map&lt;/code&gt; 파일의 형태로 소스맵을 제공하는데, 만약 &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt;이 &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;일 경우에는 소스 파일 내부에 주석으로 소스맵을 추가한다.&lt;/p&gt;
&lt;p&gt;간단한 함수를 가지고 있는 모듈을 직접 컴파일해보며 어떤 차이가 있는지 직접 알아보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; 옵션이 꺼져 있는 경우, 타입스크립트는 별도의 소스맵 파일을 생성하고, 컴파일된 JS 파일에는 해당 소스맵의 경로만을 적어두는 형태로 소스맵을 생성한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=math.js.map&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// math.js.map&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;math.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;sources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../../utils/math.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;mappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AAAA,MAAM,CAAC,IAAM,GAAG,GAAG,UAAC,CAAS,IAAK,OAAA,UAAC,CAAS,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAApB,CAAoB,CAAC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 컴파일된 JS 파일에는 소스맵 파일의 경로가 &lt;code class=&quot;language-text&quot;&gt;#sourceMappingURL=math.js.map&lt;/code&gt;의 형태로 추가되고, 소스맵 파일에는 &lt;code class=&quot;language-text&quot;&gt;&quot;sources&quot;: [&quot;../../utils/math.ts&quot;]&lt;/code&gt;처럼 원본 타입스크립트 소스 파일의 경로가 적혀있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; 옵션을 켜게되면 이제 타입스크립트는 소스맵 파일을 생성하지 않고, 컴파일된 JS 파일 내에 직접 소스맵 파일의 내용을 Base64로 인코딩해서 추가한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3V0aWxzL21hdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sR0FBRyxHQUFHLFVBQUMsQ0FBUyxJQUFLLE9BQUEsVUFBQyxDQUFTLElBQUssT0FBQSxDQUFDLEdBQUcsQ0FBQyxFQUFMLENBQUssRUFBcEIsQ0FBb0IsQ0FBQyJ9&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;inlinesources&quot; style=&quot;position:relative;&quot;&gt;inlineSources&lt;a href=&quot;#inlinesources&quot; aria-label=&quot;inlinesources permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;인라인 소스맵에 소스 코드의 내용은 포함시키지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;인라인 소스맵에 소스 코드의 내용도 함께 포함시킨다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;inlineSources&lt;/code&gt; 옵션은 &lt;code class=&quot;language-text&quot;&gt;inlineSourceMap&lt;/code&gt; 옵션을 사용하여 만들어낸 인라인 소스맵에 원본 소스 코드의 내용도 함께 포함시킬 것인지 여부를 결정한다.&lt;/p&gt;
&lt;p&gt;이 옵션의 값이 &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;인 경우, 인라인 소스맵에 &lt;code class=&quot;language-text&quot;&gt;sourceContent&lt;/code&gt;라는 필드가 추가되고 해당 필드에는 소스 코드의 내용이 함꼐 포함된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3V0aWxzL21hdGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sR0FBRyxHQUFHLFVBQUMsQ0FBUyxJQUFLLE9BQUEsVUFBQyxDQUFTLElBQUssT0FBQSxDQUFDLEdBQUcsQ0FBQyxFQUFMLENBQUssRUFBcEIsQ0FBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBhZGQgPSAoeDogbnVtYmVyKSA9PiAoeTogbnVtYmVyKSA9PiB4ICsgeTtcbiJdfQ==&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Decoding된 소스맵&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;math.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../../utils/math.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AAAA,MAAM,CAAC,IAAM,GAAG,GAAG,UAAC,CAAS,IAAK,OAAA,UAAC,CAAS,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAApB,CAAoB,CAAC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sourcesContent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;export const add = (x: number) =&gt; (y: number) =&gt; x + y;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;애초에 &lt;a href=&quot;https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/preview#&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;소스맵의 스펙&lt;/a&gt; 상 &lt;code class=&quot;language-text&quot;&gt;sourceContent&lt;/code&gt; 필드는 원본 소스 파일에 접근하지 못한 경우를 대응하기 위한 일종의 예외처리에 가까우므로, 굳이 켜지 않아도 큰 문제가 없는 옵션이기도 하다.&lt;/p&gt;
&lt;h2 id=&quot;noemit&quot; style=&quot;position:relative;&quot;&gt;noEmit&lt;a href=&quot;#noemit&quot; aria-label=&quot;noemit permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일 후에 출력 파일을 내보낸다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일 후에 출력 파일을 내보내지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;noEmit&lt;/code&gt; 옵션은 이름 그대로 타입스크립트가 컴파일을 한 이후에 출력 파일들을 내보낼 것인지에 대한 동작을 결정한다. 설명만 들어보면 이런 경우가 필요할까 싶기는 한데, 생각보다 유용하게 자주 쓰이는 옵션이다.&lt;/p&gt;
&lt;p&gt;대표적인 예로는 CI나 Git Hook 같은 타이밍에 정적 타입 체크만 진행해야 하는 경우 &lt;code class=&quot;language-text&quot;&gt;tsc --noEmit&lt;/code&gt;와 같은 명령어를 NPM 스크립트로 등록해놓거나, Webpack, Parcel, Rollup 등의 도구를 사용하여 컴파일을 진행할 때도 정적 타입 체크만을 TSC에게 시키기 위해 해당 옵션을 사용하는 경우가 많다.&lt;/p&gt;
&lt;h2 id=&quot;noemithelpers&quot; style=&quot;position:relative;&quot;&gt;noEmitHelpers&lt;a href=&quot;#noemithelpers&quot; aria-label=&quot;noemithelpers permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일된 파일에 &lt;code class=&quot;language-text&quot;&gt;__awaiter&lt;/code&gt;와 같은 헬퍼 함수를 포함시킨다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일된 파일에는 &lt;code class=&quot;language-text&quot;&gt;__awaiter&lt;/code&gt;와 같은 헬퍼 함수를 포함시키지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; 옵션은 컴파일이 완료된 출력 파일에 &lt;code class=&quot;language-text&quot;&gt;__awaiter&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;__generator&lt;/code&gt;와 같은 헬퍼 함수들을 포함시킬지 여부를 결정한다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; 옵션의 동작이 &lt;a href=&quot;#importhelpers&quot;&gt;importHelpers&lt;/a&gt;와 유사하기 때문에 조금 헷갈릴 수 있다. &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt; 옵션은 헬퍼 함수들의 구현을 “소스에 포함할지”, “다른 곳에서 import할지”를 결정한다면, &lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; 옵션은 헬퍼 함수들의 구현을 “소스에 포함할지”, “아예 하지 않을 것인지”를 결정하기 때문이다.&lt;/p&gt;
&lt;p&gt;이 차이점을 직접 컴파일된 코드를 보면서 알아보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// importHelpers, noEmitHelpers가 모두 꺼져있는 경우에는 출력 파일에 헬퍼의 구현도 포함된다&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __awaiter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__awaiter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _arguments&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __generator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__generator&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__awaiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/*return*/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// importHelper가 켜져있는 경우에는 외부에서 헬퍼를 가져온다&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; __awaiter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; __generator &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tslib&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__awaiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/*return*/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// noEmitHelpers가 켜져있는 경우에는 아예 헬퍼를 가져오거나 선언하는 코드 조차 없다&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&apos;use strict&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__awaiter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__generator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/*return*/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;noEmitHelpers&lt;/code&gt; 옵션이 모두 켜져있다면 헬퍼 함수를 “외부에서 가져올 것이냐”, “출력 파일에 포함시키지 않을 것이냐”라는 설정이 충돌하게 되는데, 이 경우에는 &lt;code class=&quot;language-text&quot;&gt;importHelpers&lt;/code&gt;의 동작을 우선적으로 따르게 되니 이 점을 주의하도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;noemitonerror&quot; style=&quot;position:relative;&quot;&gt;noEmitOnError&lt;a href=&quot;#noemitonerror&quot; aria-label=&quot;noemitonerror permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일 중 에러가 발생하더라도 출력 파일을 내보낸다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;컴파일 중 에러가 발생한 경우 출력 파일을 내보내지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;noEmitOnError&lt;/code&gt; 옵션은 이름 그대로 컴파일 중 여러가지 요인으로 인해 에러가 발생하게 되는 경우 출력 파일을 내보낼 것인지에 대한 여부를 결정한다. 만약 이 옵션이 켜져있는 경우, 컴파일 중 에러가 발생하면 출력 파일이 내보내지지 않는다.&lt;/p&gt;
&lt;p&gt;이렇게만 보면 “당연히 에러가 나면 출력 파일을 안 만드는 게 맞지 않나?”라고 생각할 수 있지만, TSC의 Watch 옵션을 사용하고 있는 개발환경 같은 경우는 컴파일 중 에러가 발생해도 출력 파일을 생성하고 그로 인해 발생하는 사이드 이펙트 또한 함께 관찰하는 것이 더 편할 수도 있기 때문에, 개발환경에서는 해당 옵션을 끄고 운영환경 배포를 위한 빌드 타임 때는 켜놓는 것을 추천한다.&lt;/p&gt;
&lt;h2 id=&quot;preserveconstenums&quot; style=&quot;position:relative;&quot;&gt;preserveConstEnums&lt;a href=&quot;#preserveconstenums&quot; aria-label=&quot;preserveconstenums permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; 키워드를 사용한 Enum 선언을 컴파일 타임 때 제거한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; 키워드를 사용한 Enum 선언을 컴파일 타임 때 제거하지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;preserveConstEnums&lt;/code&gt; 옵션은 컴파일 타임 때 &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/enums.html#const-enums&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;const enum&lt;/a&gt; 키워드를 사용한 Enum 선언을 제거할 것인지에 대한 옵션이다. 타입스크립트는 런타임 때의 메모리 비용을 절약하기 위해 &lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; 키워드로 선언한 Enum의 값을 참조하는 부분을 해당 Enum의 값으로 치환한다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;enum&lt;/code&gt; 키워드만을 사용하여 선언한 Enum과 다르게 &lt;code class=&quot;language-text&quot;&gt;const enum&lt;/code&gt; 키워드를 사용한 Enum은 반드시 상수 값만 가지는 것이 보장되기 때문에 참조 투명성 또한 보장되고, 결국 컴파일 타임 때 값을 그냥 치환해버려도 아무 문제가 없는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; Foo &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Foo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; Foo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Foo&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Foo &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* A */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;= Foo.A가 아닌, 값으로 치환되었다&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 컴파일된 코드를 자세히 보면, Enum을 표현하기 위해 &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt;라는 변수를 선언하고 IIFE를 사용하여 해당 변수에 값을 할당하고 있지만, 정작 이 변수에 접근하는 부분은 없는 것을 알 수 있다. 즉, 이 JS 코드가 실행되는 런타임 환경에서는 &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt;라는 변수가 없어도 아무 문제가 없다는 것이다.&lt;/p&gt;
&lt;p&gt;이때 &lt;code class=&quot;language-text&quot;&gt;preserveConstEnums&lt;/code&gt; 옵션의 값을 &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;로 설정하면 이렇게 런타임에서는 아무 의미없는 Enum 선언을 제거할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* A */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; 4번째 시리즈인 &lt;code class=&quot;language-text&quot;&gt;Emit&lt;/code&gt; 편을 마무리했다. Emit과 관련된 역할을 하는 옵션들은 주로 TSC와 다른 도구를 결합하여 사용하거나, 번들 사이즈를 최적화해야하는 경우에 주로 건드리게 되는데, 필자 또한 꽤나 오랜만에 이 옵션들을 공부하게 되었던 지라 예전에 써본 옵션들이 있음에도 불구하고 기억이 가물가물 했던 것 같다.&lt;/p&gt;
&lt;p&gt;이상으로 [tsconfig의 모든 것] Compiler options / Emit 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Find Your Own Color – Setting a Direction for Growth]]></title><description><![CDATA[Lately, I’ve been doing more mentoring — reviewing résumés, conducting mock interviews, and discussing growth strategies with developers who are relatively new to the profession. These conversations have been happening more and more frequently. As these experiences accumulated, I started noticing patterns in the struggles people face. Today, I want to talk about those patterns.]]></description><link>https://evan-moon.github.io/2021/09/10/developer-direction-of-effort/en/</link><guid isPermaLink="false">20210910-developer-direction-of-effort-en</guid><pubDate>Fri, 10 Sep 2021 11:30:31 GMT</pubDate><content:encoded>&lt;p&gt;Lately, I’ve been doing more mentoring — reviewing résumés, conducting mock interviews, and discussing growth strategies with developers who are relatively new to the profession. These conversations have been happening more and more frequently.&lt;/p&gt;
&lt;p&gt;As these experiences accumulated, I started noticing patterns in the struggles people face. Today, I want to talk about those patterns.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;These patterns show up not just in mentoring but in actual interviews as well, so in a way, this post might serve as interview advice too. Of course, developers with some years under their belt probably have an intuitive sense of these things already, so I think this post will be most helpful for those in the entry-level to two-year-experience range.&lt;/p&gt;
&lt;p&gt;Going forward, I’ll continue framing the discussion around the emotions and situations of this group. Since writing “entry-level to two-year experience” every time would be tedious, I’ll just call this segment “juniors.”&lt;/p&gt;
&lt;h2 id=&quot;effort-without-direction&quot; style=&quot;position:relative;&quot;&gt;Effort Without Direction&lt;a href=&quot;#effort-without-direction&quot; aria-label=&quot;effort without direction permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the most common concerns I hear from junior developers during mentoring is: “I can’t figure out the right direction for my growth.”&lt;/p&gt;
&lt;p&gt;In my experience, people who join the &lt;a href=&quot;https://lubycon.io&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Lubycon mentoring project&lt;/a&gt; or request mentoring through other platforms tend to be people who are self-motivated and working hard.&lt;/p&gt;
&lt;p&gt;But because the direction of that effort isn’t clear, doubts like “Am I even on the right path…?” creep in, and they feel anxious despite putting in the work.&lt;/p&gt;
&lt;p&gt;To ease that anxiety and find stability, it’s very easy to channel effort toward a direction that feels safe — meaning what lots of other people are doing. Common examples include daily commits (1 commit per day), writing TIL (Today I Learned) posts, and clone coding. In mentoring sessions and interviews, I see a remarkable number of junior developers engaging in these activities.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/39cecaa3a513c543dbe8543953b2ff61/07d7d/contributions.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 20%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAABYlAAAWJQFJUiTwAAABBklEQVR42h2O21KCUABF+f8/qabppcnKptKki6WN2qQoGmDckcMBQVBzxfi2935YaytZkTP2ZvxmLvPYRAvmiEIS5YJxNEcLF0RZjJk6zGIDp/DRpYWd+7hlgC5MvoWOnhhsdiVKICJUp88g0rizn3nwXuiEfYZ1V4Mej8s3hr7GuBZdW21uww5PfpfRasqZ3eDUaNDyuvSTL6JKoCRlipb+sJBLLs17mo5aw6Z4acir+OTcuKHtvfPhjWhaKld2qwb2mEmTC7PJyeSSkdSOgnJfoVT7Lb6MCOQKJ/ZZCpckTY/35X5NUmakuzWiSlnvcuS23upc/G0QG4mbBQxWExa+xeFw4B9gECNpMFTS+QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;contributions&quot; title=&quot;&quot; src=&quot;/static/39cecaa3a513c543dbe8543953b2ff61/6af66/contributions.png&quot; srcset=&quot;/static/39cecaa3a513c543dbe8543953b2ff61/69538/contributions.png 160w,
/static/39cecaa3a513c543dbe8543953b2ff61/72799/contributions.png 320w,
/static/39cecaa3a513c543dbe8543953b2ff61/6af66/contributions.png 640w,
/static/39cecaa3a513c543dbe8543953b2ff61/d9199/contributions.png 960w,
/static/39cecaa3a513c543dbe8543953b2ff61/21b4d/contributions.png 1280w,
/static/39cecaa3a513c543dbe8543953b2ff61/07d7d/contributions.png 1478w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;The contribution graph on a GitHub profile is data showing how active someone is in development-related activities.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Of course, doing &lt;em&gt;something&lt;/em&gt; for your growth is a great attitude. But blindly jumping in because everyone else is doing it, or because a bootcamp told you it’s necessary for landing a job, may not be the best approach.&lt;/p&gt;
&lt;p&gt;If you’re just starting out, simply committing every day or writing down what you learned on a blog might generate some growth. That’s because at this stage, rapidly getting comfortable with coding directly translates to growth.&lt;/p&gt;
&lt;p&gt;But as you know, this phase passes fairly quickly. The more comfortable you get with coding, the more you encounter familiar things rather than new ones — and from that point on, simply coding alone makes it increasingly difficult to improve or learn something new.&lt;/p&gt;
&lt;p&gt;Eventually, you start to feel that daily commits or TIL posts alone aren’t producing the same growth velocity they used to. And that’s when this question hits:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What should I study next to go further? What kind of effort should I be making now?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the state of putting in effort without a clear direction. You need to nail both the &lt;em&gt;volume&lt;/em&gt; and the &lt;em&gt;direction&lt;/em&gt; of your effort — only then can you get maximum return on the same amount of investment.&lt;/p&gt;
&lt;h2 id=&quot;thinking-about-the-cost-of-effort&quot; style=&quot;position:relative;&quot;&gt;Thinking About the Cost of Effort&lt;a href=&quot;#thinking-about-the-cost-of-effort&quot; aria-label=&quot;thinking about the cost of effort permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;People tend to think of the effort they put into achieving something as a kind of cost — and it genuinely is. You’re investing your time and energy to create new value. That’s why we instinctively seek the most efficient form of effort — the direction where minimal input yields maximum return.&lt;/p&gt;
&lt;p&gt;Unfortunately, there’s no predetermined shortcut in life. But you can gradually improve your effort’s efficiency by constantly asking yourself where the right direction might be. The method that maximizes efficiency differs from person to person, and the only way to find it is through your own reflection.&lt;/p&gt;
&lt;p&gt;The problem is that many people can’t afford the mental space for this kind of reflection. Someone who experienced rapid growth through daily commits or TIL tends to think “I’m not growing because I’m not trying hard enough” — because of that past experience, or simply out of inertia.&lt;/p&gt;
&lt;p&gt;But as I mentioned, misdirected effort leads to lower efficiency, and lower efficiency means the value of what your effort produces decreases.&lt;/p&gt;
&lt;p&gt;For those who aren’t sure what “the value of your effort decreasing” means, I want to explain this from two perspectives: the market perspective and the perspective of continuous personal growth.&lt;/p&gt;
&lt;h3 id=&quot;the-market-perspective&quot; style=&quot;position:relative;&quot;&gt;The Market Perspective&lt;a href=&quot;#the-market-perspective&quot; aria-label=&quot;the market perspective permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, the place where the returns on your effort shine most brightly is the job market. And since the job market is literally a market, most of the principles we know about markets apply.&lt;/p&gt;
&lt;p&gt;The principle I want to discuss is “inflation.” The basic definition of inflation is when something becomes so common in the market that its value drops. Usually we talk about the value of money dropping, but in the job market, think of it as the value of skills or credentials.&lt;/p&gt;
&lt;p&gt;The most classic example of this inflation is education. In the 1970s, having a college degree commanded respect and gave you a significant advantage in job hunting. But by the 2020s, with college enrollment rates approaching 79%, simply having a bachelor’s degree no longer carries much weight.&lt;/p&gt;
&lt;p&gt;In other words, the bachelor’s degree we spent 12 years earning — from elementary school through college entrance exams — has become something that most people in the job market possess. It’s become an ordinary commodity, and an ordinary commodity that everyone has is, by definition, one that has lost its value.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/16a130e56cdf12fffd6fd91b275a887d/36dd4/graduate.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMFAgb/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAVMlaZvHOGX/xAAZEAADAQEBAAAAAAAAAAAAAAAAAQITETH/2gAIAQEAAQUCUigXmlGtc0s//8QAFhEBAQEAAAAAAAAAAAAAAAAAABES/9oACAEDAQE/Aco//8QAFhEBAQEAAAAAAAAAAAAAAAAAABES/9oACAECAQE/AdK//8QAGBAAAgMAAAAAAAAAAAAAAAAAABABMnH/2gAIAQEABj8Ceq0n/8QAGRABAQEBAQEAAAAAAAAAAAAAAREAUUHx/9oACAEBAAE/IVzhKz3u7ZRq5cRjZvob/9oADAMBAAIAAwAAABDTH//EABcRAAMBAAAAAAAAAAAAAAAAAAEQEUH/2gAIAQMBAT8QEan/xAAXEQADAQAAAAAAAAAAAAAAAAABEBFB/9oACAECAQE/EDeL/8QAHBABAQADAAMBAAAAAAAAAAAAAREAIUFRYXHw/9oACAEBAAE/EB7Wh4MPhuTX4HAgJvocRvUKzX7uFKtsFkmiZYKuuvP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;graduate&quot; title=&quot;&quot; src=&quot;/static/16a130e56cdf12fffd6fd91b275a887d/36dd4/graduate.jpg&quot; srcset=&quot;/static/16a130e56cdf12fffd6fd91b275a887d/0913d/graduate.jpg 160w,
/static/16a130e56cdf12fffd6fd91b275a887d/cb69c/graduate.jpg 320w,
/static/16a130e56cdf12fffd6fd91b275a887d/36dd4/graduate.jpg 512w&quot; sizes=&quot;(max-width: 512px) 100vw, 512px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    As of 2021, the proportion of college graduates has grown compared to the past,&lt;br&gt;
    and having a degree no longer signals that you&apos;re an exceptional talent.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;This is a fundamental market principle: when everyone has something, its value drops. And this principle applies to hiring as well. The job market is essentially a jungle of supply and demand where you have to compete against others to survive.&lt;/p&gt;
&lt;p&gt;To survive in this jungle, you need to demonstrate that you’re better at the job than others, that you have higher growth potential — sending the message “invest in me and you won’t regret it” to companies, our consumers. That’s why people try so hard to graduate from good universities, earn certifications, and study abroad.&lt;/p&gt;
&lt;p&gt;The bottom line: you need to be a differentiated person, a desirable product in the job market. This is no different for developers — the only difference is that the differentiation criteria focus on programming skills rather than credentials.&lt;/p&gt;
&lt;p&gt;But the problem is that many people don’t think deeply about whether a particular asset will serve as a weapon in the job market — or whether it’s a weapon at all. They just think they need it because other people already have it. Much like our parents told us we absolutely must graduate college to make a living.&lt;/p&gt;
&lt;p&gt;Sure, having it is probably better than not having it. But relative to the 12 years of effort you invested, a bachelor’s degree probably doesn’t guarantee proportional value. This is especially true in the IT industry, which values ability over credentials.&lt;/p&gt;
&lt;p&gt;Similarly, activities like daily commits, TIL, and clone coding are already widely known. Bootcamps are even providing explicit guidance that these activities help with getting hired. When reviewing résumés, I can definitely feel that far more people are doing these activities than before.&lt;/p&gt;
&lt;p&gt;In other words, these activities have become commodities that too many people possess. Simply having done them no longer makes a strong impression on an interviewer — just like a bachelor’s degree.&lt;/p&gt;
&lt;h3 id=&quot;the-perspective-of-continuous-personal-growth&quot; style=&quot;position:relative;&quot;&gt;The Perspective of Continuous Personal Growth&lt;a href=&quot;#the-perspective-of-continuous-personal-growth&quot; aria-label=&quot;the perspective of continuous personal growth permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Second, as I mentioned, activities like daily commits, TIL, and clone coding only generate meaningful growth during the very earliest stages of learning to code. There are limits to what you can achieve by simply being exposed to coding frequently.&lt;/p&gt;
&lt;p&gt;Moreover, since these activities emphasize consistency, they can easily become mere habits. You end up just “doing them” without deeply considering what you’re learning from them or why you’re doing them in the first place.&lt;/p&gt;
&lt;p&gt;The reasons people fall into this habit vary — inertia from having done it consistently, anxiety about falling behind if they stop — but regardless of the reason, continuing to pour effort in without clear direction can never produce sustained growth.&lt;/p&gt;
&lt;p&gt;Worse, if you forget the original purpose of these activities and just repeat them mechanically, there’s a risk of becoming fixated on results over purpose — making meaningless commits to fill the daily quota, or even faking commit timestamps. This is actually a recurring theme in many people’s retrospectives on daily commits.&lt;/p&gt;
&lt;p&gt;Ultimately, even if you have both the passion for growth and the energy to execute, if you can’t define a clear direction for yourself, your energy might end up invested in the wrong places.&lt;/p&gt;
&lt;h2 id=&quot;so-what-should-i-do&quot; style=&quot;position:relative;&quot;&gt;So What Should I Do?&lt;a href=&quot;#so-what-should-i-do&quot; aria-label=&quot;so what should i do permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Alright, so what should you actually do? Obviously, I can’t provide a one-size-fits-all answer with perfectly clear action items in a single blog post.&lt;/p&gt;
&lt;p&gt;But I can at least talk about things worth reflecting on — things you should sit down and think about seriously.&lt;/p&gt;
&lt;h3 id=&quot;beware-of-fixating-on-the-act-itself&quot; style=&quot;position:relative;&quot;&gt;Beware of Fixating on the Act Itself&lt;a href=&quot;#beware-of-fixating-on-the-act-itself&quot; aria-label=&quot;beware of fixating on the act itself permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What does it mean to fixate on the act itself? Let me use the popular activity of daily commits as an example.&lt;/p&gt;
&lt;p&gt;The act of “one commit per day” means nothing more and nothing less than making at least one commit each day. If you focus on the act itself, when someone asks “Why do you do daily commits?”, you can only answer with something like “Because it’s important to do something consistently.”&lt;/p&gt;
&lt;p&gt;But as I discussed, once you’re past the very earliest stage of learning to code, mere consistency alone can’t produce sustained growth. If you’ve reached this stage, it’s time to ask yourself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is the essential value that daily commits create?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The answer will differ for each person, but I believe the essential value of daily commits is closer to “consistently working on my own development projects without letting go.”&lt;/p&gt;
&lt;p&gt;In other words, the “commit” in “daily commit” doesn’t mean any random commit — it means commits toward building your own side project, contributing to open source, and so on.&lt;/p&gt;
&lt;p&gt;As you know, a commit is ultimately part of the process of building something. But if you fixate on the act of committing itself, the goal of building something disappears into the distance, and only the “commit” remains.&lt;/p&gt;
&lt;p&gt;When you focus solely on the act itself, you fail to capture the real benefits these activities offer and end up wasting energy.&lt;/p&gt;
&lt;h3 id=&quot;diligence-isnt-a-strong-weapon&quot; style=&quot;position:relative;&quot;&gt;Diligence Isn’t a Strong Weapon&lt;a href=&quot;#diligence-isnt-a-strong-weapon&quot; aria-label=&quot;diligence isnt a strong weapon permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A few years ago, I had a casual conversation with someone who had graduated from a bootcamp. I heard something interesting: at their bootcamp, students were told that writing TIL posts on their blogs was necessary for getting hired.&lt;/p&gt;
&lt;p&gt;Of course, bootcamps are businesses, not charities, so they need to maximize results with minimal resources. Providing customized education for every individual is prohibitively expensive, which is why they end up creating standardized curricula and funneling people through them. &lt;em&gt;(Most of the education industry works this way, honestly.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So I asked:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Why does writing TIL posts on your blog help with getting hired?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I asked because I believe hiring involves an enormous number of variables — company size, current business conditions, the talent pool in the market, existing team members’ capacity — and I wasn’t convinced that any specific activity would universally help with employment.&lt;/p&gt;
&lt;p&gt;The answer I got was: “Isn’t it data that shows diligence?”&lt;/p&gt;
&lt;p&gt;Honestly, learning something new every single day and writing about it on a blog is no small feat. How can anyone possibly learn something new every single day?&lt;/p&gt;
&lt;p&gt;Of course, a developer who just started coding might encounter new knowledge daily. But the more comfortable you get with coding, the less that happens. You &lt;em&gt;can&lt;/em&gt; sustain this pattern by actively seeking out new knowledge, but it takes considerable effort.&lt;/p&gt;
&lt;p&gt;And if the result of all that effort is merely to demonstrate “diligence” — well, personally, I don’t think that’s a good trade.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because &lt;strong&gt;companies don’t hire people based on diligence alone.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Companies exist to generate profit. So naturally, when they hire, they want people who will earn back more than what’s invested in them. Diligence might be one criterion for evaluating such people, but it’s not a critical factor. If someone is a bit lazier than average but does great work, helps the team grow, and generates revenue — that’s fine.&lt;/p&gt;
&lt;p&gt;On top of that, as I mentioned, TIL is already a widely recommended activity across multiple bootcamps, and many junior developers are doing it. Inflation has already arrived — simply having done it consistently is no longer that attractive in the job market.&lt;/p&gt;
&lt;p&gt;So if you want TIL to be your weapon, you need something beyond mere consistency and diligence — something that differentiates you. For instance, diving deep into areas most people don’t study, or showing an extraordinary five-year streak of TIL posts without missing a single day.&lt;/p&gt;
&lt;p&gt;To create these differentiating factors, you need to think about what value TIL truly provides.&lt;/p&gt;
&lt;p&gt;TIL isn’t something you do to get hired. It’s an archive where you observe, learn, and record things to hand off to your future self. Yet many people write TIL posts as little more than rough, unorganized notes. And with notes that disorganized, revisiting them a year or two later for review won’t be easy.&lt;/p&gt;
&lt;p&gt;This is a textbook example of using a good tool in a bad way. If you’ve been doing TIL or daily commits for the sake of employment, it’s time to reflect on what value you can genuinely extract from these activities and how that value can fuel your growth.&lt;/p&gt;
&lt;p&gt;Nobody else will do this thinking for you, and no one will teach you the answer. It certainly won’t come quickly, but I recommend practicing — even just a little each day — the habit of questioning whether what you’re currently doing truly has meaning.&lt;/p&gt;
&lt;h3 id=&quot;build-intrinsic-motivation&quot; style=&quot;position:relative;&quot;&gt;Build Intrinsic Motivation&lt;a href=&quot;#build-intrinsic-motivation&quot; aria-label=&quot;build intrinsic motivation permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last thing I want to talk about is building intrinsic motivation. This connects to the earlier discussion about “activities done for the sake of getting hired or changing jobs” — because landing a job or making a career move is the quintessential example of external motivation.&lt;/p&gt;
&lt;p&gt;Imagine you’ve been diligently doing daily commits or TIL to get hired.&lt;/p&gt;
&lt;p&gt;The developer market currently has more demand than supply, and company founders are always asking “Know any good developers?” — so you’ll probably land a job eventually. &lt;em&gt;(Everyone feels anxious during the process, but people tend to land jobs more easily than they expect.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;OK, so you’ve achieved your goal. Should you keep doing daily commits or TIL?&lt;/p&gt;
&lt;p&gt;Maybe inertia carries you for a while. But once you start adapting to new people, new code, and a new environment at your job, it’s easy to stop — because you’re tired, or because adapting to the job takes priority over personal development.&lt;/p&gt;
&lt;p&gt;The reason you stop might not actually matter that much. Because the moment you achieved your goal of getting hired, the very motivation to continue these labor-intensive, diligence-demanding activities simply vanished.&lt;/p&gt;
&lt;p&gt;This is the fundamental problem with external motivation. Behavior driven by external motivation is easily abandoned the moment the source of that motivation disappears.&lt;/p&gt;
&lt;p&gt;That’s why motivation should stem from intrinsic sources — like growth and genuine interest — rather than external conditions like employment or job changes.&lt;/p&gt;
&lt;p&gt;Intrinsic motivation can also collapse due to internal factors like burnout, but at least it’s far more robust than motivation that evaporates the instant you hit your target.&lt;/p&gt;
&lt;p&gt;Even if you’ve never deeply considered external versus intrinsic motivation, everyone instinctively knows which one is more robust.&lt;/p&gt;
&lt;p&gt;If you were an interviewer and asked “Why do you write TIL?”, would you trust the person who says “To get hired” more, or the person who says “Because I enjoy developing” or “Because it helps me grow”?&lt;/p&gt;
&lt;p&gt;The first answer naturally provokes the thought: “So they’ll stop once they’re hired?” And that reaction is exactly the risk that external motivation creates.&lt;/p&gt;
&lt;p&gt;Of course, most people nod in agreement when I explain it with examples like this. But the truth is, we’re all very accustomed to lives driven by external motivation — and even I, the one writing this, find myself increasingly dependent on the external motivation of money as I get older. &lt;del&gt;&lt;em&gt;(Housing prices are absolutely maddening…)&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;Ultimately, what I want to say in this post isn’t that you should eliminate external motivation entirely. That’s impossible, and sometimes external motivation can create even greater momentum. But I do think it’s worth reflecting at least once on whether the motivation you’re currently depending on is sustainable going forward, and whether it truly helps your growth.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This might sound somewhat idealistic. After all, if you’re in an urgent, desperate situation where you need a job right now, it’s hard to find the headspace for this kind of reflection.&lt;/p&gt;
&lt;p&gt;But everything I’ve discussed in this post will absolutely help your job search and career moves. Your real enemy is the anxiety whispering inside you: “Everyone else is working hard while I’m wasting time on these thoughts” or “I don’t have time to think — I just need to do something.”&lt;/p&gt;
&lt;p&gt;Developers with relatively little experience often don’t have many weapons to showcase in the job market. So to put their best foot forward in interviews, they focus on fundamentals like algorithm problems and language comprehension, or on immediately actionable activities like daily commits.&lt;/p&gt;
&lt;p&gt;Studying fundamentals is indeed essential — you could call it a developer’s basic literacy. And activities like daily commits or TIL can help you demonstrate qualities like diligence. But what matters is that interviewers ultimately aren’t looking for someone who’s merely knowledgeable in theory or just diligent — they’re looking for someone who can “get things done, whatever it takes.”&lt;/p&gt;
&lt;p&gt;In other words, you need a strategy to stand out as a compelling talent in the job market. And crafting that strategy requires “effort with a clear direction.”&lt;/p&gt;
&lt;p&gt;Before starting anything, try visualizing what you want from this effort and who you want to become. Establish your direction, then execute. If you keep practicing this, I believe you’ll eventually develop your own know-how and strategy to showcase what makes you special in the market.&lt;/p&gt;
&lt;p&gt;This concludes my post: How to Find Your Own Color — Setting a Direction for Growth.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[나만의 색깔을 찾는 방법 – 성장의 방향성을 설정하자]]></title><description><![CDATA[최근 개인적으로 이런 저런 멘토링을 하며 이력서 리뷰, 모의 면접을 진행하는 등 개발자로써 일을 시작한 지 오래 되지 않으신 분들의 고민을 듣고 궁금한 점들을 물어보며 함께 성장의 방향성에 대해서 논의하는 경험이 점점 잦아지고 있다. 이런 경험이 반복되다보니 이 분들이 어려움을 겪고 있는 상황에 대해서 어느 정도 패턴이 보이기 시작했는데, 오늘은 이 패턴에 대한 이야기를 조금 해보려고 한다.]]></description><link>https://evan-moon.github.io/2021/09/10/developer-direction-of-effort/</link><guid isPermaLink="false">20210910-developer-direction-of-effort</guid><pubDate>Fri, 10 Sep 2021 11:30:31 GMT</pubDate><content:encoded>&lt;p&gt;최근 개인적으로 이런 저런 멘토링을 하며 이력서 리뷰, 모의 면접을 진행하는 등 개발자로써 일을 시작한 지 오래 되지 않으신 분들의 고민을 듣고 궁금한 점들을 물어보며 함께 성장의 방향성에 대해서 논의하는 경험이 점점 잦아지고 있다.&lt;/p&gt;
&lt;p&gt;이런 경험이 반복되다보니 이 분들이 어려움을 겪고 있는 상황에 대해서 어느 정도 패턴이 보이기 시작했는데, 오늘은 이 패턴에 대한 이야기를 조금 해보려고 한다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;또한 이 패턴은 비단 멘토링 뿐 아니라 면접에서도 자주 보이는 패턴이기 때문에, 어떻게 보면 면접에 대한 팁이 될 수도 있을 거라고 생각한다. 물론 연차가 어느 정도 되시는 분들은 짬에서 나오는 바이브가 있는 만큼 알잘딱하고 계실 것이라고 생각하기 때문에, 이 글은 상대적으로 일을 해온 경험이 적은 신입 ~ 2년차 정도의 분들에게 더 도움이 될만한 글이라는 점을 말씀드리고 싶다.&lt;/p&gt;
&lt;p&gt;그러므로 이후의 글에서도 계속 신입 ~ 2년차 분들의 감정과 상황에 맞춰서 이야기를 풀어나갈 예정인데, 매번 신입 ~ 2년차라고 이야기하기에는 손가락도 아프고 번거로우니 이 세그먼트를 “주니어”라고 부르도록 하겠다.&lt;/p&gt;
&lt;h2 id=&quot;방향성이-모호한-노력&quot; style=&quot;position:relative;&quot;&gt;방향성이 모호한 노력&lt;a href=&quot;#%EB%B0%A9%ED%96%A5%EC%84%B1%EC%9D%B4-%EB%AA%A8%ED%98%B8%ED%95%9C-%EB%85%B8%EB%A0%A5&quot; aria-label=&quot;방향성이 모호한 노력 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;필자가 멘토링을 하면서 주니어 개발자 분들에게서 가장 많이 듣는 고민 중 하나는 바로 “성장의 방향성을 못 잡겠다”라는 것이다.&lt;/p&gt;
&lt;p&gt;지금까지의 필자의 경험상, &lt;a href=&quot;https://lubycon.io&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;루비콘 멘토링 프로젝트&lt;/a&gt;에 참여하고 계신 분들이나 다른 플랫폼을 통해 필자에게 멘토링을 신청하시는 분들은 스스로 성장에 대한 모티베이션을 부여하고 열심히 노력하고 계신 분들이 많았다.&lt;/p&gt;
&lt;p&gt;하지만 이 노력의 방향성이 명확하지 않다보니 “이 길이 맞나…?”와 같은 의문이 들게 되고, 열심히 노력을 하면서도 불안한 마음이 드는 것이다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 이 불안감을 지우고 안정성을 찾기 위해 어느 정도 안정성이 보장된 방향, 즉 많은 사람들이 하고 있는 방향으로 노력이라는 리소스를 사용하게 되기가 굉장히 쉽다. 그런 방향 중 대표적인 예는 1일 1커밋, TIL 작성, 클론 코딩 등이 있는데, 실제로 멘토링을 하거나 면접을 보다보면 요즘 정말 많은 주니어 개발자 분들이 이런 활동들을 하고 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/39cecaa3a513c543dbe8543953b2ff61/07d7d/contributions.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 20%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAABYlAAAWJQFJUiTwAAABBklEQVR42h2O21KCUABF+f8/qabppcnKptKki6WN2qQoGmDckcMBQVBzxfi2935YaytZkTP2ZvxmLvPYRAvmiEIS5YJxNEcLF0RZjJk6zGIDp/DRpYWd+7hlgC5MvoWOnhhsdiVKICJUp88g0rizn3nwXuiEfYZ1V4Mej8s3hr7GuBZdW21uww5PfpfRasqZ3eDUaNDyuvSTL6JKoCRlipb+sJBLLs17mo5aw6Z4acir+OTcuKHtvfPhjWhaKld2qwb2mEmTC7PJyeSSkdSOgnJfoVT7Lb6MCOQKJ/ZZCpckTY/35X5NUmakuzWiSlnvcuS23upc/G0QG4mbBQxWExa+xeFw4B9gECNpMFTS+QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;contributions&quot; title=&quot;&quot; src=&quot;/static/39cecaa3a513c543dbe8543953b2ff61/6af66/contributions.png&quot; srcset=&quot;/static/39cecaa3a513c543dbe8543953b2ff61/69538/contributions.png 160w,
/static/39cecaa3a513c543dbe8543953b2ff61/72799/contributions.png 320w,
/static/39cecaa3a513c543dbe8543953b2ff61/6af66/contributions.png 640w,
/static/39cecaa3a513c543dbe8543953b2ff61/d9199/contributions.png 960w,
/static/39cecaa3a513c543dbe8543953b2ff61/21b4d/contributions.png 1280w,
/static/39cecaa3a513c543dbe8543953b2ff61/07d7d/contributions.png 1478w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;깃허브 계정의 잔디는 이 사람이 평소에 얼마나 개발과 관련된 활동을 많이 하는지를 나타내는 데이터이기도 하다&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;물론 이렇게 자신의 성장을 위해 뭐라도 하는 것은 아주 좋은 자세이다. 하지만 이렇게 덮어놓고 남들이 많이 하기 때문에, 혹은 부트캠프나 학원에서 취업하려면 해야한다고 해서 일단 해보는 식으로 덤비는 것은 좋지 않을 수도 있다.&lt;/p&gt;
&lt;p&gt;처음 개발을 시작하는 분이라면 단순히 커밋을 매일 한다거나 블로그에 오늘 배운 것을 적는다는 행위만으로도 어느 정도 성장을 만들어 낼 수 있을지 모른다. 왜냐하면 이 시기는 코딩 자체에 빠르게 익숙해지는 것이 그대로 성장과 이어지는 시기이기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 여러분도 아시다시피 이 시기는 꽤나 빠르게 지나간다. 그리고 점점 코딩에 익숙해지면 익숙해질수록 새로 접하는 것보다는 익숙해지는 것이 많아질 것이고, 그때부터는 단순히 코딩을 하는 것만으로는 실력이 늘거나 새로운 지식을 접하는 것이 점점 더 어려워 질 것이다.&lt;/p&gt;
&lt;p&gt;결국 어느 순간부터는 이제 더 이상 단순하게 매일 커밋을 하는 것이나 TIL을 적는 것만으로는 예전처럼 성장의 속도가 빨리지지 않는다는 것이 느껴지기 시작한다. 그러면 이제 이런 고민을 하게 되는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;여기서 더 나아가려면 이제 뭘 공부해야하지? 이제 어떤 노력을 해야하지?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이것이 바로 방향성이 모호한 노력을 쏟고 있는 상황이다. 결국 이 노력의 양과 방향성, 이 두 가지 모두를 잡을 수 있어야 여러분이 똑같은 노력을 쏟아붓더라도 최소의 비용으로 최대의 이윤을 얻을 수 있게 된다.&lt;/p&gt;
&lt;h2 id=&quot;노력에-들어가는-비용-생각하기&quot; style=&quot;position:relative;&quot;&gt;노력에 들어가는 비용 생각하기&lt;a href=&quot;#%EB%85%B8%EB%A0%A5%EC%97%90-%EB%93%A4%EC%96%B4%EA%B0%80%EB%8A%94-%EB%B9%84%EC%9A%A9-%EC%83%9D%EA%B0%81%ED%95%98%EA%B8%B0&quot; aria-label=&quot;노력에 들어가는 비용 생각하기 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;사람들은 자신이 어떤 것을 이루기 위해 들인 노력을 일종의 비용이라고 생각하고, 실제로 비용이 맞기도 하다. 내 시간과 에너지를 투자해서 새로운 가치를 창출해내는 것이니 말이다. 그렇기 때문에 본능적으로 가장 효율적인 노력, 즉, 내가 최소의 노력을 들여서 최대의 이윤을 얻을 수 있는 방향을 찾고자 한다.&lt;/p&gt;
&lt;p&gt;안타깝지만 세상에 그렇게 정답이 정해진 지름길은 없다. 다만, 스스로 올바른 노력의 방향이 어디일지를 끊임없이 고민하며 내 노력의 효율을 조금씩 높혀볼 수는 있다. 왜냐하면 노력의 효율이 극대화되는 방법은 사람마다 다르고, 그 방법이 무엇인지는 본인이 스스로 고민해봐야 알 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 문제는 많은 분들이 이런 고민을 진지하게 해볼 수 있는 여유를 가지지 못 한다는 것이다. 지금까지 1일 1커밋이나 TIL을 통해 빠른 성장을 경험했던 사람은 그 경험 때문에, 혹은 관성 때문에 “내가 노력이 부족해서 성장을 못 하는 거야”라고 생각하기 쉽기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 이야기 했듯이 잘못된 방향성으로 인해 노력의 효율은 떨어질 수 있으며, 노력의 효율이 떨어진다는 것을 다른 말로 하면 내 노력으로 만들어낸 무언가의 가치가 떨어진다고 볼 수도 있다.&lt;/p&gt;
&lt;p&gt;내 노력으로 만들어낸 무언가의 가치가 떨어진다는 것이 어떤 의미인지 잘 이해가 가지 않는 분들을 위해, 크게 두 가지의 시각에서 이 부분을 이야기하려고 한다. 첫 번째는 시장에서의 시각, 그리고 두 번째는 개인의 지속적인 성장에 대한 시각이다.&lt;/p&gt;
&lt;h3 id=&quot;시장에서의-시각&quot; style=&quot;position:relative;&quot;&gt;시장에서의 시각&lt;a href=&quot;#%EC%8B%9C%EC%9E%A5%EC%97%90%EC%84%9C%EC%9D%98-%EC%8B%9C%EA%B0%81&quot; aria-label=&quot;시장에서의 시각 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;첫 번째. 내가 노력함으로써 얻고자 하는 이익이 가장 빛을 드러내는 대표적인 예는 바로 채용 시장이다. 그리고 채용 시장은 말 그대로 시장이기 때문에 일반적으로 우리가 알고 있는 시장의 요소들이 대부분 적용된다.&lt;/p&gt;
&lt;p&gt;그 중 필자가 이야기하고 싶은 요소는 바로 “인플레이션”이다. 인플레이션의 기본적인 정의는 시장 내에서 어떤 재화가 평범한 것이 되어버리면서 가치가 떨어지는 것이다. 이때 보통은 돈의 가치가 떨어지는 상황을 많이 이야기하지만, 채용 시장에서는 능력이나 경력의 가치라고 보면 될 것이다.&lt;/p&gt;
&lt;p&gt;이러한 인플레이션의 가장 대표적인 예는 바로 학력이다. 예를 들어 1970년대에 대학을 나온 사람은 어느 정도 인정도 받고 취업에도 꽤나 유리한 위치를 점할 수 있었지만, 2020년대에는 대학 진학률 자체가 79%에 육박하게 되면서 대학을 졸업하고 학사 학위를 가지고 있다는 것 자체가 큰 메리트가 되지 않는다는 상황을 생각해보면 된다.&lt;/p&gt;
&lt;p&gt;즉, 우리가 초딩 때부터 고3 수능 때까지 장장 12년의 노력을 들여서 따낸 이 학사 학위는 이제 채용 시장에 나와있는 대부분의 사람들이 가치고 있는 것이 되어버렸기 때문에, 예전에 비해 학사 학위라는 것이 굉장히 평범한 재화가 되어버렸다는 것이다. 누구나 가지고 있는 평범한 재화가 되었다는 것은 결국 가치가 떨어졌다는 말과 똑같다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/16a130e56cdf12fffd6fd91b275a887d/36dd4/graduate.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 66.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMFAgb/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAVMlaZvHOGX/xAAZEAADAQEBAAAAAAAAAAAAAAAAAQITETH/2gAIAQEAAQUCUigXmlGtc0s//8QAFhEBAQEAAAAAAAAAAAAAAAAAABES/9oACAEDAQE/Aco//8QAFhEBAQEAAAAAAAAAAAAAAAAAABES/9oACAECAQE/AdK//8QAGBAAAgMAAAAAAAAAAAAAAAAAABABMnH/2gAIAQEABj8Ceq0n/8QAGRABAQEBAQEAAAAAAAAAAAAAAREAUUHx/9oACAEBAAE/IVzhKz3u7ZRq5cRjZvob/9oADAMBAAIAAwAAABDTH//EABcRAAMBAAAAAAAAAAAAAAAAAAEQEUH/2gAIAQMBAT8QEan/xAAXEQADAQAAAAAAAAAAAAAAAAABEBFB/9oACAECAQE/EDeL/8QAHBABAQADAAMBAAAAAAAAAAAAAREAIUFRYXHw/9oACAEBAAE/EB7Wh4MPhuTX4HAgJvocRvUKzX7uFKtsFkmiZYKuuvP/2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;graduate&quot; title=&quot;&quot; src=&quot;/static/16a130e56cdf12fffd6fd91b275a887d/36dd4/graduate.jpg&quot; srcset=&quot;/static/16a130e56cdf12fffd6fd91b275a887d/0913d/graduate.jpg 160w,
/static/16a130e56cdf12fffd6fd91b275a887d/cb69c/graduate.jpg 320w,
/static/16a130e56cdf12fffd6fd91b275a887d/36dd4/graduate.jpg 512w&quot; sizes=&quot;(max-width: 512px) 100vw, 512px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;
    2021년 현재는 과거에 비해 대학 졸업자의 비율이 늘어나며,&lt;br&gt;
    대학을 졸업했다는 사실이 내가 특별한 인재라는 것을 나타내는 시대가 아니게 되었다.
  &lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;이처럼 남들이 다 가지고 있는 재화는 가치가 떨어진다는 것이 기본적인 시장의 원리이다. 그리고 이 원리는 취업에도 마찬가지로 적용된다. 여러분도 아시다시피 채용 시장이라는 것은 결국 수요와 공급으로 이루어진, 다른 사람과 경쟁해서 살아야 하는 정글이나 마찬가지이기 때문이다.&lt;/p&gt;
&lt;p&gt;즉, 이 정글에서 살아남기 위해서는 내가 남들보다 더 일을 잘한다, 내가 남들보다 더 성장 가능성이 높다는 것을 어필하며 “나한테 투자하면 절대 손해보지 않을걸?”이라는 메세지를 우리들의 소비자인 기업들에게 던져야 한다는 것이고, 그렇기 때문에 사람들이 어떻게 해서든 좋은 대학을 졸업하고 자격증도 따고 어학 연수도 다녀오고 하는 것이다.&lt;/p&gt;
&lt;p&gt;결국 남들과 차별화된 사람, 가지고 싶은 상품이 되어야 취업 시장에서 유리하다는 것이며, 이는 개발자라고 해서 크게 다르지 않다. 다만 그 차별점이 학력이나 자격증이 아니라 프로그래밍 실력과 같은 기준에 초점이 맞춰져 있을 뿐이다.&lt;/p&gt;
&lt;p&gt;하지만 문제는 많은 사람들이 이 가치가 채용 시장에서 나에게 어떤 무기가 될 지, 혹은 아예 무기가 될 수 없는지는 깊게 생각하지 않고, 그저 다른 사람들이 이미 가지고 있기 때문에 나도 갖춰야 한다고 생각한다는 것이다. 마치 부모님이 우리에게 대한민국에서 먹고 살려면 무조건 대학은 나와야한다고 말씀하셨던 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;물론 없는 것보다는 있는 게 나을 수도 있다. 하지만 여러분이 들인 12년 동안 노력에 비해 학사 학위라는 것이 그 만큼의 가치를 보장하지는 않을 것이다. 특히 학력보다 실력을 더 중요하게 생각하는 이 IT 업계에서는 더 그렇다고 생각한다.&lt;/p&gt;
&lt;p&gt;마찬가지로 1일 1커밋, TIL, 클론 코딩과 같은 활동들은 이미 많은 사람들에게 알려져버린 활동들이며, 심지어 부트캠프 같은 곳에서는 이런 활동들을 해야 취업에 도움이 된다는 가이드까지 주고 있다. 확실히 이력서를 보다보면 예전에 비해 확실히 이런 활동을 하시는 분들이 많다는 것이 체감되기도 한다.&lt;/p&gt;
&lt;p&gt;즉, 이런 활동들은 이제 너무나도 많은 사람들이 하고 있는 재화가 되었기 때문에, 이제 단순히 이런 활동을 했다는 것만으로는 면접관에게 어떠한 감명을 주기 어려워졌다는 것이다. 마치 학사 학위처럼 말이다.&lt;/p&gt;
&lt;h3 id=&quot;개인의-지속적인-성장에서의-시각&quot; style=&quot;position:relative;&quot;&gt;개인의 지속적인 성장에서의 시각&lt;a href=&quot;#%EA%B0%9C%EC%9D%B8%EC%9D%98-%EC%A7%80%EC%86%8D%EC%A0%81%EC%9D%B8-%EC%84%B1%EC%9E%A5%EC%97%90%EC%84%9C%EC%9D%98-%EC%8B%9C%EA%B0%81&quot; aria-label=&quot;개인의 지속적인 성장에서의 시각 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;두 번째. 앞서 이야기한 것과 같이 특별한 목표 없이 수행하는 1일 1커밋, TIL 작성, 클론 코딩 등의 활동이 만들어 주는 성장은 개발을 처음 접한 아주 극초반 뿐이다. 단순히 코딩을 자주 접하는 것만으로 이뤄내는 성장에는 한계가 있다는 것이다.&lt;/p&gt;
&lt;p&gt;게다가 이런 활동들은 꾸준함을 강조하기 때문에 자칫하면 그저 습관처럼 하게 되기가 쉽다. 즉, 내가 이것들을 실천함으로써 배울 수 있는 점은 무엇인지, 내가 왜 이런 것들을 해야 하는 지에 대한 깊은 고민 없이 말 그대로 그저 “하게만 되기 쉽다는 것”이다.&lt;/p&gt;
&lt;p&gt;이것들을 그저 습관처럼 하게 되는 이유들은 지금까지 꾸준히 해왔다는 관성이나 뭐라도 하지 않으면 뒤쳐질 것이라는 불안감 등 다양한 이유가 있겠지만, 뭐가 되었든 이런 방향성이 모호한 노력을 계속 하는 것으로는 절대 지속적인 성장을 만들어낼 수 없다.&lt;/p&gt;
&lt;p&gt;게다가 만약 이런 활동들의 본래 목적을 잊고 단지 기계처럼 반복하고 있는 상태라면, 하루 할당량을 채우기 위해 의미없는 커밋을 하거나 심지어는 커밋 타임을 변경하는 등 목적보다는 결과 자체에만 몰두하게 되어버릴 위험도 있다. 실제로 이런 상황은 실제로 많은 분들의 1일 1커밋 회고에 등장하는 단골 소재이기도 하다.&lt;/p&gt;
&lt;p&gt;결국 아무리 성장을 원하는 열정과 액션 아이템을 실천할 수 있는 에너지가 모두 있더라도, 명확한 방향성을 스스로 정의하지 못 한다면 오히려 여러분의 에너지가 엉뚱한 곳으로 투자될 가능성이 있다는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;그러면-어떻게-해야한다는-건가요&quot; style=&quot;position:relative;&quot;&gt;그러면 어떻게 해야한다는 건가요?&lt;a href=&quot;#%EA%B7%B8%EB%9F%AC%EB%A9%B4-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EC%95%BC%ED%95%9C%EB%8B%A4%EB%8A%94-%EA%B1%B4%EA%B0%80%EC%9A%94&quot; aria-label=&quot;그러면 어떻게 해야한다는 건가요 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;자, 그렇다면 뭘 어떻게 해야한다는 걸까? 물론 필자가 이 포스팅에서 모든 상황에 딱딱 들어맞는 정답과 명확한 액션 아이템을 제시하는 것은 불가능하다.&lt;/p&gt;
&lt;p&gt;하지만 적어도 여러분이 한번 각 잡고 지난 행동들을 뒤돌아 보며 고민해볼 수 있는 것들에 대한 이야기를 해볼 수는 있을 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;행위-자체에만-집착하는-것을-경계하자&quot; style=&quot;position:relative;&quot;&gt;행위 자체에만 집착하는 것을 경계하자&lt;a href=&quot;#%ED%96%89%EC%9C%84-%EC%9E%90%EC%B2%B4%EC%97%90%EB%A7%8C-%EC%A7%91%EC%B0%A9%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%84-%EA%B2%BD%EA%B3%84%ED%95%98%EC%9E%90&quot; aria-label=&quot;행위 자체에만 집착하는 것을 경계하자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;행위 자체에 집착한다는 것은 어떤 상황일까? 많은 분들이 노력을 하고 있는 대표적인 활동인 1일 1커밋을 예로 들어보도록 하겠다.&lt;/p&gt;
&lt;p&gt;사실 1일 1커밋이라는 행위가 가지는 의미는 단순히 하루에 한번 이상 커밋을 한다는 것 그 이상 그 이하도 아니다. 그렇기 때문에 이 행위 자체에 집중하게 되면 누군가 여러분에게 “1일 1커밋은 왜 해야하는 거에요?”라는 질문을 던졌을 때 “꾸준히 뭐라도 하는 게 중요하니까요”와 같은 답변을 할 수 밖에 없는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 앞서 이야기 했듯이 개발을 처음 접한 극초반 단계를 넘어서게 되면 이런 꾸준함만으로 지속적인 성장을 만들어내는 것에는 무리가 있다. 만약 여러분이 이 단계에 들어섰다면 이제 스스로에게 이런 질문을 던져봐야 할 차례이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1일 1커밋이 본질적으로 만들어내는 가치는 무엇일까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 질문에 대한 답변은 사람마다 다르겠지만, 필자는 1일 1커밋이 가지는 본질적인 가치가 바로 “매일 나만의 개발을 놓지않고 꾸준히 하는 것”에 가깝다고 생각한다.&lt;/p&gt;
&lt;p&gt;즉, 1일 1커밋이라는 단어에서 “커밋”이라는 것이 가지는 의미는 아무 커밋이 아니라, 나만의 토이 프로젝트를 개발하거나 오픈소스에 기여를 하거나 하는 커밋이라는 것이다.&lt;/p&gt;
&lt;p&gt;여러분도 아시다시피 커밋이라는 것은 결국 무언가를 만들기 위한 과정이다. 하지만 이 커밋이라는 행위 자체에만 집착하게 되면 무언가를 만들어야 한다는 목표는 저 멀리 사라지고 그저 “커밋”만 남게 되는 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 행위 자체에만 집중하게 되면 이 활동이 가져다주는 좋은 이점들을 제대로 취하지 못 하고 에너지를 낭비하게 될 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;성실함은-좋은-무기가-아니다&quot; style=&quot;position:relative;&quot;&gt;성실함은 좋은 무기가 아니다&lt;a href=&quot;#%EC%84%B1%EC%8B%A4%ED%95%A8%EC%9D%80-%EC%A2%8B%EC%9D%80-%EB%AC%B4%EA%B8%B0%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4&quot; aria-label=&quot;성실함은 좋은 무기가 아니다 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;몇 년전에 모 부트캠프를 수료하신 분과 사적인 자리에서 이런저런 이야기를 나눴던 적이 있다. 이때 필자는 한 가지 특이한 이야기를 들었는데, 그 분이 수료했던 부트캠프에서는 취업하려면 블로그에 TIL(Today I Learned)라는 글을 작성해야 한다고 가이드했다는 것이다.&lt;/p&gt;
&lt;p&gt;물론 부트캠프는 자원봉사단체가 아니라 기업이기 때문에 최소한의 리소스로 최대한의 이익을 얻어야 한다. 모든 사람에게 맞춤형 교육을 제공한다는 것은 현실적으로 비용이 너무 많이 드는 일이고, 그렇기 때문에 이런 식의 특정한 커리큘럼이나 가이드를 만들고 그것들에 사람들을 밀어넣는 형태로 운영하게 될 수 밖에 없는 것이다. &lt;small&gt;(사실 대부분의 교육업이 이런 식이기는 하다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;그래서 필자는 그 분에게 이런 질문을 던졌었다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“블로그에 TIL을 작성하는 게 왜 취업에 도움이 되는 거에요?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;왜냐하면 필자는 채용이라는 것에 기업의 규모와 현재 사업 상황, 채용 시장의 인재풀 상태, 기존 조직원들의 여유 리소스 등 굉장히 많은 변수가 작용한다고 생각하기 때문에, 어떤 특정한 행동을 하는 것이 무조건 취업에 도움이 된다고 하는 입장에는 딱히 공감이 되지 않았기 때문이다.&lt;/p&gt;
&lt;p&gt;당시 그 분은 “성실함을 보여줄 수 있는 데이터가 아닐까요?”라는 답변을 하셨었다.&lt;/p&gt;
&lt;p&gt;솔직히 매일 뭔가를 한 개 이상 새로운 것을 배우고 블로그에 적는다는 것은 보통 어려운 일이 아니다. 사람이 어떻게 매일매일 새로운 것을 배울 수 있단 말인가.&lt;/p&gt;
&lt;p&gt;물론 코딩을 시작한 지 얼마 안 된 개발자라면 매일매일 새로운 지식을 접할 수도 있다. 하지만 여러분이 코딩이라는 행위에 익숙해지면 익숙해질수록 이런 것들은 점점 사라질 것이다. 여러분이 능동적으로 새로운 지식을 찾아나선다면 이런 패턴을 계속 해서 만들어 낼 수도 있겠지만, 상당히 많은 노력이 필요한 부분이다.&lt;/p&gt;
&lt;p&gt;하지만 이런 노력의 결과가 단지 “성실함”을 보여주기 위해서라면, 글쎄…개인적으로 필자는 수지타산이 전혀 맞지 않는 장사라고 생각한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;왜냐하면 기업은 &lt;strong&gt;성실함만으로 사람을 채용하지 않기 때문이다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;기업은 애초에 금전적인 이윤을 만들어 내기 위한 집단이다. 그러니 당연히 사람을 채용할 때도 투자한 금액보다 더 돈을 많이 벌어다 줄 수 있는 사람을 원하는 것이다. 성실함은 그런 사람을 판단할 수 있는 기준 중 하나가 될 수는 있겠지만, 중요한 팩터는 아니다. 남들 보다 조금 게으르더라도 일 잘 하고 팀을 성장시킬 수 있으며 돈을 만들어 낼 수 있는 사람이라면 상관없다는 것이다.&lt;/p&gt;
&lt;p&gt;게다가 앞서 이야기했듯이 TIL은 이미 여러 부트캠프들이 가이드하고 있는 활동이고 실제로도 많은 주니어 개발자 분들이 하고 있는 활동이기 때문에 이미 인플레이션이 왔고, 이 활동을 꾸준히 했다는 것만으로는 이제 채용 시장에서 그렇게 매력적으로 보이지 않는다.&lt;/p&gt;
&lt;p&gt;즉, 여러분이 TIL을 여러분의 무기로 삼고 싶다면 단순히 꾸준함과 성실함 뿐만 아니라 남들과 차별화 될 수 있는 무언가가 더 얹어져야 한다. 예를 들어 남들이 잘 공부하지 않는 부분들을 깊게 판다던가, 5년이라는 엄청난 시간동안 하루도 빼먹지 않고 매일 TIL을 적는 미친 성실함을 보여준다던가 하는 것처럼 말이다.&lt;/p&gt;
&lt;p&gt;이런 차별 요소를 만들어내기 위해서는 이 TIL이라는 것이 주는 진정한 가치가 무엇인지를 한번 고민해봐야 한다.&lt;/p&gt;
&lt;p&gt;TIL은 취업하기 위해서 하는 활동이 아니라 실제로 여러분이 뭔가를 보고 배우고 기록하여 미래의 자신에게 건네주기 위한 아카이브이다. 하지만 많은 분들이 TIL을 작성할 때 정돈되지 않은 메모 정도의 글을 적는다. 그리고 이렇게 정돈되지 않은 글을 적어놓았으니 1-2년 뒤에 다시 예전에 적어둔 TIL을 복기하며 공부하기도 쉽지 않을 것이다.&lt;/p&gt;
&lt;p&gt;이게 바로 TIL이라는 좋은 도구를 좋지 않은 수단으로 사용하고 있는 대표적인 상황이다. 지금까지 TIL이나 1일 1커밋과 같은 행위들을 취업을 위해 하고 있었다면, 이제는 이 활동들을 통해 내가 진짜로 얻을 수 있는 가치가 무엇인지, 그리고 그 가치가 나를 어떻게 성장시킬 수 있을 지에 대해서 스스로 고민해보자.&lt;/p&gt;
&lt;p&gt;이런 고민은 그 누구도 여러분을 대신해서 해주지 않으며, 고민에 대한 정답은 어디에서도 가르쳐 주지 않는다. 물론 빠른 시간 안에 답이 나오는 고민은 아니겠지만, 매일매일 조금씩이라도 내가 지금 하고 있는 이 활동이 진정 의미가 있는 것인지 고민해보는 연습을 해보는 것을 추천한다.&lt;/p&gt;
&lt;h3 id=&quot;내재적인-모티베이션을-만들자&quot; style=&quot;position:relative;&quot;&gt;내재적인 모티베이션을 만들자&lt;a href=&quot;#%EB%82%B4%EC%9E%AC%EC%A0%81%EC%9D%B8-%EB%AA%A8%ED%8B%B0%EB%B2%A0%EC%9D%B4%EC%85%98%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%9E%90&quot; aria-label=&quot;내재적인 모티베이션을 만들자 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;마지막으로 이야기하고 싶은 것은 내재적인 모티베이션을 만들라는 것이다. 이는 앞서 말한 “취업이나 이직을 위한 활동”과도 약간은 이어지는 맥락인데, 이 취업이나 이직이라는 목표가 외부적인 모티베이션의 가장 대표적인 예이기 때문이다.&lt;/p&gt;
&lt;p&gt;만약 취업이나 이직을 위해 매일 1일 1커밋이나 TIL을 꾸준히 했다고 생각해보자.&lt;/p&gt;
&lt;p&gt;현재 개발자 시장은 공급에 비해 수요가 많은 상황이고, 이런 저런 회사의 대표님들은 항상 “주변에 좋은 개발자 없어요?”라는 질문을 뿌리고 다니는 세상이니 분명 언젠가는 취업이나 이직을 성공할 수 있을 것이다. &lt;small&gt;(당연히 채용 과정 중에는 다들 불안해하지만 생각보다 척척 잘 붙는다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;자, 그러면 여러분은 이제 목표를 이뤘는데, 1일 1커밋이나 TIL을 계속 해야 할까?&lt;/p&gt;
&lt;p&gt;물론 지금까지 해오던 관성이 있기 때문에 계속 이어나갈 수 있을지도 모른다. 하지만 입사 후 새로운 사람들, 새로운 코드, 새로운 환경에 적응하다 보면 피곤하다는 이유로, 지금은 자기 계발보다는 회사 일에 적응하는 것이 우선이라는 이유로 쉽게 그만 두게 된다.&lt;/p&gt;
&lt;p&gt;사실 이런 행위들을 그만 두게 되는 이유는 그렇게 중요하지 않을 지도 모른다. 왜냐하면 여러분이 취업이나 이직이라는 목표를 달성함과 동시에, 1일 1커밋이나 TIL처럼 엄청난 노동력과 성실함이 필요한 작업을 계속 이어가야 하는 모티베이션 자체가 사라졌기 때문이다.&lt;/p&gt;
&lt;p&gt;이것이 바로 외부적인 모티베이션의 문제점이다. 외부에서 오는 모티베이션에 의존한 행위는 그 모티베이션의 원천이 사라지는 순간 쉽게 그만 두게 되기 쉽다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 모티베이션의 원천은 취업이나 이직과 같은 외부 조건이 아니라, 성장이나 흥미와 같은 내재적인 부분에서 비롯되는 것이 훨씬 건강하다.&lt;/p&gt;
&lt;p&gt;물론 이런 내재적인 모티베이션도 번아웃과 같은 내부적 요인 때문에 무너질 수는 있지만, 적어도 목표를 달성하는 순간 내가 달릴 수 있는 원동력이 사라져버리는 상황보다는 훨씬 탄탄한 모티베이션이다.&lt;/p&gt;
&lt;p&gt;사실 이렇게 외부적인 모티베이션이나 내재적인 모티베이션에 대해 깊은 고민을 안 해본 사람이라고 해도, 본능적으로 어떤 것이 더 탄탄한 모티베이션인지는 누구나 다 알고 있다.&lt;/p&gt;
&lt;p&gt;여러분이 만약 면접관이라면 “왜 TIL을 쓰시는 거에요?”라는 질문에 “취업하기 위해서요”라고 말하는 사람에게 더 신뢰가 가겠는가, 아니면 “개발하는 것이 재미있어서요”, “제가 성장하기 위해서요”라고 말하는 사람에게 더 신뢰가 갈 것 같은가?&lt;/p&gt;
&lt;p&gt;전자의 답변같은 경우에는 당연히 “그럼 취업하면 안 하겠다는 건가?”라는 생각이 들 수 밖에 없는 답변이다. 그리고 이런 생각이 들게 만드는 것이 바로 외부적인 모티베이션이 주는 리스크인 것이다.&lt;/p&gt;
&lt;p&gt;물론 이런 예시와 함께 이야기하면 대부분 고개를 끄덕이며 공감하지만, 사실 우리는 모두 외부적인 모티베이션에 의존하는 삶에 굉장히 익숙하고, 이런 이야기를 하고 있는 필자 또한 나이가 점점 들면서 돈이라는 외부적인 모티베이션에 의존하는 경향이 강해지고 있다. &lt;small&gt;&lt;del&gt;(집 값 너무 킹받는다…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;결국 필자가 이 포스팅에서 이야기하고 싶은 것은 외부적인 모티베이션을 완전히 없애라는 것은 아니다. 이것은 불가능하기도 하고, 때로는 이러한 모티베이션이 더 뛰어난 모멘텀을 만들어 내기도 한다. 하지만 적어도 내가 현재 의존하고 있는 이 모티베이션이 앞으로도 지속 가능한 모티베이션인지, 정말로 나의 성장에 도움이 되는 모티베이션인지에 대한 고찰은 한번 쯤 해봐야 한다고 생각한다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;어찌보면 약간은 이상적인 이야기를 하는 것처럼 들릴 수도 있다. 왜냐하면 현실적으로 취업이나 이직이 당장 급하고 절박한 상황이라면 이런 고민을 해볼 여유를 가지기가 쉽지 않기 때문이다.&lt;/p&gt;
&lt;p&gt;하지만 필자가 이 포스팅에서 이야기한 내용들은 당연히 여러분의 취업이나 이직에 도움이 되는 것들이다. 여러분의 진정한 적은 “다른 사람들은 열심히 하고 있는데, 나만 이런 고민하느라 시간을 낭비하는 게 아닐까?”, “내가 고민할 시간이 어딨어. 일단 뭐라도 해야지”라고 속삭이는 여러분 마음 속의 불안감이다.&lt;/p&gt;
&lt;p&gt;물론 상대적으로 일을 해온 경험이 부족한 개발자는 채용 시장에서 내세울 수 있는 무기가 그렇기 많지 않은 경우가 많다. 그래서 면접에서 조금이라도 더 좋은 모습을 보여주기 위해서 알고리즘 문제나 언어에 대한 이해와 같은 펀더멘탈에 집중하거나 1일 1커밋과 같이 당장 내가 실천할 수 있는 활동들에 집중하게 되는 것이다.&lt;/p&gt;
&lt;p&gt;물론 이런 펀더멘탈들을 공부하는 것은 개발자의 기본적인 소양이라고 할 수 있을만큼 중요하기도 하고, 1일 1커밋이나 TIL 같은 활동을 통해 성실함 같은 요소들을 어필할 수도 있겠지만, 중요한 것은 결과적으로 면접관이 찾는 사람이 단순히 이론에 빠삭하거나 성실하기만 한 사람이 아니라 “뭐가 됐든 일을 잘 할 수 있는 사람”이라는 사실이다.&lt;/p&gt;
&lt;p&gt;즉, 여러분은 채용 시장에서 눈에 띄는 인재가 되기 위한 전략이 필요한 것이고, 이 전략을 만드는 과정에서 “방향성이 명확한 노력”이 필요한 것이다.&lt;/p&gt;
&lt;p&gt;뭔가를 시작하기 전에 내가 이 노력을 통해서 뭘 원하는 지, 어떤 모습이 되고 싶은 지를 한번 머릿속에 그려보고 방향성을 수립한 후 실행하는 연습을 꾸준히 하다보면 언젠가는 여러분만의 노하우나 전략을 통해 시장에서 특별함을 뽐낼 수 있는 인재가 될 수 있을 것이라고 믿는다.&lt;/p&gt;
&lt;p&gt;이상으로 나만의 색깔을 찾는 방법 – 성장의 방향성을 설정하자 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Everything About tsconfig] Compiler Options / Modules]]></title><description><![CDATA[Following up on my previous post [Everything About tsconfig] Compiler options / Type Checking, this post covers the module-related options in tsconfig’s compiler settings.]]></description><link>https://evan-moon.github.io/2021/08/22/tsconfig-compiler-options-modules/en/</link><guid isPermaLink="false">20210822-tsconfig-compiler-options-modules-en</guid><pubDate>Sun, 22 Aug 2021 03:11:05 GMT</pubDate><content:encoded>&lt;p&gt;Following up on my previous post &lt;a href=&quot;/20210808-tsconfig-compiler-options-type-check&quot;&gt;[Everything About tsconfig] Compiler options / Type Checking&lt;/a&gt;, this post covers the module-related options in tsconfig’s compiler settings.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;These options control which module system TypeScript should follow when compiling modules, which paths to include in compilation, what module format the compiled JavaScript should use, and so on. They come up more often when building TypeScript libraries than when building typical applications.&lt;/p&gt;
&lt;h2 id=&quot;allowumdglobalaccess&quot; style=&quot;position:relative;&quot;&gt;allowUmdGlobalAccess&lt;a href=&quot;#allowumdglobalaccess&quot; aria-label=&quot;allowumdglobalaccess permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows access to UMD modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Disallows access to UMD modules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;allowUmdGlobalAccess&lt;/code&gt; option controls whether TypeScript modules can access UMD (Universal Module Definition) modules that expose themselves as properties on the global object.&lt;/p&gt;
&lt;p&gt;When this option is disabled, you cannot access global variables like jQuery’s &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt; directly; you must import the module using an &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;Libraries built using the UMD pattern typically have type declarations that look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;doThing1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnInterface&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  foo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; myLibrary&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When a type file exports a namespace this way, TypeScript assumes the module is implicitly assigned to a global variable named &lt;code class=&quot;language-text&quot;&gt;myLibrary&lt;/code&gt;. That’s why including this type declaration in your source lets you access the module’s contents through the &lt;code class=&quot;language-text&quot;&gt;myLibrary&lt;/code&gt; namespace.&lt;/p&gt;
&lt;p&gt;If &lt;code class=&quot;language-text&quot;&gt;allowUmdGlobalAccess&lt;/code&gt; is disabled, you’ll encounter this error:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; myLibrary&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doThing1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &apos;myLibrary&apos; refers to a UMD global, but the current file is a module. Consider adding an import instead.ts(2686)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Enabling &lt;code class=&quot;language-text&quot;&gt;allowUmdGlobalAccess&lt;/code&gt; allows access to UMD modules exported as namespaces. However, explicitly importing modules with the &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; keyword is safer than relying on modules implicitly declared in the global scope. Unless you have no choice, it’s better to keep this option enabled.&lt;/p&gt;
&lt;h2 id=&quot;baseurl&quot; style=&quot;position:relative;&quot;&gt;baseUrl&lt;a href=&quot;#baseurl&quot; aria-label=&quot;baseurl permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; option specifies the base directory for resolving relative module paths.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── index.ts
├── utils
│   └── foo.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For instance, in the structure above, to import the &lt;code class=&quot;language-text&quot;&gt;foo.ts&lt;/code&gt; module from &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; using a relative path, you’d write &lt;code class=&quot;language-text&quot;&gt;./utils/foo&lt;/code&gt; — where &lt;code class=&quot;language-text&quot;&gt;./&lt;/code&gt; marks the current location as the starting point.&lt;/p&gt;
&lt;p&gt;But if you think about it, even when using relative paths, the base location itself doesn’t change that often.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── index.ts
├── utils
│   └── foo.ts
├── remotes
│   └── bar.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If a module in &lt;code class=&quot;language-text&quot;&gt;remotes/bar&lt;/code&gt; wants to access the &lt;code class=&quot;language-text&quot;&gt;utils/foo&lt;/code&gt; module in this structure, it would use &lt;code class=&quot;language-text&quot;&gt;../utils/foo&lt;/code&gt; — climbing up to the project root and then descending again.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; option eliminates this repetitive “journey to root” whenever you use relative paths.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;baseUrl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The relative path in &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; is relative to where &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; is located — typically the project root. With this configuration, when you use relative paths to access modules, TypeScript searches starting from the root specified in &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Actually .(root)/utils/foo&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; bar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;remotes/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Actually .(root)/remotes/bar&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; this way lets you write relative paths as if they were absolute, without repeatedly navigating to the root with &lt;code class=&quot;language-text&quot;&gt;./&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;../&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;paths&quot; style=&quot;position:relative;&quot;&gt;paths&lt;a href=&quot;#paths&quot; aria-label=&quot;paths permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; option provides a mapping that tells the compiler where to search when you specify certain module names.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;baseUrl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;paths&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;app/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;config/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app/_config/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;environment/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;environments/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;shared/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app/_shared/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;helpers/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;helpers/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;tests/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tests/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Paths in the mapping are calculated relative to &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;, so you must set &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; to use the &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; option. In the example above, &lt;code class=&quot;language-text&quot;&gt;app/*&lt;/code&gt; means &lt;code class=&quot;language-text&quot;&gt;./src/app/*&lt;/code&gt;, and when you import with &lt;code class=&quot;language-text&quot;&gt;import foo from &apos;app/math&apos;&lt;/code&gt;, TypeScript automatically searches the corresponding path &lt;code class=&quot;language-text&quot;&gt;./src/app/math&lt;/code&gt; and loads the module.&lt;/p&gt;
&lt;p&gt;If TypeScript can’t find the module after searching all locations in &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt;, it performs additional searching according to the strategy set in &lt;code class=&quot;language-text&quot;&gt;moduleResolution&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Path mapping itself is quite simple, but people often forget that path mapping always starts relative to &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;, leading to mistakes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── src
│   └── index.ts
├── node_modules
│   └── foo
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Consider a project with this structure where &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; is set to &lt;code class=&quot;language-text&quot;&gt;./src&lt;/code&gt;. How would you map the &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt; path to &lt;code class=&quot;language-text&quot;&gt;node_modules/foo&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;A common mistake is setting &lt;code class=&quot;language-text&quot;&gt;&quot;foo&quot;: &quot;./node_modules/foo&quot;&lt;/code&gt; based on the location of &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;. Since you’re working in &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;, it’s natural to specify paths relative to that file without thinking.&lt;/p&gt;
&lt;p&gt;But path mapping is relative to &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;, so in this case &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; is the reference point. You’d need to write &lt;code class=&quot;language-text&quot;&gt;&quot;foo&quot;: &quot;../node_modules/foo&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It’s easy to forget this and map paths relative to &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;’s location, then fail to resolve modules. Keep this in mind.&lt;/p&gt;
&lt;h2 id=&quot;module&quot; style=&quot;position:relative;&quot;&gt;module&lt;a href=&quot;#module&quot; aria-label=&quot;module permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;CommonJS&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Compiles modules to CommonJS format.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;AMD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compiles modules to Asynchronous Module Definition format.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;UMD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compiles modules using the Universal Module Definition design pattern.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;System&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compiles modules to System.js format.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;ES6&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ES2015&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ES2020&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ESNext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compiles modules to ESM (ES Module) format.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; option sets which module system the compiled JavaScript modules will use.&lt;/p&gt;
&lt;p&gt;Of course, the official module system specified by ECMAScript is ESM using &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; keywords, but realistically, not many browsers support this system yet. And while Node.js added support for ESM without the &lt;code class=&quot;language-text&quot;&gt;--experimental-modules&lt;/code&gt; flag in version 12.0.0, the ESM system isn’t widespread across the entire ecosystem. &lt;small&gt;(Node.js still heavily uses CommonJS)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;For these reasons, it’s not practically feasible to compile all our modules to ESM. We need to be able to choose an appropriate module system for the situation.&lt;/p&gt;
&lt;p&gt;This post won’t cover everything about JavaScript module systems, but let’s briefly look at the characteristics of each. Imagine a simple application with two modules:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils/math.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; module imports the &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; function from &lt;code class=&quot;language-text&quot;&gt;utils/math.ts&lt;/code&gt;, uses currying to create &lt;code class=&quot;language-text&quot;&gt;add2&lt;/code&gt;, and exports it. Let’s see how &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; changes when compiled with each module system and what each system’s characteristics are.&lt;/p&gt;
&lt;h3 id=&quot;commonjs&quot; style=&quot;position:relative;&quot;&gt;CommonJS&lt;a href=&quot;#commonjs&quot; aria-label=&quot;commonjs permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; math_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;CommonJS&lt;/code&gt;, true to its “Common” name, represents a module system designed for using JavaScript modules freely not just in browsers but also in server environments and desktop applications.&lt;/p&gt;
&lt;p&gt;For this reason, server-side runtimes like Node.js still commonly use the CommonJS system, so if you’re building a library for server-side use, you should consider using CommonJS.&lt;/p&gt;
&lt;p&gt;CommonJS assigns modules to properties of the &lt;code class=&quot;language-text&quot;&gt;exports&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;module.exports&lt;/code&gt; object and synchronously loads modules directly using the global &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt; function. In the example above, you can see the module being assigned to the &lt;code class=&quot;language-text&quot;&gt;math_1&lt;/code&gt; variable through the &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt; function, and the &lt;code class=&quot;language-text&quot;&gt;add2&lt;/code&gt; function being assigned to the &lt;code class=&quot;language-text&quot;&gt;exports.add2&lt;/code&gt; property.&lt;/p&gt;
&lt;p&gt;Because the &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt; function loads modules synchronously when executed, CommonJS even allows tricks like “if this, load module A; if that, load module B” using &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statements.&lt;/p&gt;
&lt;h3 id=&quot;amd&quot; style=&quot;position:relative;&quot;&gt;AMD&lt;a href=&quot;#amd&quot; aria-label=&quot;amd permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;require&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;require&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exports&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;AMD (Asynchronous Module Definition)&lt;/code&gt;, as its name suggests, is a module system that loads modules asynchronously.&lt;/p&gt;
&lt;p&gt;The original CommonJS was designed assuming synchronous module loading, which sparked active discussions about implementing asynchronous module loading. During these discussions, some people who didn’t agree with CommonJS’s core principle of “JavaScript modules that work in every environment” emerged, and they split off to form the AMD group.&lt;/p&gt;
&lt;p&gt;Browser environments are inherently different from servers: modules need to be fetched from a server to be used. So it’s more efficient to asynchronously fetch only the needed parts of modules from the server rather than loading all necessary modules at once and executing them. But for the CommonJS group aiming for “JavaScript modules that work in every environment,” unifying these environmental differences was challenging.&lt;/p&gt;
&lt;p&gt;This led people with the mindset “let’s at least get browsers right” to split off and create AMD, which is why AMD focuses specifically on asynchronous module calls in browsers. &lt;small&gt;(CommonJS did later add asynchronous module loading separately)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Since AMD ultimately split from CommonJS, the two systems provide many compatible features, allowing techniques like wrapping existing CommonJS modules in AMD format.&lt;/p&gt;
&lt;p&gt;In the example above, you can see AMD’s &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; function pulling in CommonJS’s &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; functions. The internal structure is basically similar to CommonJS, but the key difference is that instead of loading modules via &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt;, modules are injected through the third argument &lt;code class=&quot;language-text&quot;&gt;math_1&lt;/code&gt; of the &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; function.&lt;/p&gt;
&lt;h3 id=&quot;umd&quot; style=&quot;position:relative;&quot;&gt;UMD&lt;a href=&quot;#umd&quot; aria-label=&quot;umd permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; module &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; v &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;require&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exports&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; define &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; define&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;require&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; factory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;require&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; math_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;UMD (Universal Module Definition)&lt;/code&gt; is less a module system and more a design pattern for creating something that can be used universally across various environments.&lt;/p&gt;
&lt;p&gt;Because UMD is a pattern, unlike AMD or CommonJS which typically use libraries like &lt;code class=&quot;language-text&quot;&gt;RequireJS&lt;/code&gt;, developers must write code using the UMD pattern themselves. Simply put, as shown in the example, using an IIFE (Immediately Invoked Function Expression) to branch directly in your source code is the UMD pattern.&lt;/p&gt;
&lt;p&gt;The example shows that if &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;module.exports&lt;/code&gt; exist, it uses the CommonJS system; if the &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; function exists, it uses AMD. This way, the UMD pattern can provide a consistent experience regardless of which module system the environment uses.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9a3cbcb2d8922dd1e01e855b408e4af4/22475/all_taken.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC10lEQVR42k2SSU9TURiGK1opBUpRFBREoy5ETYhKjDGaOEaN08aoCyMhaqIGB9hoxAEBK8YBp1Kwg9iR3tKWFluo4oSgSAMBozaGpYk7/QuP361GXTy55yb3Puf93nM0RX1PKertSTMnHmGWuk7EWNgbYGHMx/xoiNJwmBKhKNhFcTDMXCWEwauQ7e4UfGS7fpMjaAp7/xPGIqzzPqLYaqY8YWNt4iHL4iHKYrJBNMKSaJSybnmGujG6veg8frK9gtP7TzgjHKRAUsyJRyno66HM5+S4uZVLE5/Y9WaAc2NjVI+McHBgkKvjHzk9PELlwHvKXWZKLS3k2DrQq0ldIpVNNAa/n/xQF4VPu5mtCu+1UHfxIq9SXzieTOKanKR+fILDQ+/o//ady6Pj7In3s995h/VnjpDf1IxeCUpKz29hbqcfY0BhpiQtjIbZbGqgreEUV/pitHydpGpwiCqRbU8849S7Qfa9eEW5v4u5dVeYd7IanekW+j8d/hXmSso8RaFASi/pDqOLRDg2/IHUj5/cSn2lJt7HI1sblf2d7I4naJTvNjQ2sfxsLfuvNlDicJKZ7tGNJsfnR0UVGoNB8oIhpvuV9Ijmzyk2979ksRR/2mGn1uOlSrqskfWh2lq2XL/BxkAAvQj1HZ50j2lhrioUSZ4/gFFQT+/E0DAXkmPc/ZTi6NAHHKMTWOS9ZjjJoZ4Y8x62UnLvAfntdrQOd1qoIoeioI6dJ2MbJIlBZDrpY+fzl+ztfcbWrgCbFB/1g28wJUc58vY9B1+8Zqb8o3W6ybI/IcvmQmd3keVwibBTkgk6KTRDZFphmtNHxhMP2sduFjWZONBQx47GenaamimSRBkeH9oOJ1Otj5ki12a63Y1BUuaLXKOmyhTJOhHubjez0uZgjd3KUquDBdZ2tl2uZk3zTVbcvsPq89eouN/GKpudJa0WKtpaqbC0Y7TYKJW7WGzr4BekrCjuRnfpjQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;all taken&quot; title=&quot;&quot; src=&quot;/static/9a3cbcb2d8922dd1e01e855b408e4af4/6af66/all_taken.png&quot; srcset=&quot;/static/9a3cbcb2d8922dd1e01e855b408e4af4/69538/all_taken.png 160w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/72799/all_taken.png 320w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/6af66/all_taken.png 640w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/d9199/all_taken.png 960w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/22475/all_taken.png 1039w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;UMD === I didn&apos;t know what you&apos;d like, so I prepared every module system&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Additionally, if an environment supports neither CommonJS nor AMD, there’s a last-resort UMD pattern approach: inserting the module as a property of global objects like &lt;code class=&quot;language-text&quot;&gt;globalThis&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;global&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, this pollutes the global scope and should be avoided when possible. And since it’s rare for modern JavaScript runtime environments to be forced into situations where no module system is supported, TypeScript doesn’t appear to use this approach.&lt;/p&gt;
&lt;h3 id=&quot;system&quot; style=&quot;position:relative;&quot;&gt;System&lt;a href=&quot;#system&quot; aria-label=&quot;system permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;exports_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __moduleName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context_1 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; context_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;setters&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;math_1_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                math_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; math_1_1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function-variable function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;exports_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;add2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the UMD pattern is “I didn’t know what you’d like, so I prepared everything” in design pattern form, &lt;code class=&quot;language-text&quot;&gt;SystemJS&lt;/code&gt; is that concept implemented as a library. &lt;small&gt;(Even more ambitious)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;SystemJS is a module loader, so it doesn’t concern itself with how modules are defined — it just loads modules already defined in CommonJS, AMD, or ESM formats.&lt;/p&gt;
&lt;p&gt;SystemJS was quite popular around 2016 when the ECMA Foundation announced ESM using &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; keywords as the official ES6 module spec, because browsers at the time didn’t support this spec.&lt;/p&gt;
&lt;p&gt;The official spec for modules had been decided, but browser vendors were slow to implement it. You couldn’t use ESM even if you wanted to. SystemJS bridged this gap. It was implemented using the &lt;a href=&quot;https://github.com/ModuleLoader/es-module-loader&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;es-module-loader&lt;/a&gt; polyfill to load ESM-format modules.&lt;/p&gt;
&lt;p&gt;This raises a question: “Even if you load modules that browsers don’t support, you can’t execute them without transpilation. How does SystemJS solve this?” The answer was surprisingly close at hand.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/934e6cd11f70c175f5171121f4db2f65/47311/cool.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAAB56Spyjs0/wD/xAAZEAEBAAMBAAAAAAAAAAAAAAABAgADEUL/2gAIAQEAAQUCjrIGbBb8VHJOuf/EABgRAAIDAAAAAAAAAAAAAAAAAAABESEx/9oACAEDAQE/AVTk0//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/AYf/xAAZEAACAwEAAAAAAAAAAAAAAAAAAQIRITH/2gAIAQEABj8Ct2YOiCHrOn//xAAYEAADAQEAAAAAAAAAAAAAAAABESEAMf/aAAgBAQABPyGnEOXAlvy4sBMDcyKrzDMHBp5B5//aAAwDAQACAAMAAAAQj/8A/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhMf/aAAgBAwEBPxC4NaP/xAAXEQADAQAAAAAAAAAAAAAAAAAAASEx/9oACAECAQE/EKUMh//EAB0QAQEAAgEFAAAAAAAAAAAAABEBACExUWFxgZH/2gAIAQEAAT8QEYDaY9sW2mi1n25ZldIzxkYiAAnnD+oHA9cvhnpz/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cool&quot; title=&quot;&quot; src=&quot;/static/934e6cd11f70c175f5171121f4db2f65/c08c5/cool.jpg&quot; srcset=&quot;/static/934e6cd11f70c175f5171121f4db2f65/0913d/cool.jpg 160w,
/static/934e6cd11f70c175f5171121f4db2f65/cb69c/cool.jpg 320w,
/static/934e6cd11f70c175f5171121f4db2f65/c08c5/cool.jpg 640w,
/static/934e6cd11f70c175f5171121f4db2f65/6a068/cool.jpg 960w,
/static/934e6cd11f70c175f5171121f4db2f65/47311/cool.jpg 1080w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;I don&apos;t really get complex stuff — just import babel and run transpilation at runtime&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;Exactly. Using this method, it doesn’t matter if the target module uses ES2020 or TypeScript, or if its module system is CommonJS or AMD. Of course, this isn’t a built-in SystemJS feature — you need the &lt;a href=&quot;https://github.com/systemjs/systemjs-babel&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;systemjs-babel&lt;/a&gt; extension — but the solution approach itself is impressively bold.&lt;/p&gt;
&lt;p&gt;However, transpiling modules at runtime isn’t just about transpilation: you also need to determine module dependencies, and if you’re using TypeScript, you need to compile after static type checking. Naturally, performing these heavy operations at runtime instead of build time hurts performance.&lt;/p&gt;
&lt;p&gt;In 2021, as everyone knows, these heavy operations can be done entirely at build time with no issues, so SystemJS is rarely used unless there’s a special situation.&lt;/p&gt;
&lt;h3 id=&quot;es-module&quot; style=&quot;position:relative;&quot;&gt;ES Module&lt;a href=&quot;#es-module&quot; aria-label=&quot;es module permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;ESM (ES Module)&lt;/code&gt; is the module system officially defined by the ECMA Foundation for the JavaScript ecosystem.&lt;/p&gt;
&lt;p&gt;That’s why, unlike CommonJS or AMD which rely on separate functions like &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; to load modules, ESM uses the &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; keywords to load modules.&lt;/p&gt;
&lt;p&gt;ESM, which appeared in 2015, was a latecomer compared to CommonJS and AMD which had been in use since 2009. It also introduced many changes like mandatory inclusion of the &lt;code class=&quot;language-text&quot;&gt;use strict&lt;/code&gt; directive in modules and &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; not pointing to the global &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;These constraints meant applications using CommonJS or AMD couldn’t easily migrate, and that situation continues today.&lt;/p&gt;
&lt;p&gt;That’s why even now, to use ESM in native JavaScript environments, you need to add the &lt;code class=&quot;language-text&quot;&gt;type=&quot;module&quot;&lt;/code&gt; attribute to &lt;code class=&quot;language-text&quot;&gt;script&lt;/code&gt; tags or add a &lt;code class=&quot;language-text&quot;&gt;&quot;type&quot;: &quot;module&quot;&lt;/code&gt; field to &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course, many vendors now support ESM compared to before, but to safely use ESM, you still need to combine bundlers like Webpack and transpilers like Babel to determine module dependencies at build time and convert them to a form the runtime can understand. Depending on the runtime environment, this can make ESM a cumbersome format to use — something to keep in mind.&lt;/p&gt;
&lt;p&gt;However, ESM has one advantage that overshadows all these drawbacks: tree-shaking is much easier when bundling modules with Webpack.&lt;/p&gt;
&lt;p&gt;Webpack’s &lt;a href=&quot;https://webpack.js.org/plugins/module-concatenation-plugin/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;ModuleConcatenationPlugin&lt;/a&gt; merges modules into a single closure to achieve better performance in browser environments. The choice between CommonJS and ESM significantly affects the output.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// CommonJS&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* harmony import */&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _utils__WEBPACK_IMPORTED_MODULE_0__ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__webpack_require__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;_utils__WEBPACK_IMPORTED_MODULE_0__&lt;span class=&quot;token comment&quot;&gt;/* .add */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When bundled with Webpack, CommonJS modules are loaded through a &lt;code class=&quot;language-text&quot;&gt;__webpack_require__&lt;/code&gt; function. The problem is this doesn’t just load the &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; function inside the module — it loads the entire module.&lt;/p&gt;
&lt;p&gt;The next line &lt;code class=&quot;language-text&quot;&gt;(0,_utils__WEBPACK_IMPORTED_MODULE_0__/* .add */ .DG)&lt;/code&gt; shows access to the &lt;code class=&quot;language-text&quot;&gt;DG&lt;/code&gt; property of the loaded module, which is the obfuscated name of the &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Since CommonJS assigns values to properties of the global &lt;code class=&quot;language-text&quot;&gt;exports&lt;/code&gt; object, it’s hard to determine “this module only uses function A.”&lt;/p&gt;
&lt;p&gt;But ESM modules can export each desired value separately using the &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; keyword, making it much easier to determine detailed dependencies.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ESM&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// webpackBootstrap&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// CONCATENATED MODULE: ./utils/math.js**&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// CONCATENATED MODULE: ./index.js**&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at an ESM module bundled with Webpack, there’s no module-loading code at all — the function from inside the module was even inlined.&lt;/p&gt;
&lt;p&gt;Of course, the &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; function I imported is very small, which allows this representation. But the key point is that only that “specific function” from inside the module was imported.&lt;/p&gt;
&lt;p&gt;As mentioned, ESM makes detailed dependency tracking easy through &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; keywords, enabling efficient separation of used and unused code at build time.&lt;/p&gt;
&lt;p&gt;Because of this powerful tree-shaking advantage, most popular libraries &lt;del&gt;except Lodash&lt;/del&gt; officially support ESM.&lt;/p&gt;
&lt;h2 id=&quot;moduleresolution&quot; style=&quot;position:relative;&quot;&gt;moduleResolution&lt;a href=&quot;#moduleresolution&quot; aria-label=&quot;moduleresolution permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Node&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Uses Node strategy to resolve modules. Default when &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; option is CommonJS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Classic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Uses Classic strategy to resolve modules. Default when &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; option is not CommonJS.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;moduleResolution&lt;/code&gt; option handles the process TypeScript uses to determine exactly what a module import refers to. This is too difficult to explain in words, so let’s look at code.&lt;/p&gt;
&lt;p&gt;First, TypeScript uses two main methods for defining module paths: relative and absolute.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Relative path&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; debounce &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Absolute path&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Relative paths use identifiers like &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; (current location) or &lt;code class=&quot;language-text&quot;&gt;..&lt;/code&gt; (parent directory) to specify a starting point, allowing precise indication of module location. Absolute paths, on the other hand, just specify the module name, so TypeScript needs to embark on a journey to find the exact module location based on specific rules.&lt;/p&gt;
&lt;p&gt;Also, since neither relative nor absolute paths specify file extensions, TypeScript needs to figure out which extension the file has — &lt;code class=&quot;language-text&quot;&gt;math.ts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;math.d.ts&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;That’s why TypeScript needs a strategy for finding exact module locations. The &lt;code class=&quot;language-text&quot;&gt;moduleResolution&lt;/code&gt; option lets you choose between Classic and Node strategies.&lt;/p&gt;
&lt;p&gt;Both strategies follow basically similar methods for finding module locations.&lt;/p&gt;
&lt;p&gt;When finding modules using relative paths like &lt;code class=&quot;language-text&quot;&gt;import { add } from &apos;./math&apos;&lt;/code&gt;, the directory to search is clear, so it only searches within that directory. When finding modules using absolute paths like &lt;code class=&quot;language-text&quot;&gt;import { add } from &apos;math&apos;&lt;/code&gt;, the directory isn’t clear, so it starts searching in the directory containing the file that imported the module, then moves up one level to the parent directory, then another level up, and so on.&lt;/p&gt;
&lt;p&gt;The difference between Classic and Node strategies lies in which file extensions to look for and where to search first.&lt;/p&gt;
&lt;h3 id=&quot;classic&quot; style=&quot;position:relative;&quot;&gt;Classic&lt;a href=&quot;#classic&quot; aria-label=&quot;classic permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Classic&lt;/code&gt; strategy is essentially TypeScript’s default module resolution strategy, also used for compatibility with older TypeScript versions.&lt;/p&gt;
&lt;p&gt;The Classic strategy searches for modules imported with relative paths starting from the importing module’s location, in the order &lt;code class=&quot;language-text&quot;&gt;*.ts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;As mentioned, when using relative paths, the directory location to search is clear, so TypeScript only searches candidate extensions and terminates if the module isn’t found.&lt;/p&gt;
&lt;p&gt;For modules using absolute paths like &lt;code class=&quot;language-text&quot;&gt;import { add } from &apos;math&apos;&lt;/code&gt;, TypeScript starts from the current importing path and climbs up the parent directories one level at a time.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;For absolute paths, TypeScript starts searching from &lt;code class=&quot;language-text&quot;&gt;/root/src&lt;/code&gt; where the importing file is located. If it doesn’t find the module in this directory, it climbs up one level and searches again. If it reaches the root and still can’t find the module, it terminates.&lt;/p&gt;
&lt;h3 id=&quot;node&quot; style=&quot;position:relative;&quot;&gt;Node&lt;a href=&quot;#node&quot; aria-label=&quot;node permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Node&lt;/code&gt; strategy mimics how Node.js finds modules. Unlike the Classic strategy, Node doesn’t just search for &lt;code class=&quot;language-text&quot;&gt;*.ts&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; extensions — it searches a wider variety of module formats.&lt;/p&gt;
&lt;p&gt;For relative paths, similar to Classic, TypeScript searches within the specified directory in this order:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math/package.json&lt;/code&gt; (only if using &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; field)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;root/src/math/index.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;root/src/math/index.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;root/src/math/index.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;It looks like a lot was added, but basically it’s the same as Classic — searching files in the specified directory — except it additionally searches for &lt;code class=&quot;language-text&quot;&gt;*.tsx&lt;/code&gt; extensions, the &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; property in &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;index.*&lt;/code&gt; files in directories with the same name as the module.&lt;/p&gt;
&lt;p&gt;When searching for relatively-pathed modules, both Node and Classic strategies use similar directory tree traversal orders. But the difference becomes larger when finding absolutely-pathed modules.&lt;/p&gt;
&lt;p&gt;That’s because the Node strategy, unlike Classic, searches &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; directories when finding absolutely-pathed modules.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/package.json&lt;/code&gt; (only if using &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; field)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/@types/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/index.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/index.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/index.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/node_modules/math.ts&lt;/code&gt; (moves to parent directory and repeats)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using the Node strategy, TypeScript first searches the &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; directory in &lt;code class=&quot;language-text&quot;&gt;/root/src&lt;/code&gt; where the file calling the &lt;code class=&quot;language-text&quot;&gt;math&lt;/code&gt; module is located.&lt;/p&gt;
&lt;p&gt;It searches for &lt;code class=&quot;language-text&quot;&gt;*.ts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*.tsx&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; files and the &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; field in &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; just like with relative paths, then searches the &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; directory and &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt; files in directories with the same name as the module.&lt;/p&gt;
&lt;p&gt;If it doesn’t find the desired module after one search pass, it moves to the parent directory and repeats. If it reaches the root, searches globally-installed modules on the local machine, and still can’t find the module, it terminates.&lt;/p&gt;
&lt;p&gt;This search process isn’t identical to how Node.js finds modules, but it’s very similar. Node.js first looks for files with the same name as the module, then looks for the file at the path in &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;’s &lt;code class=&quot;language-text&quot;&gt;main&lt;/code&gt; field, and finally searches for &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt; files in directories with the same name. TypeScript’s Node strategy mimics this search process.&lt;/p&gt;
&lt;p&gt;The TypeScript docs say it’s not particularly complex compared to Node.js’s method, so don’t worry. But honestly, Node.js’s package search method itself is inefficient. That’s why starting from TypeScript 4.0, modules that aren’t imported no longer have their type information searched through this process.&lt;/p&gt;
&lt;h2 id=&quot;noresolve&quot; style=&quot;position:relative;&quot;&gt;noResolve&lt;a href=&quot;#noresolve&quot; aria-label=&quot;noresolve permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Resolves all modules included in the application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only resolves modules explicitly included in the application.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;By default, the TypeScript compiler tries to compile all modules included in the application. Even if a file isn’t included in the tsconfig root’s &lt;a href=&quot;/2021/07/30/tsconfig-options-root-fields/#include&quot;&gt;include&lt;/a&gt; or &lt;a href=&quot;/2021/07/30/tsconfig-options-root-fields/#files&quot;&gt;files&lt;/a&gt; fields, if it’s imported somewhere in the application using an &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; statement or &lt;code class=&quot;language-text&quot;&gt;/// &amp;lt;reference path=&quot;...&quot; /&gt;&lt;/code&gt; directive, that module is also a compilation target.&lt;/p&gt;
&lt;p&gt;In a sense, this implicitly includes modules in the compilation targets. Setting &lt;code class=&quot;language-text&quot;&gt;noResolve&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; prevents this implicit module compilation.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/index.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;noResolve&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/index.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, the &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; field only contains &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt;, not the &lt;code class=&quot;language-text&quot;&gt;utils/math&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;When &lt;code class=&quot;language-text&quot;&gt;noResolve&lt;/code&gt; is &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;, the &lt;code class=&quot;language-text&quot;&gt;utils/math&lt;/code&gt; module used in &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; compiles without issues. But when it’s &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;, you get an error saying the module can’t be found.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;src/index.ts:1:21 - error TS2307: Cannot find module &apos;./utils/math&apos; or its corresponding type declarations.

1 import { add } from &apos;./utils/math&apos;;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Only modules explicitly declared in the &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;files&lt;/code&gt; fields are compiled. For the same reason, modules imported using directives like &lt;code class=&quot;language-text&quot;&gt;/// &amp;lt;reference path=&quot;...&quot; /&gt;&lt;/code&gt; are also excluded from compilation if they’re not in those fields.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noResolve&lt;/code&gt; option helps with easier module management by forcing developers to explicitly declare TypeScript’s compilation targets. However, because it excludes even directive-imported modules from compilation, when using libraries like Next.js that import type definition files via directives, it’s better for your mental health to just use the default &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;resolvejsonmodule&quot; style=&quot;position:relative;&quot;&gt;resolveJsonModule&lt;a href=&quot;#resolvejsonmodule&quot; aria-label=&quot;resolvejsonmodule permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Disallows importing modules with &lt;code class=&quot;language-text&quot;&gt;*.json&lt;/code&gt; extensions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows importing modules with &lt;code class=&quot;language-text&quot;&gt;*.json&lt;/code&gt; extensions.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;resolveJsonModule&lt;/code&gt; option determines whether to allow importing modules implemented as JSON files.&lt;/p&gt;
&lt;p&gt;If this option is &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;, TypeScript throws an error saying it can’t find the module when you import a JSON module.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// me.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;evan-moon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Frontend Engineer&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; me &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./me.json&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Cannot find module &apos;./settings.json&apos;. Consider using &apos;--resolveJsonModule&apos; to import module with &apos;.json&apos; extension.&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Enabling &lt;code class=&quot;language-text&quot;&gt;resolveJsonModule&lt;/code&gt; lets you import and use JSON modules just like regular TypeScript modules, and it even analyzes the file to automatically infer types.&lt;/p&gt;
&lt;p&gt;However, since inference using Enum or Union Types is impossible, all values are inferred as primitive types like &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt;. If you need to enforce strong type declarations, it’s better to declare your model using TypeScript modules instead of JSON modules.&lt;/p&gt;
&lt;h2 id=&quot;rootdir&quot; style=&quot;position:relative;&quot;&gt;rootDir&lt;a href=&quot;#rootdir&quot; aria-label=&quot;rootdir permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; option determines which directory to treat as the root when maintaining the current structure after compiling modules.&lt;/p&gt;
&lt;p&gt;By default, TypeScript maintains the input directory structure when compiling and outputting files. The &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; option lets you set which directory to treat as the root.&lt;/p&gt;
&lt;p&gt;If you don’t set this option, TypeScript automatically finds the file that serves as the application’s entry point and sets the directory containing that file as the root for the output directory structure.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── src
│   ├── index.ts
│   └── utils
│       └── math.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Consider a project with this structure. When &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; isn’t specified, TypeScript finds the application’s entry point &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt; and recognizes &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; as the root.&lt;/p&gt;
&lt;p&gt;The output directory will have this structure with &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; as the root:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;dist
├── index.ts
└── utils
    └── math.ts&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, if you set &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; (current path), the output directory structure changes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;dist
└── src
    ├── index.ts
    └── utils
        └── math.ts&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since I changed the root directory to the current &lt;code class=&quot;language-text&quot;&gt;myProject&lt;/code&gt; directory where &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; is located, the output directory &lt;code class=&quot;language-text&quot;&gt;dist&lt;/code&gt; has exactly the same structure as the original project directory, including the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;While it’s a fairly simple operation, there’s one caveat when using this option: &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; doesn’t affect compilation targets at all.&lt;/p&gt;
&lt;p&gt;This means if you use &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt;, all compilation target files must be located under that directory.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── src
│   ├── index.ts
│   └── utils
│       └── math.ts
├── foo.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at this configuration, the root directory is set to &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt;, and the &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; option says to compile all files.&lt;/p&gt;
&lt;p&gt;The problem is that one of these “all files,” &lt;code class=&quot;language-text&quot;&gt;foo.ts&lt;/code&gt;, isn’t inside the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; directory. The settings contradict each other.&lt;/p&gt;
&lt;p&gt;Even though &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; sets the root directory, TypeScript won’t automatically exclude &lt;code class=&quot;language-text&quot;&gt;foo.ts&lt;/code&gt; from compilation — instead, it throws this error:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;File ‘/Users/john/myProject/foo.ts’ is not under ‘rootDir’ ‘/Users/john/myProejct/src’. &lt;strong&gt;‘rootDir’ is expected to contain all source files.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As this error shows, if you set a root directory with &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt;, all source files must be inside that root directory. Even if you use &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; to designate files outside the root directory as compilation targets, TypeScript won’t automatically compile them.&lt;/p&gt;
&lt;h2 id=&quot;rootdirs&quot; style=&quot;position:relative;&quot;&gt;rootDirs&lt;a href=&quot;#rootdirs&quot; aria-label=&quot;rootdirs permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; option creates a kind of virtual root. This is much easier to understand with code than words, so let’s look at an example right away.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── core
│   └── index.ts
├── utils
│   └── math.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Imagine an application with this structure. How would you import the &lt;code class=&quot;language-text&quot;&gt;utils/math.ts&lt;/code&gt; module in &lt;code class=&quot;language-text&quot;&gt;core/index.ts&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Without using the &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; option, you’d use a relative path to climb up one level to the parent directory and access the module.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// core/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; math &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; option creates a virtual root so that modules in the &lt;code class=&quot;language-text&quot;&gt;core&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;utils&lt;/code&gt; directories can be used as if they were in “a single directory.”&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDirs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;utils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// core/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; math &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Use as if in the same directory&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even if the directory depth is deep like &lt;code class=&quot;language-text&quot;&gt;core/components/Foo/index.tsx&lt;/code&gt;, registering the directory in &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; lets directories registered in &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; import modules as if they’re always in the same directory.&lt;/p&gt;
&lt;p&gt;And because &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; implements this by creating a kind of “virtual directory,” it has no effect whatsoever on the output directory structure after compilation. It’s literally virtual.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; option is convenient in that it lets you use simple relative paths even with deep directory structures.&lt;/p&gt;
&lt;p&gt;However, using this configuration creates a disconnect between the actual directory structure and the paths used in code to access modules, making the code harder to understand intuitively. And to understand the cause of this disconnect, you need to look at &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; — a potentially sad situation. Keep this in mind.&lt;/p&gt;
&lt;h2 id=&quot;typeroots&quot; style=&quot;position:relative;&quot;&gt;typeRoots&lt;a href=&quot;#typeroots&quot; aria-label=&quot;typeroots permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By default, TypeScript automatically includes files under &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; package directories in compilation targets. Following the resolve strategy described earlier, it searches &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; directories inside &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; while climbing up directories: &lt;code class=&quot;language-text&quot;&gt;./node_modules/@types&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;../node_modules/@types&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;But using the &lt;code class=&quot;language-text&quot;&gt;typeRoots&lt;/code&gt; option, you can specify where TypeScript should find type files instead of searching everywhere.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typeRoots&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./typings&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./node_modules/@types&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Paths in &lt;code class=&quot;language-text&quot;&gt;typeRoots&lt;/code&gt; are relative to &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;. Also, while this example includes the &lt;code class=&quot;language-text&quot;&gt;./node_modules/@types&lt;/code&gt; directory in the option, it’s actually unnecessary.&lt;/p&gt;
&lt;p&gt;When &lt;code class=&quot;language-text&quot;&gt;typeRoots&lt;/code&gt; is specified, TypeScript abandons its existing module search strategy and only looks for type declaration modules in the paths in the array. This is more efficient than the existing module search strategy of continuously climbing up parent directories searching for type declaration modules.&lt;/p&gt;
&lt;h2 id=&quot;types&quot; style=&quot;position:relative;&quot;&gt;types&lt;a href=&quot;#types&quot; aria-label=&quot;types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As explained, TypeScript automatically includes all files under &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; package directories in compilation targets, which spreads type declarations into the global scope.&lt;/p&gt;
&lt;p&gt;Because these type declarations exist in the global scope, we can use things like the &lt;code class=&quot;language-text&quot;&gt;process&lt;/code&gt; object from &lt;code class=&quot;language-text&quot;&gt;@types/node&lt;/code&gt; without separate type declarations.&lt;/p&gt;
&lt;p&gt;But using the &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; option, you can include only specific packages’ types in the global scope.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Only import @types/node, @types/jest, @types/express&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jest&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;express&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this configuration, types for &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;jest&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;express&lt;/code&gt; packages are included in the global scope, automatically type-checking statements like &lt;code class=&quot;language-text&quot;&gt;import express from &apos;express&apos;;&lt;/code&gt;. But other libraries not included here require you to import their type declaration modules directly.&lt;/p&gt;
&lt;p&gt;The key thing to note is that the &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; option targets type declaration modules that exist inside &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; package directories.&lt;/p&gt;
&lt;p&gt;For example, the date library &lt;code class=&quot;language-text&quot;&gt;moment&lt;/code&gt; doesn’t require installing a separate type package like &lt;code class=&quot;language-text&quot;&gt;@types/moment&lt;/code&gt; — it has built-in type declaration modules.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;moment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./moment.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;jsnext:main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist/moment.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./moment.d.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Includes type declaration file internally&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, the statement &lt;code class=&quot;language-text&quot;&gt;import moment from &apos;moment&apos;&lt;/code&gt; imports the library and automatically includes &lt;code class=&quot;language-text&quot;&gt;moment.d.ts&lt;/code&gt; as a compilation target, so you can naturally use the types.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; option only targets type declaration modules inside &lt;code class=&quot;language-text&quot;&gt;@types/*&lt;/code&gt; packages and only applies when TypeScript spreads those type declarations into the global space. Don’t get confused.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot; style=&quot;position:relative;&quot;&gt;Closing Thoughts&lt;a href=&quot;#closing-thoughts&quot; aria-label=&quot;closing thoughts permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That wraps up the third installment in the tsconfig series: the Modules edition. While there aren’t that many module-related options, since they deal with which module system to use during compilation and which module resolution strategy to use, the explanations got lengthy.&lt;/p&gt;
&lt;p&gt;And now that I’ve written this far, a realization hits me…&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2f03c5fd1831cbdc146edbf1130bd061/00d43/tsconfig.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 94.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAAC1UlEQVR42oVTZ1PbQBTU//8vhJrQMcaUDKGXTBKKcbflpi5Zstnsni1iEmbyYefda/v2nk5WEIXo9HuwB320e10EoxhjABlekb5O3tkc8j/EOIMVPj/BvblG+vhgkPz8geD7Pfy7WwT3d/9Y7/YGIfOqzebx8AtprQorPj9DvLmBeHcHCZEV95HuFz6EyRX2kNJmf2NvF+nFOSzv9BT9tVUMtzYRqvjoEEnpwCA+KGJ0WMKoVJr6xSJS+gnj8rPjoz9gPOVNreDsGwKSqWjy9QTR/h5aS0toL09hryyjM4O9sgJ7dYX5RWMDqvJ5K9mRVF5fwUquLzGhKk0ZExFVNhYW0Fz8ZBpFZOzylFTxNn0NU6z3eQ1d3tBZ/4KI4qz46hLZnPwRz5rq7WwbGxYK8GdKTHymKOBgd3sLDuGqljYyOzw5hk92Q6rdsHDIqQPtldbb2IDLvLe5zvO6UTJg3OXZ195JFnFATMLs8oKEzQaSVhOp3TGI6Q/4lIblZzgvZbiVl3foPz0a65TLJh+xPqjXEBIZ37Ll+R6SdIQ0S5FNxvDDAFW+p0argVqjblBlcYXQuVKvokxCod6c1lRYL/iBz4/CP2VCsjFJs1GCgAOaLBLsThv9ro0h/ySH03u8wYB/k9BlTnG73TK5iGTislxniAETQwZTEsYM6uwMB/A9FyELVSN4rmP8sW4jAXNQr2CpSM2yCiRxZFTOQzlZkWmg6kZJ/A5vhCKzeRU1aFLEHUqhVOfKVKNB883/VZhfWYStZhNtfvkO9yObQ369VjO7zVehXlkNNITak0gFkSlhlM0G5evId5j7Dn2JEJTTAKm38sY+v5ysSKWgx6/b5So6PA/600b5dqdj1pHndQ58n33hlFCBuh4mJ7zyHcqKUMV5Q5fN5glxqIhyZVqBrG6lj2UIpUpFUqblBiSsVSvcVdW8xRYfb6/bfXtGOfLnJpvHRPwbAA92vl9EkpcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;tsconfig&quot; title=&quot;&quot; src=&quot;/static/2f03c5fd1831cbdc146edbf1130bd061/6af66/tsconfig.png&quot; srcset=&quot;/static/2f03c5fd1831cbdc146edbf1130bd061/69538/tsconfig.png 160w,
/static/2f03c5fd1831cbdc146edbf1130bd061/72799/tsconfig.png 320w,
/static/2f03c5fd1831cbdc146edbf1130bd061/6af66/tsconfig.png 640w,
/static/2f03c5fd1831cbdc146edbf1130bd061/d9199/tsconfig.png 960w,
/static/2f03c5fd1831cbdc146edbf1130bd061/00d43/tsconfig.png 1000w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;Wait... I&apos;ve only written this much...?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;I knew tsconfig had many options, but I never imagined it would be this challenging. &lt;small&gt;&lt;del&gt;(First time my wrist hurt from writing…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Of course, if I just translated the official docs line by line, I’d finish quickly. But the whole point of starting this post series wasn’t just to provide that level of information — it was to do a complete analysis of tsconfig, so I’ll keep pushing forward.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/2021/10/30/tsconfig-compiler-options-modules-emit/&quot;&gt;In the next post&lt;/a&gt;, I’ll discuss options that control TypeScript’s behavior when generating output files.&lt;/p&gt;
&lt;p&gt;That concludes this post: [Everything About tsconfig] Compiler options / Modules.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[tsconfig의 모든 것] Compiler options / Modules]]></title><description><![CDATA[이번 포스팅에서는 지난 [tsconfig의 모든 것] Compiler options / Type Checking 포스팅에 이어 의 컴파일 옵션 중 모듈과 관련된 옵션들에 대한 이야기를 해보려고 한다.]]></description><link>https://evan-moon.github.io/2021/08/22/tsconfig-compiler-options-modules/</link><guid isPermaLink="false">20210822-tsconfig-compiler-options-modules</guid><pubDate>Sun, 22 Aug 2021 03:11:05 GMT</pubDate><content:encoded>&lt;p&gt;이번 포스팅에서는 지난 &lt;a href=&quot;/20210808-tsconfig-compiler-options-type-check&quot;&gt;[tsconfig의 모든 것] Compiler options / Type Checking&lt;/a&gt; 포스팅에 이어 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt;의 컴파일 옵션 중 모듈과 관련된 옵션들에 대한 이야기를 해보려고 한다.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;이 옵션들은 타입스크립트를 컴파일할 때 모듈들이 어떤 모듈 시스템을 따르도록 할 것인지, 어떤 경로에 있는 파일들을 컴파일 할 것인지, 빌드된 자바스크립트 파일들이 어떤 모듈 방식을 따르게 할 것인지 등을 컨트롤 할 수 있는 것들인데, 일반적인 서비스를 만드는 경우보다는 타입스크립트로 작성된 라이브러리를 만들 때 자주 다루게 되는 옵션들이기도 하다.&lt;/p&gt;
&lt;h2 id=&quot;allowumdglobalaccess&quot; style=&quot;position:relative;&quot;&gt;allowUmdGlobalAccess&lt;a href=&quot;#allowumdglobalaccess&quot; aria-label=&quot;allowumdglobalaccess permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;umd 모듈로의 접근을 허용한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;umd 모듈로의 접근을 허용하지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;allowUmdGlobalAccess&lt;/code&gt; 옵션은 타입스크립트 모듈이 전역 객체에 모듈을 포함시켜 내보내는 UMD(Universal Module Definition)형태의 모듈에 접근이 가능하게 할 것인지를 컨트롤 하는 옵션이다.&lt;/p&gt;
&lt;p&gt;만약 이 옵션이 꺼져 있다면 jQuery의 &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt;와 같은 전역 변수에 그냥 접근하는 것이 불가능해지고, 무조건 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; 문을 통해서 모듈을 가져와야 한다.&lt;/p&gt;
&lt;p&gt;UMD 방식을 사용하여 만들어진 라이브러리들은 보통 이런 형태의 글로벌 타입 선언을 가지고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;doThing1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnInterface&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  foo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; myLibrary&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 타입 파일이 네임스페이스를 export 하도록 선언되어 있는 경우, 타입스크립트는 이 모듈이 암묵적으로 전역 변수인 &lt;code class=&quot;language-text&quot;&gt;myLibrary&lt;/code&gt;에 할당된다고 판단한다. 그렇기 때문에 이런 타입 선언을 내 소스에 포함시키면 &lt;code class=&quot;language-text&quot;&gt;myLibrary&lt;/code&gt;라는 네임스페이스를 통해 이 모듈의 내용물에 접근할 수가 있는 것이다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;allowUmdGlobalAccess&lt;/code&gt; 옵션이 꺼져있는 상태라면 이런 에러를 만나게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; myLibrary&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doThing1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &apos;myLibrary&apos; refers to a UMD global, but the current file is a module. Consider adding an import instead.ts(2686)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 &lt;code class=&quot;language-text&quot;&gt;allowUmdGlobalAccess&lt;/code&gt; 옵션을 켜게 되면 네임스페이스로 export된 UMD 모듈에 접근하는 것이 허용된다. 하지만 굳이 암묵적으로 전역 변수에 선언되어있는 모듈에 접근해서 사용하는 것보다 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; 키워드로 명시적으로 모듈을 가져와서 사용하는 것이 더 안전하니, 피치 못하는 경우가 아니라면 가급적 해당 옵션을 켜두도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;baseurl&quot; style=&quot;position:relative;&quot;&gt;baseUrl&lt;a href=&quot;#baseurl&quot; aria-label=&quot;baseurl permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; 옵션은 상대 경로로 모듈의 경로를 지정할 때 기준이 되는 위치를 지정할 수 있는 옵션이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── index.ts
├── utils
│   └── foo.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;예를 들어 위와 같은 상황일 때, &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt;에서 상대 경로를 사용하여 &lt;code class=&quot;language-text&quot;&gt;foo.ts&lt;/code&gt; 모듈을 가져오려면 &lt;code class=&quot;language-text&quot;&gt;./utils/foo&lt;/code&gt;와 같이 현재 기준이 되는 위치를 &lt;code class=&quot;language-text&quot;&gt;./&lt;/code&gt; 처럼 지정한 후 해당 모듈에 접근하게 된다.&lt;/p&gt;
&lt;p&gt;하지만 잘 생각해보면 아무리 상대 경로를 사용한다고 해도, 기준이 되는 위치 자체가 변하는 경우는 많지 않다는 것을 알 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── index.ts
├── utils
│   └── foo.ts
├── remotes
│   └── bar.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 이런 구조의 프로젝트의 &lt;code class=&quot;language-text&quot;&gt;remotes/bar&lt;/code&gt; 모듈에서 &lt;code class=&quot;language-text&quot;&gt;utils/foo&lt;/code&gt; 모듈에 접근하려고 한다면 결국 &lt;code class=&quot;language-text&quot;&gt;../utils/foo&lt;/code&gt; 처럼 프로젝트의 루트까지 올라간 후 다시 내려오는 방식으로 접근을 하기 때문이다.&lt;/p&gt;
&lt;p&gt;그래서 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; 옵션은 상대경로를 사용할 때마다 반복되는 “루트로의 여정”을 없애주는 역할을 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;baseUrl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이때 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;에 입력하는 상대 경로의 기준은 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt;가 위치하는 곳이기 때문에 일반적으로는 프로젝트의 루트가 된다. 즉, 이렇게 설정한 후 우리가 모듈에 접근하기 위해 상대 경로를 사용하게 되면, 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;에 입력된 루트의 위치에서부터 해당 모듈을 찾아가게 되는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utils/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 사실 .(루트)/utils/foo&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; bar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;remotes/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 사실 .(루트)/remotes/bar&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; 옵션을 사용하면 매번 &lt;code class=&quot;language-text&quot;&gt;./&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;../&lt;/code&gt; 등을 사용하여 루트를 먼저 찾은 후 모듈에 접근하는 상대 경로를 절대 경로처럼 사용할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;paths&quot; style=&quot;position:relative;&quot;&gt;paths&lt;a href=&quot;#paths&quot; aria-label=&quot;paths permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; 옵션은 특정한 모듈 이름을 지정했을 때 컴파일러가 어디서 부터 모듈을 탐색해야 할 지를 지정할 수 있는 맵을 제공한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;baseUrl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;paths&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;app/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;config/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app/_config/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;environment/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;environments/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;shared/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app/_shared/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;helpers/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;helpers/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;tests/*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tests/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;맵에 포함되는 경로들은 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;을 기준으로 상대 경로로 계산되기 때문에, &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; 옵션을 사용하기 위해서는 반드시 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt; 옵션에 값을 채워주어야 한다. 즉, 위 예시의 &lt;code class=&quot;language-text&quot;&gt;app/*&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;./src/app/*&lt;/code&gt;를 의미하며, 모듈을 불러올 때 &lt;code class=&quot;language-text&quot;&gt;import foo from &apos;app/math&apos;&lt;/code&gt;와 같이 접근하게 되면, 타입스크립트는 자동으로 맵에 해당하는 경로인 &lt;code class=&quot;language-text&quot;&gt;./src/app/math&lt;/code&gt;를 탐색한 후 모듈을 가져오게 된다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; 옵션에 설정된 위치들을 전부 탐색했는데도 모듈을 찾지 못 했다면, &lt;code class=&quot;language-text&quot;&gt;moduleResolution&lt;/code&gt; 옵션에서 설정한 전략에 따라 추가적인 탐색을 진행하게 된다.&lt;/p&gt;
&lt;p&gt;사실 패스 매핑 자체는 워낙 간단한 설정이기 때문에 크게 어려울 것이 없지만, 종종 패스 매핑이 반드시 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;을 기준으로 시작한다는 점을 까먹어서 실수를 하곤 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── src
│   └── index.ts
├── node_modules
│   └── foo
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 구조의 프로젝트에서 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;로 &lt;code class=&quot;language-text&quot;&gt;./src&lt;/code&gt;를 지정한 상황을 생각해보자. 우리가 &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt;라는 패스에 &lt;code class=&quot;language-text&quot;&gt;node_modules/foo&lt;/code&gt;를 매핑하려면 어떻게 해야할까?&lt;/p&gt;
&lt;p&gt;이때 자주 하는 실수는 &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;의 위치를 기준으로 &lt;code class=&quot;language-text&quot;&gt;&quot;foo&quot;: &quot;./node_modules/foo&quot;&lt;/code&gt;라고 설정하는 것이다. 아무래도 내가 지금 패스 매핑 작업을 하고 있는 파일이 &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;이니 별 생각없이 현재 파일 기준으로 경로를 지정하는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 패스 매핑은 &lt;code class=&quot;language-text&quot;&gt;baseUrl&lt;/code&gt;을 기준으로 진행되기 때문에 이 경우에는 &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; 디렉토리가 기준점이 된다. 즉, &lt;code class=&quot;language-text&quot;&gt;&quot;foo&quot;: &quot;../node_modules/foo&quot;&lt;/code&gt;로 매핑을 진행해주어야 한다는 것이다.&lt;/p&gt;
&lt;p&gt;간혹 이 점을 잊고 &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;의 위치를 기준으로 패스 매핑을 진행했다가 모듈 탐색에 실패하는 경우가 왕왕 있으니 주의하도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;module&quot; style=&quot;position:relative;&quot;&gt;module&lt;a href=&quot;#module&quot; aria-label=&quot;module permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;CommonJS&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;CommonJS 형식으로 모듈을 컴파일한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;AMD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Asynchronous Module Definition 형식으로 모듈을 컴파일한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;UMD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Universal Module Definition 디자인 패턴을 사용하여 모듈을 컴파일한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;System&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;System.js 형식으로 모듈을 컴파일한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;ES6&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ES2015&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ES2020&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ESNext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESM(ES Module) 방식으로 모듈을 컴파일한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; 옵션은 컴파일을 마친 자바스크립트 모듈이 어떤 모듈 시스템을 사용할 지를 설정하는 옵션이다.&lt;/p&gt;
&lt;p&gt;물론 ECMAScript에서 지정한 공식 모듈 시스템은 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; 키워드를 사용하는 ESM 방식이기는 하지만, 현실적으로 이러한 모듈 시스템을 지원하는 브라우저가 아직 많지 않고, NodeJS 같은 경우 지난 12.0.0 버전에서 &lt;code class=&quot;language-text&quot;&gt;--experimental-modules&lt;/code&gt; 플래그 없이 ESM을 사용할 수 있는 기능이 추가되기는 했지만, 아직 생태계 전체에 ESM 시스템이 퍼져있는 상황은 아니다. &lt;small&gt;(NodeJS 진영은 아직 CommonJS를 많이 사용한다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;이런 이유들로 인해 우리의 모듈이 무조건 ESM 시스템을 사용하도록 컴파일하기는 현실적으로 어렵기 때문에, 적절히 상황에 맞는 모듈 시스템을 선택할 수 있어야 하는 것이다.&lt;/p&gt;
&lt;p&gt;이 포스팅에서 자바스크립트의 모듈 시스템에 대한 모든 것을 다룰 수는 없으니, 각 모듈 시스템들의 특징 정도만 간단하게 알아보고 넘어가도록 하겠다. 한번 간단하게 두 개의 모듈로 구성된 어플리케이션을 상상해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils/math.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 어플리케이션의 &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; 모듈은 &lt;code class=&quot;language-text&quot;&gt;utils/math.ts&lt;/code&gt; 모듈에서 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt;라는 함수를 가져와서 커링을 통해 &lt;code class=&quot;language-text&quot;&gt;add2&lt;/code&gt; 함수를 생성하고 다시 내보내는 모듈이다. 이제 이 어플리케이션을 각각의 모듈 시스템을 사용하도록 컴파일하면 &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt;가 어떻게 변경되는지, 그리고 각 모듈 시스템의 특징이 무엇인지 살펴보도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;commonjs&quot; style=&quot;position:relative;&quot;&gt;CommonJS&lt;a href=&quot;#commonjs&quot; aria-label=&quot;commonjs permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; math_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;CommonJS&lt;/code&gt;는 Common이라는 이름답게, 자바스크립트 모듈을 브라우저 뿐 아니라 서버 환경이나 데스크탑 어플리케이션 내에서도 자유롭게 사용하는 것을 표방하고 있는 모듈 시스템이다.&lt;/p&gt;
&lt;p&gt;그런 이유로 서버 사이드에서 주로 사용하는 런타임인 NodeJS 같은 경우에는 아직까지 CommonJS 시스템을 사용하고 있는 환경이 많기 때문에 서버 사이드에서 사용할 라이브러리 등을 만든다면 해당 CommonJS 시스템을 사용하는 것을 고민해봐야 한다.&lt;/p&gt;
&lt;p&gt;CommonJS는 &lt;code class=&quot;language-text&quot;&gt;exports&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;module.exports&lt;/code&gt; 객체의 프로퍼티에 모듈을 할당하고, 전역함수 &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt;를 통해 동기적으로 모듈을 직접 가져오는 방식을 사용한다. 위 예시에서도 &lt;code class=&quot;language-text&quot;&gt;math_1&lt;/code&gt;이라는 변수에 &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt;라는 함수를 통해 모듈을 할당하고, &lt;code class=&quot;language-text&quot;&gt;exports.add2&lt;/code&gt; 프로퍼티에 &lt;code class=&quot;language-text&quot;&gt;add2&lt;/code&gt; 함수를 다시 할당하고 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt; 함수가 실행될 때 동기적으로 모듈을 가져오는 CommonJS의 특징 덕분에 &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; 문을 사용하여 “이럴 땐 A 모듈, 저럴 땐 B 모듈을 가져와!” 같은 짓을 하는 것도 가능하다.&lt;/p&gt;
&lt;h3 id=&quot;amd&quot; style=&quot;position:relative;&quot;&gt;AMD&lt;a href=&quot;#amd&quot; aria-label=&quot;amd permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;require&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;require&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exports&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;AMD(Asynchronous Module Definition)&lt;/code&gt;는 이름에 걸맞게 비동기적으로 모듈을 가져오는 방식을 사용하는 모듈 시스템이다.&lt;/p&gt;
&lt;p&gt;기존의 CommonJS는 동기적으로 모듈을 가져오는 것을 전제로 개발되었기 때문에 항상 비동기적으로 모듈을 가져오는 방식을 구현하기 위한 활발한 논의가 있었는데, 이 논의 과정 속에서 기존의 CommonJS의 정신인 “모든 환경에서 작동하는 자바스크립트 모듈”에 공감하지 못하는 사람들이 나왔고, 이 사람들이 따로 독립하여 AMD 그룹을 만들게 되었다.&lt;/p&gt;
&lt;p&gt;사실 브라우저 환경은 애초에 서버와 다르게, 필요한 모듈들을 서버로부터 받아와서 사용해야 하는 환경이다. 그렇기 때문에 필요한 모든 모듈을 한번에 받아서 실행하는 것보다 모듈 중에서 필요한 부분만 서버로부터 비동기적으로 가져와서 사용하는 것이 더 효율적인 것이다. 하지만 “모든 환경에서 작동하는 자바스크립트 모듈”을 목표로 하는 CommonJS 그룹에서는 이런 환경 차이를 통합하기가 쉽지 않았다.&lt;/p&gt;
&lt;p&gt;이 과정에서 “브라우저만이라도 제대로 해보자”라는 의견을 가진 사람들이 독립하여 AMD 시스템이 탄생하게 되었고, 그런 이유로 AMD 시스템은 브라우저에서의 비동기 모듈 호출에 초점을 맞추고 개발되었다. &lt;small&gt;(물론 CommonJS도 이후 비동기 모듈 로딩 기능을 따로 추가했다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;하지만 결국 CommonJS에서 떨어져 나온 그룹인만큼 CommonJS와 AMD는 서로 호환할 수 있는 기능들을 많이 제공하고 있기 때문에, 기존의 CommonJS 모듈을 AMD 방식으로 래핑해서 사용하는 등의 응용도 가능하다.&lt;/p&gt;
&lt;p&gt;위 예시에서도 AMD 시스템의 &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; 함수가 기본적으로 CommonJS의 &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; 함수를 가져와서 사용하고 있는 모습을 볼 수 있다. 기본적으로 내부 구조는 CommonJS와 비슷하지만, &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt;함수를 통해 모듈을 가져오는 것이 아니라, &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; 함수의 3번째 인자인 &lt;code class=&quot;language-text&quot;&gt;math_1&lt;/code&gt;을 통해 모듈을 주입받고 있다는 것이 CommonJS 시스템과의 결정적인 차이이다.&lt;/p&gt;
&lt;h3 id=&quot;umd&quot; style=&quot;position:relative;&quot;&gt;UMD&lt;a href=&quot;#umd&quot; aria-label=&quot;umd permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; module &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; v &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;require&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exports&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; define &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; define&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;require&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; factory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;require&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; math_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;UMD(Universal Module Definition)&lt;/code&gt;은 모듈 시스템이라기보다 다양한 환경에서 Universal, 즉, 범용으로 사용할 수 있는 형태의 디자인 패턴이라고 볼 수 있다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 UMD 패턴은 보통 &lt;code class=&quot;language-text&quot;&gt;RequireJS&lt;/code&gt; 같은 라이브러리를 통해 사용하는 AMD나 CommonJS와 다르게, 직접 개발자가 직접 UMD 패턴을 사용한 코드를 작성해줘야 한다. 쉽게 말해 위의 예시처럼 IIFE(Immediately Invoked Function Expression, 즉시실행함수)를 사용하여 개발자가 직접 소스 코드 내에서 분기를 쳐주는 것이 결국 UMD 패턴이라는 것이다.&lt;/p&gt;
&lt;p&gt;위 예시를 보면 &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;module.exports&lt;/code&gt;가 존재한다면 CommonJS 시스템을, &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; 함수가 존재한다면 AMD 시스템을 사용하는 것을 볼 수 있다. 이처럼 UMD 패턴은 모듈이 사용되는 환경이 어떤 모듈 시스템을 사용하는지 여부와 상관없이 항상 동일한 경험을 제공할 수 있다는 장점이 있다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9a3cbcb2d8922dd1e01e855b408e4af4/22475/all_taken.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC10lEQVR42k2SSU9TURiGK1opBUpRFBREoy5ETYhKjDGaOEaN08aoCyMhaqIGB9hoxAEBK8YBp1Kwg9iR3tKWFluo4oSgSAMBozaGpYk7/QuP361GXTy55yb3Puf93nM0RX1PKertSTMnHmGWuk7EWNgbYGHMx/xoiNJwmBKhKNhFcTDMXCWEwauQ7e4UfGS7fpMjaAp7/xPGIqzzPqLYaqY8YWNt4iHL4iHKYrJBNMKSaJSybnmGujG6veg8frK9gtP7TzgjHKRAUsyJRyno66HM5+S4uZVLE5/Y9WaAc2NjVI+McHBgkKvjHzk9PELlwHvKXWZKLS3k2DrQq0ldIpVNNAa/n/xQF4VPu5mtCu+1UHfxIq9SXzieTOKanKR+fILDQ+/o//ady6Pj7In3s995h/VnjpDf1IxeCUpKz29hbqcfY0BhpiQtjIbZbGqgreEUV/pitHydpGpwiCqRbU8849S7Qfa9eEW5v4u5dVeYd7IanekW+j8d/hXmSso8RaFASi/pDqOLRDg2/IHUj5/cSn2lJt7HI1sblf2d7I4naJTvNjQ2sfxsLfuvNlDicJKZ7tGNJsfnR0UVGoNB8oIhpvuV9Ijmzyk2979ksRR/2mGn1uOlSrqskfWh2lq2XL/BxkAAvQj1HZ50j2lhrioUSZ4/gFFQT+/E0DAXkmPc/ZTi6NAHHKMTWOS9ZjjJoZ4Y8x62UnLvAfntdrQOd1qoIoeioI6dJ2MbJIlBZDrpY+fzl+ztfcbWrgCbFB/1g28wJUc58vY9B1+8Zqb8o3W6ybI/IcvmQmd3keVwibBTkgk6KTRDZFphmtNHxhMP2sduFjWZONBQx47GenaamimSRBkeH9oOJ1Otj5ki12a63Y1BUuaLXKOmyhTJOhHubjez0uZgjd3KUquDBdZ2tl2uZk3zTVbcvsPq89eouN/GKpudJa0WKtpaqbC0Y7TYKJW7WGzr4BekrCjuRnfpjQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;all taken&quot; title=&quot;&quot; src=&quot;/static/9a3cbcb2d8922dd1e01e855b408e4af4/6af66/all_taken.png&quot; srcset=&quot;/static/9a3cbcb2d8922dd1e01e855b408e4af4/69538/all_taken.png 160w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/72799/all_taken.png 320w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/6af66/all_taken.png 640w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/d9199/all_taken.png 960w,
/static/9a3cbcb2d8922dd1e01e855b408e4af4/22475/all_taken.png 1039w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;UMD === 뭘 좋아할 지 몰라서 모든 모듈 시스템을 다 준비했어&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;추가적으로, 모듈을 사용하는 환경이 CommonJS, AMD 두 시스템 모두 지원하지 않는 경우에는 UMD 패턴을 사용하여 전역 객체인 &lt;code class=&quot;language-text&quot;&gt;globalThis&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;global&lt;/code&gt; 등의 프로퍼티로 모듈을 넣는 최후의 방법도 있기는 하다.&lt;/p&gt;
&lt;p&gt;하지만 이 방법은 전역 스코프를 오염시키기 때문에 가급적이면 피하는 것이 좋기도 하고, 최근의 자바스크립트 런타임 환경에서 모듈 시스템 자체가 지원되지 않는 환경이 강제되는 경우는 흔치 않으므로 타입스크립트는 이런 방법까지는 사용하지 않는 것으로 보인다.&lt;/p&gt;
&lt;h3 id=&quot;system&quot; style=&quot;position:relative;&quot;&gt;System&lt;a href=&quot;#system&quot; aria-label=&quot;system permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./utils/math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;exports_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; __moduleName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context_1 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; context_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;setters&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;math_1_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                math_1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; math_1_1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function-variable function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;exports_1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;add2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; math_1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;UMD 패턴이 “네가 뭘 좋아할 지 몰라서 다 준비했어”의 디자인 패턴 버전이라면, &lt;code class=&quot;language-text&quot;&gt;SystemJS&lt;/code&gt;는 이걸 라이브러리로 구현한 모듈 로더이다. &lt;small&gt;(한 술 더 떴다)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;즉, SystemJS는 모듈 로더이기 때문에 모듈을 어떻게 정의하는지에 대한 것은 관여하지 않고, 그저 이미 CommonJS, AMD, ESM 방식으로 정의된 모듈을 로드해주기만 하는 녀석이다.&lt;/p&gt;
&lt;p&gt;SystemJS는 2016년 ECMA 재단이 ES6의 공식 모듈 스펙으로 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; 키워드를 사용하는 ESM 패턴을 발표했을 때 즈음 꽤나 많이 사용되던 녀석인데, 그 이유는 이 당시 브라우저들이 이 스펙을 지원하지 않았기 때문이다.&lt;/p&gt;
&lt;p&gt;모듈링에 대한 공식 스펙은 정해졌으나 정작 그걸 실행시킬 브라우저 벤더들의 대응이 늦는 상황이라 ESM을 사용하고 싶어도 할 수가 없는 상황이었는데, 이때 SystemJS가 이 중간 다리 역할을 해줬었다. 당시에는 &lt;a href=&quot;https://github.com/ModuleLoader/es-module-loader&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;es-module-loader&lt;/a&gt;라는 폴리필을 사용하여 ESM 방식의 모듈을 불러오도록 구현되어있었다.&lt;/p&gt;
&lt;p&gt;그런데 여기서 한 가지 의문이 드는 것이 “브라우저가 지원하지 않는 모듈을 불러와도 트랜스파일링을 하지 않으면 실행을 시킬 수 없는 경우도 있을텐데, SystemJS는 이 문제를 어떻게 해결하는 걸까?”라는 것인데, 정답은 의외로 가까운 곳에 있었다.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/934e6cd11f70c175f5171121f4db2f65/47311/cool.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAAB56Spyjs0/wD/xAAZEAEBAAMBAAAAAAAAAAAAAAABAgADEUL/2gAIAQEAAQUCjrIGbBb8VHJOuf/EABgRAAIDAAAAAAAAAAAAAAAAAAABESEx/9oACAEDAQE/AVTk0//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/AYf/xAAZEAACAwEAAAAAAAAAAAAAAAAAAQIRITH/2gAIAQEABj8Ct2YOiCHrOn//xAAYEAADAQEAAAAAAAAAAAAAAAABESEAMf/aAAgBAQABPyGnEOXAlvy4sBMDcyKrzDMHBp5B5//aAAwDAQACAAMAAAAQj/8A/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhMf/aAAgBAwEBPxC4NaP/xAAXEQADAQAAAAAAAAAAAAAAAAAAASEx/9oACAECAQE/EKUMh//EAB0QAQEAAgEFAAAAAAAAAAAAABEBACExUWFxgZH/2gAIAQEAAT8QEYDaY9sW2mi1n25ZldIzxkYiAAnnD+oHA9cvhnpz/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cool&quot; title=&quot;&quot; src=&quot;/static/934e6cd11f70c175f5171121f4db2f65/c08c5/cool.jpg&quot; srcset=&quot;/static/934e6cd11f70c175f5171121f4db2f65/0913d/cool.jpg 160w,
/static/934e6cd11f70c175f5171121f4db2f65/cb69c/cool.jpg 320w,
/static/934e6cd11f70c175f5171121f4db2f65/c08c5/cool.jpg 640w,
/static/934e6cd11f70c175f5171121f4db2f65/6a068/cool.jpg 960w,
/static/934e6cd11f70c175f5171121f4db2f65/47311/cool.jpg 1080w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;복잡한 건 잘 모르겠고, 그냥 babel 가져와서 런타임에 쿨하게 트랜스파일링 돌리자&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;그렇다. 이 방법을 쓰면 불러올 대상 모듈의 언어가 ES2020나 타입스크립트라도 아무 문제가 없고, 모듈 시스템으로 CommonJS를 사용하던 AMD를 사용하던 아무 문제가 없다. 물론 이 기능은 SystemJS의 기본 기능이 아니라서 &lt;a href=&quot;https://github.com/systemjs/systemjs-babel&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;systemjs-babel&lt;/a&gt;이라는 익스텐션을 사용해야 하지만, 문제 해결 방식 자체가 상당히 화끈한 것이 인상적이다.&lt;/p&gt;
&lt;p&gt;하지만 런타임에 모듈을 트랜스파일링한다는 것은 단순히 트랜스파일링만의 문제가 아니라 모듈 간의 의존관계도 파악해야하고, 심지어 타입스크립트를 사용하는 경우에는 정적 타입 체크를 거친 컴파일까지 해야하기 때문에, 당연히 빌드 타임에 이런 무거운 작업을 수행해버리면 퍼포먼스가 떨어질 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;2021년 현재, 모두가 알다시피 이런 무거운 작업들은 모두 빌드 타임에 진행해도 아무 문제가 없으니, 굳이 런타임에 이런 짓을 벌이는 SystemJS는 특수한 상황이 아니면 쓰이지 않는 분위기인 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;es-module&quot; style=&quot;position:relative;&quot;&gt;ES Module&lt;a href=&quot;#es-module&quot; aria-label=&quot;es module permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;ESM(ES Module)&lt;/code&gt; 방식은 ECMA 재단에서 공식으로 정의한 자바스크립트 생태계의 모듈 시스템이다.&lt;/p&gt;
&lt;p&gt;그런 이유로 &lt;code class=&quot;language-text&quot;&gt;require&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;define&lt;/code&gt; 같은 별도의 함수에 의존하여 모듈을 불러오는 CommonJS나 AMD와 다르게 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt;라는 키워드를 사용하여 모듈을 불러오는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;2015년에 등장한 ESM은 2009년부터 사용하던 CommonJS나 AMD에 비하면 후발 주자인 주제에, 모듈에 &lt;code class=&quot;language-text&quot;&gt;use strict&lt;/code&gt; 디렉티브가 반드시 포함되어야 한다던가, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;가 전역 객체인 &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt;를 바라보지 않는 등의 변경 사항이 많았던 스펙이기도 했다.&lt;/p&gt;
&lt;p&gt;그래서 이런 제약이 없는 CommonJS나 AMD 시스템을 사용하던 어플리케이션들이 손쉽게 마이그레이션을 할 수 있는 상황이 아니였고, 그 상황이 지금까지도 이어져오고 있다.&lt;/p&gt;
&lt;p&gt;그런 이유로 오늘 날에도 네이티브 자바스크립트 환경에서 ESM을 사용하기 위해서 &lt;code class=&quot;language-text&quot;&gt;script&lt;/code&gt; 태그에 &lt;code class=&quot;language-text&quot;&gt;type=&quot;module&quot;&lt;/code&gt; 속성을 추가하거나, &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;&quot;type&quot;: &quot;module&quot;&lt;/code&gt;이라는 필드를 추가해줘야 하는 등 별도의 작업이 필요한 것이다.&lt;/p&gt;
&lt;p&gt;물론 예전에 비하면 최근 많은 벤더들이 ESM을 지원하고 있지만, 그래도 아직까지 ESM을 안전하게 사용하기 위해서는 Webpack이나 Babel같은 번들러와 트랜스파일러를 조합하여 빌드 타임에 모듈 간의 의존 관계를 파악하고 런타임이 알아들을 수 있는 형태로 변환해주는 과정이 필요하기 때문에, 모듈을 사용하는 환경이 어떤 환경인지에 따라서 때로는 사용하기 번거로운 포맷이 될 수 있다는 것을 염두에 두어야 한다.&lt;/p&gt;
&lt;p&gt;다만 ESM은 이런 단점을 모두 씹어먹을 수 있을 정도의 한 가지 장점을 가지고 있는데, 바로 Webpack으로 모듈을 번들링할 때 트리쉐이킹이 수월하다는 것이다.&lt;/p&gt;
&lt;p&gt;Webpack의 &lt;a href=&quot;https://webpack.js.org/plugins/module-concatenation-plugin/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;ModuleConcatenationPlugin&lt;/a&gt;은 모듈들을 하나의 클로저로 통합하여 브라우저 환경에서 더 높은 퍼포먼스를 만들어내는데, 이때 CommonJS와 ESM 중 어떤 모듈 시스템을 사용하냐에 따라 결과물이 많이 달라지게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// CommonJS&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* harmony import */&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _utils__WEBPACK_IMPORTED_MODULE_0__ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__webpack_require__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;_utils__WEBPACK_IMPORTED_MODULE_0__&lt;span class=&quot;token comment&quot;&gt;/* .add */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DG&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Webpack을 통해 번들링 했을 때 CommonJS 시스템을 사용한 모듈은  &lt;code class=&quot;language-text&quot;&gt;__webpack_require__&lt;/code&gt;라는 함수를 통해 불러와지게 되는데, 문제는 이게 모듈 내부에 있는 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; 함수만 불러오는 것이 아니라 전체 모듈을 다 불러오는 코드라는 것이다.&lt;/p&gt;
&lt;p&gt;다음 라인인 &lt;code class=&quot;language-text&quot;&gt;(0,_utils__WEBPACK_IMPORTED_MODULE_0__/* .add */ .DG)&lt;/code&gt;를 보면, 불러온 모듈의 &lt;code class=&quot;language-text&quot;&gt;DG&lt;/code&gt;라는 프로퍼티에 접근하고 있는 것을 볼 수 있는데, 이 &lt;code class=&quot;language-text&quot;&gt;DG&lt;/code&gt;가 난독화된 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; 함수의 이름이다.&lt;/p&gt;
&lt;p&gt;애초에 CommonJS는 &lt;code class=&quot;language-text&quot;&gt;exports&lt;/code&gt;라는 전역 객체의 프로퍼티에 값들을 할당하는 방식을 사용하기 때문에, “이 모듈에서 A라는 함수만 사용한다”라는 것을 파악하기가 쉽지가 않은 것이다.&lt;/p&gt;
&lt;p&gt;하지만 ESM 시스템을 사용한 모듈은 각각의 &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; 키워드를 사용하여 원하는 값을 따로 내보낼 수 있고, 그로 인해 상세한 의존 관계를 파악하기가 한결 수월하다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ESM&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// webpackBootstrap&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// CONCATENATED MODULE: ./utils/math.js**&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// CONCATENATED MODULE: ./index.js**&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Webpack을 통해 번들링한 ESM 시스템의 모듈을 보면, 애초에 모듈을 불러오는 코드 자체가 없고 심지어 모듈 내부에 있던 함수를 인라인으로 박아버렸다.&lt;/p&gt;
&lt;p&gt;물론 필자가 불러온 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; 함수는 매우 작은 함수라 이런 식으로 표현될 수 있는 것이기는 하지만, 중요한 점은 모듈 내부에 있는 “특정 함수”만 가져왔다는 것이다.&lt;/p&gt;
&lt;p&gt;앞서 이야기 했듯이 ESM은 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; 키워드를 통한 상세 의존 관계 파악이 쉬운 편이기 때문에 빌드 타임에 효율적으로 사용하는 코드와 사용하지 않는 코드를 발라내는 것이 가능하다.&lt;/p&gt;
&lt;p&gt;이렇게 트리쉐이킹이 쉽다는 강력한 이유 때문에 &lt;del&gt;Lodash를 제외한&lt;/del&gt; 유명한 라이브러리들은 대부분 ESM 방식을 공식적으로 지원하고 있다.&lt;/p&gt;
&lt;h2 id=&quot;moduleresolution&quot; style=&quot;position:relative;&quot;&gt;moduleResolution&lt;a href=&quot;#moduleresolution&quot; aria-label=&quot;moduleresolution permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Node&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Node 전략을 사용하여 모듈을 탐색한다. &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; 옵션이 CommonJS일 때 Default.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;Classic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Classic 전략을 사용하여 모듈을 탐색한다. &lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt; 옵션이 CommonJS가 아닐 때 Default.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;moduleResolution&lt;/code&gt; 옵션은 타입스크립트가 모듈을 불러올 때 이 모듈이 정확히 무엇을 참조하는 지를 확인하는 프로세스를 다루는 옵션이다. 이건 그냥 말로 설명하면 너무 어려우니 직접 코드를 보면서 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;우선 타입스크립트는 크게 상대 경로와 절대 경로, 2가지 방법을 사용하여 모듈의 경로를 정의하는 방법을 사용하고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 상대 경로&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; debounce &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 절대 경로&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;상대 경로의 경우에는 현재 위치를 나타내는 &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt;이나 상위 디렉토리를 나타내는 &lt;code class=&quot;language-text&quot;&gt;..&lt;/code&gt; 등의 식별자를 사용하여 탐색을 위한 기점을 지정함으로써 정확한 모듈의 위치를 나타낼 수 있는 반면, 절대 경로의 경우에는 단순히 모듈의 이름만 적고 있기 때문에 정확한 모듈의 위치를 찾기 위해서 특정한 규칙을 기반으로 모듈을 찾아나서는 여행을 떠나야 한다.&lt;/p&gt;
&lt;p&gt;또한 상대 경로, 절대 경로 두 방법 모두 모듈의 확장자까지는 적고 있지 않기 때문에, 이 모듈이 &lt;code class=&quot;language-text&quot;&gt;math.ts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;math.d.ts&lt;/code&gt; 등 어떤 확장자를 가지고 있는 파일인지도 알아내어야 한다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 타입스크립트는 모듈의 정확한 위치를 찾아내는 전략을 세워야 하는데, 이때 &lt;code class=&quot;language-text&quot;&gt;moduleResolution&lt;/code&gt; 옵션으로 Classic과 Node 중 어떤 전략을 사용할 것인지를 선택할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;사실 두 전략 모두 모듈의 위치를 찾는 기본적인 방법 자체는 크게 다르지 않다.&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;import { add } from &apos;./math&apos;&lt;/code&gt;와 같이 상대 경로를 사용한 모듈을 찾을 때는 찾아 볼 디렉토리가 명확하기 때문에 해당 디렉토리 내에서만 파일을 찾아보고, &lt;code class=&quot;language-text&quot;&gt;import { add } from &apos;math&apos;&lt;/code&gt;와 같이 절대 경로를 사용한 모듈을 찾을 때는 찾아야 할 디렉토리가 명확하지 않으니, 우선 해당 모듈을 불러온 파일이 위치한 디렉토리부터 뒤져보고, 없다면 한 단계 상위 디렉토리로, 그래도 없다면 또 한 단계 상위 디렉토리로 거슬러 올라가는 방식으로 모듈을 찾는다.&lt;/p&gt;
&lt;p&gt;이때 찾고자 하는 파일의 확장자가 무엇인지, 그리고 모듈을 찾을 때 어디를 먼저 찾아보는지에 따라서 Classic 전략과 Node 전략 간의 차이가 발생한다.&lt;/p&gt;
&lt;h3 id=&quot;classic&quot; style=&quot;position:relative;&quot;&gt;Classic&lt;a href=&quot;#classic&quot; aria-label=&quot;classic permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Classic&lt;/code&gt; 전략은 사실 상 타입스크립트의 기본 모듈 탐색 전략으로, 예전부터 사용하던 전략이기도 해서 하위 버전의 타입스크립트과의 호환성을 맞출 때에도 사용한다.&lt;/p&gt;
&lt;p&gt;Classic 전략은 상대 경로를 사용하여 불러온 모듈을 찾을 때, 해당 모듈을 불러오는 모듈의 위치를 기점으로 &lt;code class=&quot;language-text&quot;&gt;*.ts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt;의 순서로 탐색을 시작한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;앞서 이야기 했듯이 상대 경로를 사용한 경우에는 찾아봐야 하는 디렉토리의 위치가 명확하기 때문에 후보가 되는 확장자만 탐색을 진행한 후, 해당 모듈이 없는 경우 탐색을 종료하게 된다.&lt;/p&gt;
&lt;p&gt;반면 &lt;code class=&quot;language-text&quot;&gt;import { add } from &apos;math&apos;&lt;/code&gt;와 같이 절대 경로를 사용한 모듈의 경우에는 현재 모듈을 불러온 경로부터 시작해서 한 단계씩 부모 디렉토리로 거슬러 올라가면서 탐색을 진행하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;절대 경로를 사용한 경우, 가장 처음으로 모듈을 불러온 파일이 위치한 &lt;code class=&quot;language-text&quot;&gt;/root/src&lt;/code&gt;에서부터 탐색을 시작한다. 이후 이 디렉토리에서 모듈을 찾지 못 하면 한 단계 씩 거슬러 올라가며 다시 탐색을 진행하고, 루트까지 탐색했는데도 해당 모듈이 없는 경우 탐색을 종료하게 된다.&lt;/p&gt;
&lt;h3 id=&quot;node&quot; style=&quot;position:relative;&quot;&gt;Node&lt;a href=&quot;#node&quot; aria-label=&quot;node permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Node&lt;/code&gt; 전략은 이름 그대로 NodeJS가 모듈을 찾는 방식을 그대로 모방하는 전략이며, Node 전략은 Classic 전략과 다르게 &lt;code class=&quot;language-text&quot;&gt;*.ts&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; 확장자를 탐색하는 것을 넘어서서 조금 더 다양한 형태의 모듈까지 탐색을 한다.&lt;/p&gt;
&lt;p&gt;상대 경로를 사용한 경우는 Classic 전략과 비슷하게, 지정된 디렉토리 내부에서 다음과 같은 순서로 파일을 탐색하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/math/package.json&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 필드를 사용하는 경우에 한해)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;root/src/math/index.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;root/src/math/index.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;root/src/math/index.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;뭔가 많이 추가된 것 같지만, 기본적으로는 Classic 전략과 마찬가지로 지정된 디렉토리 내부의 파일을 찾되, &lt;code class=&quot;language-text&quot;&gt;*.tsx&lt;/code&gt; 확장자를 가진 모듈과 &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; 내부의 &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 속성, 그리고 모듈 이름과 동일한 디렉토리의 &lt;code class=&quot;language-text&quot;&gt;index.*&lt;/code&gt; 파일을 추가로 탐색할 뿐이다.&lt;/p&gt;
&lt;p&gt;이처럼 상대 경로를 사용한 모듈을 탐색할 때는 Node 전략과 Classic 전략 모두 비슷한 순서로 디렉토리 트리를 탐색하지만, 절대 경로로 지정된 모듈을 찾을 때는 차이가 커진다.&lt;/p&gt;
&lt;p&gt;왜냐하면 Node 전략은 Classic과 다르게, 절대 경로를 사용한 모듈을 찾을 때는 &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; 디렉토리를 탐색하기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /root/src/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/package.json&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 필드를 사용하는 경우에 한해)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/@types/math.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/index.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/index.tsx&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/src/node_modules/math/index.d.ts&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;/root/node_modules/math.ts&lt;/code&gt; (부모 디렉토리로 이동 후 반복)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Node 전략을 사용하게 되면 가장 먼저 &lt;code class=&quot;language-text&quot;&gt;math&lt;/code&gt; 모듈을 호출한 파일이 위치한 &lt;code class=&quot;language-text&quot;&gt;/root/src&lt;/code&gt; 디렉토리에 있는 &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; 디렉토리에서 탐색을 진행한다.&lt;/p&gt;
&lt;p&gt;이때 상대 경로에서와 동일하게 &lt;code class=&quot;language-text&quot;&gt;*.ts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*.tsx&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;*.d.ts&lt;/code&gt; 파일과 &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 필드를 찾아보며, 그 이후에는 &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; 디렉토리와 모듈 이름과 동일한 이름을 가진 디렉토리 밑에 있는 &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt; 파일을 탐색한다.&lt;/p&gt;
&lt;p&gt;이렇게 한 번의 탐색 과정이 끝나도 원하는 모듈을 찾지 못했다면, 부모 디렉토리로 이동한 후 이 과정을 다시 반복한다. 그 후 루트에 도달하여 로컬 머신에 전역 설치된 모듈이 있는지까지 탐색했는데도 해당 모듈이 없다면 탐색을 종료하게 된다.&lt;/p&gt;
&lt;p&gt;이러한 탐색 과정은 NodeJS가 모듈을 찾는 과정과 동일하지는 않지만, 매우 비슷하다. NodeJS는 먼저 모듈과 동일한 이름의 파일을 찾은 후, &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;main&lt;/code&gt; 필드에 적힌 경로의 파일을 찾아 보고, 마지막으로 모듈과 동일한 디렉토리 밑에 있는 &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt; 파일을 탐색하는데, 타입스크립트의 Node 전략이 바로 이 탐색 과정을 모방한 것이기 때문이다.&lt;/p&gt;
&lt;p&gt;타입스크립트 공홈에는 NodeJS가 사용하는 방식과 비교해서 크게 복잡하지 않으니 걱정말라고 하지만, 사실 애초에 NodeJS가 사용하고 있는 패키지 탐색 방식 자체가 비효율적이기는 하다. 그런 이유로 타입스크립트 4.0 버전부터는 불러오지 않은 모듈에 대해서는 더 이상 위와 같은 과정을 통해 타입 정보를 찾지 않도록 업데이트가 되었다.&lt;/p&gt;
&lt;h2 id=&quot;noresolve&quot; style=&quot;position:relative;&quot;&gt;noResolve&lt;a href=&quot;#noresolve&quot; aria-label=&quot;noresolve permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;어플리케이션에 포함된 모든 모듈을 해석한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;명시적으로 어플리케이션에 포함하기로한 모듈만 해석한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;기본적으로 타입스크립트 컴파일러는 어플리케이션에 포함된 모든 모듈을 컴파일하려고 시도한다. 즉, tsconfig 루트의 &lt;a href=&quot;/2021/07/30/tsconfig-options-root-fields/#include&quot;&gt;include&lt;/a&gt;나 &lt;a href=&quot;/2021/07/30/tsconfig-options-root-fields/#files&quot;&gt;files&lt;/a&gt; 필드에 포함하지 않은 파일이라고 해도, 어플리케이션 내에서 직접 &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; 문이나 &lt;code class=&quot;language-text&quot;&gt;/// &amp;lt;reference path=&quot;...&quot; /&gt;&lt;/code&gt; 같은 디렉티브를 사용하여 모듈을 불러왔다면, 그 모듈 또한 컴파일 대상이라는 것이다.&lt;/p&gt;
&lt;p&gt;어찌보면 암시적으로 모듈을 컴파일 대상에 포함시킨다는 이야기인데, 이때 &lt;code class=&quot;language-text&quot;&gt;noResolve&lt;/code&gt; 옵션을 &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;로 설정하면 이런 암시적인 모듈 컴파일을 막을 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/index.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;noResolve&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/index.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; add2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 예시의 &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; 필드에는 &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt;만 포함되어 있고, &lt;code class=&quot;language-text&quot;&gt;utils/math&lt;/code&gt; 모듈은 포함되어있지 않다.&lt;/p&gt;
&lt;p&gt;이런 경우일 때 &lt;code class=&quot;language-text&quot;&gt;noResolve&lt;/code&gt; 옵션의 값이 &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;라면 &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt;에서 사용하는 &lt;code class=&quot;language-text&quot;&gt;utils/math&lt;/code&gt; 모듈도 아무 문제 없이 컴파일되지만, &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;인 경우에는 해당 모듈을 찾을 수 없다는 에러가 발생하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;src/index.ts:1:21 - error TS2307: Cannot find module &apos;./utils/math&apos; or its corresponding type declarations.

1 import { add } from &apos;./utils/math&apos;;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, 반드시 명시적으로 &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;files&lt;/code&gt; 필드에 선언된 모듈들만 컴파일을 하고 있는 것이다. 이와 마찬가지 이유로 &lt;code class=&quot;language-text&quot;&gt;/// &amp;lt;reference path=&quot;...&quot; /&gt;&lt;/code&gt; 같이 디렉티브를 사용하여 불러온 모듈들도 해당 필드에 포함되어 있지 않기 때문에 컴파일 대상에서 제외된다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;noResolve&lt;/code&gt; 옵션은 개발자가 타입스크립트의 컴파일 대상을 명시적으로 선언하게 만듦으로써 수월한 모듈 관리를 도와주기는 하지만, 디렉티브를 사용하여 불러온 모듈까지 컴파일 대상에서 제외한다는 특성 때문에 디렉티브를 사용하여 타입 정의 파일을 불러오는 NextJS 같은 라이브러리를 사용하고 있는 상황에서는 그냥 기본 값인 &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;로 사용하는 것이 정신 건강에 이롭다.&lt;/p&gt;
&lt;h2 id=&quot;resolvejsonmodule&quot; style=&quot;position:relative;&quot;&gt;resolveJsonModule&lt;a href=&quot;#resolvejsonmodule&quot; aria-label=&quot;resolvejsonmodule permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;*.json&lt;/code&gt; 확장자로 끝나는 모듈의 import를 허용하지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;*.json&lt;/code&gt; 확장자로 끝나는 모듈의 import를 허용한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;resolveJsonModule&lt;/code&gt; 옵션은 이름 그대로 JSON 파일로 구현된 모듈을 끌어다 쓸 수 있게 허용할 것인지에 대한 여부를 결정한다.&lt;/p&gt;
&lt;p&gt;만약 해당 옵션이 &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;라면, JSON 모듈을 가져왔을 때 타입스크립트는 해당 모듈을 찾을 수 없다는 에러를 발생시킨다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// me.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;evan-moon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Frontend Engineer&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; me &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./me.json&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Cannot find module &apos;./settings.json&apos;. Consider using &apos;--resolveJsonModule&apos; to import module with &apos;.json&apos; extension.&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;resolveJsonModule&lt;/code&gt; 옵션을 켜게 되면 일반적인 타입스크립트 모듈과 동일하게 JSON 모듈을 가져와서 사용할 수 있게 되고, 심지어 해당 파일을 분석하여 자동으로 타입 추론까지 해준다.&lt;/p&gt;
&lt;p&gt;하지만 이 경우 당연히 Enum이나 Union Type을 사용한 추론은 불가능하기 때문에 모든 값들은 &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;이나 &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; 등의 원시 타입으로 추론된다. 그러니 만약 강력한 타입 선언을 강제해야하는 경우라면 JSON 모듈이 아니라 타입스크립트 모듈을 사용하여 모델을 선언해주는 것이 좋다.&lt;/p&gt;
&lt;h2 id=&quot;rootdir&quot; style=&quot;position:relative;&quot;&gt;rootDir&lt;a href=&quot;#rootdir&quot; aria-label=&quot;rootdir permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션은 모듈을 컴파일 한 이후 어떤 디렉토리를 루트로 하여 현재 구조를 유지할 것 인지를 결정한다.&lt;/p&gt;
&lt;p&gt;기본적으로 타입스크립트는 컴파일을 수행할 때 입력된 디렉토리의 구조를 그대로 유지하며 컴파일된 파일들을 출력하는데, 이때 &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션을 사용하여 어떤 디렉토리를 루트로 설정할 것인지를 정하는 것이다.&lt;/p&gt;
&lt;p&gt;만약 이 옵션을 따로 설정하지 않는다면, 타입스크립트는 자동으로 해당 모듈의 엔트리 포인트가 되는 파일을 찾고, 해당 파일이 위치한 디렉토리를 루트로 설정하여 출력 디렉토리 구조를 설정하게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── src
│   ├── index.ts
│   └── utils
│       └── math.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같은 구조의 프로젝트가 있다고 생각해보자. &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션이 주어지지 않았을 때의 타입스크립트는 이 어플리케이션의 엔트리 포인트인 &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt;를 찾아내고, 이 파일의 위치인 &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt;를 루트로 인식하게 된다.&lt;/p&gt;
&lt;p&gt;그렇기 때문에 출력 디렉토리는 루트를 &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; 디렉토리로 하는 다음과 같은 구조를 가지게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;dist
├── index.ts
└── utils
    └── math.ts&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그러나 만약 이 상태에서 &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션을 현재 경로를 의미하는 &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt;로 설정하게 되면, 출력 디렉토리의 구조가 변경되게 된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tsconfig.json&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;dist
└── src
    ├── index.ts
    └── utils
        └── math.ts&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;필자가 루트 디렉토리를 현재 &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;이 위치한 &lt;code class=&quot;language-text&quot;&gt;myProject&lt;/code&gt; 디렉토리로 변경했기 때문에, 출력 디렉토리인 &lt;code class=&quot;language-text&quot;&gt;dist&lt;/code&gt;는 기존 프로젝트 디렉토리와 완전히 동일한 구조를 가지게 되고, 이로 인해 디렉토리 내부에 &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; 디렉토리까지 함께 생성된 형태로 출력되게 된다.&lt;/p&gt;
&lt;p&gt;어찌보면 굉장히 간단한 동작이지만, 이 옵션을 사용할 때는 한 가지 주의해야 할 점이 있다. 바로 &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션은 컴파일 대상에 아무런 영향을 끼치지 않는다는 것이다.&lt;/p&gt;
&lt;p&gt;즉, 만약 &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션을 사용한다면 모든 컴파일 대상 파일은 해당 디렉토리 밑에 위치해야 한다는 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── src
│   ├── index.ts
│   └── utils
│       └── math.ts
├── foo.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 설정을 살펴보면 루트 디렉토리로 &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; 디렉토리를 설정하고, &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; 옵션을 사용하여 모든 파일을 컴파일 할 것이라고 설정해주었다.&lt;/p&gt;
&lt;p&gt;문제는 이 “모든 파일”의 대상 중 하나인 &lt;code class=&quot;language-text&quot;&gt;foo.ts&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; 디렉토리에 들어가 있지 않은 녀석이라는 것이다. 즉, 설정에 모순이 발생한 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션으로 루트 디렉토리를 정했다고 해도, 타입스크립트는 자동으로 &lt;code class=&quot;language-text&quot;&gt;foo.ts&lt;/code&gt;를 컴파일 대상에 포함시키지 않고, 이런 에러를 발생시킨다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;File ‘/Users/john/myProject/foo.ts’ is not under ‘rootDir’ ‘/Users/john/myProejct/src’. &lt;strong&gt;‘rootDir’ is expected to contain all source files.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 에러를 보면 알 수 있듯이, &lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt; 옵션을 사용하여 루트 디렉토리를 설정했다면 반드시 모든 소스 파일들은 루트 디렉토리 내부에 들어있어야 하며, 만약 &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; 등을 사용하여 루트 디렉토리 밖에 있는 파일을 컴파일 대상으로 지정했다고 해도 자동으로 컴파일 해주거나 하지 않는다.&lt;/p&gt;
&lt;h2 id=&quot;rootdirs&quot; style=&quot;position:relative;&quot;&gt;rootDirs&lt;a href=&quot;#rootdirs&quot; aria-label=&quot;rootdirs permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; 옵션은 일종의 가상 루트를 만들어 줄 수 있는 옵션이다. 이 옵션은 말로 설명하기 보다 코드로 보는 것이 훨씬 이해가 편하니, 바로 예시를 보도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;myProject
├── core
│   └── index.ts
├── utils
│   └── math.ts
└── tsconfig.json&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 이런 구조의 어플리케이션이 있다고 생각해보자. 만약 &lt;code class=&quot;language-text&quot;&gt;core/index.ts&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;utils/math.ts&lt;/code&gt; 모듈을 가져오고 싶다면 어떻게 해야할까?&lt;/p&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt; 옵션을 사용하지 않았다면, 상대 경로를 사용하여 한 단계 상위 디렉토리로 거슬러 올라가서 해당 모듈에 접근할 것이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// core/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; math &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; 옵션은 이런 상황일 때 가상의 루트를 만들어서, &lt;code class=&quot;language-text&quot;&gt;core&lt;/code&gt; 디렉토리와 &lt;code class=&quot;language-text&quot;&gt;utils&lt;/code&gt; 디렉토리 내부에 있는 모듈들이 마치 “하나의 디렉토리” 내부에 있는 것처럼 사용할 수 있도록 만들어준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDirs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;utils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// core/index.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; math &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./utils/math&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 마치 같은 디렉토리에 있는 것처럼 사용한다&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만약 &lt;code class=&quot;language-text&quot;&gt;core/components/Foo/index.tsx&lt;/code&gt;와 같이 디렉토리 깊이가 깊다고 해도 &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt;에 해당 디렉토리를 등록하게 되면, &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt;에 등록된 디렉토리 끼리는 항상 같은 디렉토리에 있는 것처럼 모듈을 불러올 수 있다.&lt;/p&gt;
&lt;p&gt;그리고 &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; 옵션은 일종의 “가상 디렉토리”를 만들어서 이런 기능을 구현하는 방식을 사용하기 때문에, 컴파일한 이후의 출력 디렉토리 구조에는 전혀 영향을 주지 않는다. 말 그대로 가상이다.&lt;/p&gt;
&lt;p&gt;이처럼 &lt;code class=&quot;language-text&quot;&gt;rootDirs&lt;/code&gt; 옵션은 디렉토리의 깊이가 깊은 상황에도 간단하게 상대 경로를 사용할 수 있도록 만들어 주기 때문에 어찌 보면 편하다고 생각할 수도 있다.&lt;/p&gt;
&lt;p&gt;하지만 이런 설정을 사용하게 되면 실제 디렉토리 구조와 코드에서 모듈에 접근하기 위해 사용하는 경로 간의 괴리가 발생하게 됨으로써 직관적인 이해가 어려운 코드가 될 수도 있으며, 심지어 이 괴리의 원인을 확인하기 위해서는 &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;을 까봐야 하는 슬픈 상황이 발생할 수도 있다는 점을 꼭 염두에 두도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;typeroots&quot; style=&quot;position:relative;&quot;&gt;typeRoots&lt;a href=&quot;#typeroots&quot; aria-label=&quot;typeroots permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;기본적으로 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; 패키지 디렉토리 밑에 있는 파일들을 자동으로 컴파일 대상으로 포함한다. 이때 앞서 설명했던 &lt;code class=&quot;language-text&quot;&gt;resolve&lt;/code&gt; 전략에 따라 &lt;code class=&quot;language-text&quot;&gt;./node_modules/@types&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;../node_modules/@types&lt;/code&gt; 등 디렉토리를 거슬러 올라가면서 &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; 내부에 있는 &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; 디렉토리를 탐색하는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;code class=&quot;language-text&quot;&gt;typeRoots&lt;/code&gt; 옵션을 사용하면 타입스크립트가 찾아 헤매는 타입 파일들이 특정한 곳에 있다고 지정할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typeRoots&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./typings&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./node_modules/@types&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;typeRoots&lt;/code&gt; 옵션에 적용하는 경로는 &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; 기준의 상대 경로이다. 또한 위 예시에서는 &lt;code class=&quot;language-text&quot;&gt;./node_modules/@types&lt;/code&gt; 디렉토리를 옵션에 포함시켰지만, 사실 없어도 아무 문제 없다.&lt;/p&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;typeRoots&lt;/code&gt;를 지정한 경우, 타입스크립트는 기존의 모듈 탐색 전략을 버리고 배열에 들어있는 경로에서만 타입 선언 모듈들을 찾기 때문에, 계속 부모 디렉토리로 거슬러 올라가며 타입 선언 모듈을 찾는 기존의 모듈 탐색 전략보다 효율적인 탐색 전략을 가져갈 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;types&quot; style=&quot;position:relative;&quot;&gt;types&lt;a href=&quot;#types&quot; aria-label=&quot;types permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;앞서 설명했듯이 타입스크립트는 &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; 패키지 디렉토리 밑에 있는 모든 파일들을 자동으로 컴파일 대상으로 포함하고, 이 과정에서 타입 선언을 전역 스코프에 뿌려버린다.&lt;/p&gt;
&lt;p&gt;이 타입 선언이 전역 스코프에 존재하기 때문에 우리가 &lt;code class=&quot;language-text&quot;&gt;@types/node&lt;/code&gt; 같은 모듈 내부에 포함된 &lt;code class=&quot;language-text&quot;&gt;process&lt;/code&gt; 객체 같은 녀석들을 별도의 타입 선언 없이도 사용할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 옵션을 사용하면, 특정한 패키지들의 타입만 전역 스코프에 포함시킬 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// @types/node, @types/jest, @types/express만 가져온다&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jest&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;express&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같이 설정할 경우, &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;jest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;express&lt;/code&gt; 패키지의 타입은 전역 스코프에 포함되어 &lt;code class=&quot;language-text&quot;&gt;import express from &apos;express&apos;;&lt;/code&gt;라는 구문만 적어도 자동으로 타입 평가가 진행되지만, 여기에 포함되지 않은 다른 라이브러리들은 직접 타입 선언 모듈을 가져와야 한다.&lt;/p&gt;
&lt;p&gt;여기서 주의해야할 점은 &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 옵션의 대상 자체가 애초에 &lt;code class=&quot;language-text&quot;&gt;@types&lt;/code&gt; 패키지 디렉토리 내부에 존재하는 타입 선언 모듈들이라는 것이다.&lt;/p&gt;
&lt;p&gt;예를 들어 날짜 관련 라이브러리인 &lt;code class=&quot;language-text&quot;&gt;moment&lt;/code&gt;는 &lt;code class=&quot;language-text&quot;&gt;@types/moment&lt;/code&gt; 같은 타입 패키지를 추가적으로 설치하지 않고, 자체적으로 내장하고 있는 타입 선언 모듈을 사용한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;moment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./moment.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;jsnext:main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist/moment.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./moment.d.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 자체적으로 타입 선언 파일을 포함하고 있다&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 경우는 &lt;code class=&quot;language-text&quot;&gt;import moment from &apos;moment&apos;&lt;/code&gt; 구문으로 이 라이브러리를 가져옴과 동시에 &lt;code class=&quot;language-text&quot;&gt;moment.d.ts&lt;/code&gt;도 자동으로 컴파일 대상으로 포함되므로, 당연히 제대로 타입을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;즉, &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt; 옵션의 대상은 어디까지나 &lt;code class=&quot;language-text&quot;&gt;@types/*&lt;/code&gt; 패키지 내부에 포함된 타입 선언 모듈이고, 타입스크립트가 해당 타입 선언 모듈을 전역 공간에 뿌리는 경우에만 해당된다는 점을 헷갈리지 말자.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;마치며&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;이렇게 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; 3번째 시리즈인 &lt;code class=&quot;language-text&quot;&gt;Modules&lt;/code&gt; 편을 마무리 했다. 모듈과 관련된 옵션들의 개수 자체는 많지 않지만, 아무래도 컴파일 과정에서 어떤 모듈 시스템을 사용할 지, 어떤 모듈 탐색 전략을 사용할 지 등을 다루는 옵션이다보니 부연 설명이 길어진 것 같다.&lt;/p&gt;
&lt;p&gt;그리고 여기까지 적고 나서 새삼스럽게 드는 생각은…&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2f03c5fd1831cbdc146edbf1130bd061/00d43/tsconfig.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 94.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAAC1UlEQVR42oVTZ1PbQBTU//8vhJrQMcaUDKGXTBKKcbflpi5Zstnsni1iEmbyYefda/v2nk5WEIXo9HuwB320e10EoxhjABlekb5O3tkc8j/EOIMVPj/BvblG+vhgkPz8geD7Pfy7WwT3d/9Y7/YGIfOqzebx8AtprQorPj9DvLmBeHcHCZEV95HuFz6EyRX2kNJmf2NvF+nFOSzv9BT9tVUMtzYRqvjoEEnpwCA+KGJ0WMKoVJr6xSJS+gnj8rPjoz9gPOVNreDsGwKSqWjy9QTR/h5aS0toL09hryyjM4O9sgJ7dYX5RWMDqvJ5K9mRVF5fwUquLzGhKk0ZExFVNhYW0Fz8ZBpFZOzylFTxNn0NU6z3eQ1d3tBZ/4KI4qz46hLZnPwRz5rq7WwbGxYK8GdKTHymKOBgd3sLDuGqljYyOzw5hk92Q6rdsHDIqQPtldbb2IDLvLe5zvO6UTJg3OXZ195JFnFATMLs8oKEzQaSVhOp3TGI6Q/4lIblZzgvZbiVl3foPz0a65TLJh+xPqjXEBIZ37Ll+R6SdIQ0S5FNxvDDAFW+p0argVqjblBlcYXQuVKvokxCod6c1lRYL/iBz4/CP2VCsjFJs1GCgAOaLBLsThv9ro0h/ySH03u8wYB/k9BlTnG73TK5iGTislxniAETQwZTEsYM6uwMB/A9FyELVSN4rmP8sW4jAXNQr2CpSM2yCiRxZFTOQzlZkWmg6kZJ/A5vhCKzeRU1aFLEHUqhVOfKVKNB883/VZhfWYStZhNtfvkO9yObQ369VjO7zVehXlkNNITak0gFkSlhlM0G5evId5j7Dn2JEJTTAKm38sY+v5ysSKWgx6/b5So6PA/600b5dqdj1pHndQ58n33hlFCBuh4mJ7zyHcqKUMV5Q5fN5glxqIhyZVqBrG6lj2UIpUpFUqblBiSsVSvcVdW8xRYfb6/bfXtGOfLnJpvHRPwbAA92vl9EkpcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;tsconfig&quot; title=&quot;&quot; src=&quot;/static/2f03c5fd1831cbdc146edbf1130bd061/6af66/tsconfig.png&quot; srcset=&quot;/static/2f03c5fd1831cbdc146edbf1130bd061/69538/tsconfig.png 160w,
/static/2f03c5fd1831cbdc146edbf1130bd061/72799/tsconfig.png 320w,
/static/2f03c5fd1831cbdc146edbf1130bd061/6af66/tsconfig.png 640w,
/static/2f03c5fd1831cbdc146edbf1130bd061/d9199/tsconfig.png 960w,
/static/2f03c5fd1831cbdc146edbf1130bd061/00d43/tsconfig.png 1000w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;어...? 아직도 여기까지밖에 못 썼다고...?&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;사실 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt; 옵션이 많은 줄은 이미 알고 있었지만 이렇게까지 힘들 줄은 상상도 못 했다. &lt;small&gt;&lt;del&gt;(글 쓰다가 손목이 아픈 적은 또 처음…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;물론 공식 문서를 번역하는 느낌으로 쭉쭉 써내려간다면 금방 끝내겠지만, 애초에 이 포스팅 시리즈를 시작한 것은 그 정도의 정보를 원해서가 아니라 &lt;code class=&quot;language-text&quot;&gt;tsconfig&lt;/code&gt;를 완전 분석해보자는 목적이었으므로 한번 달려보도록 하겠다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/2021/10/30/tsconfig-compiler-options-modules-emit/&quot;&gt;다음 포스팅&lt;/a&gt;에서는 타입스크립트가 출력 파일을 생성할 때의 동작들을 다루는 방법에 대한 옵션들에 대해서 이야기해볼 예정이다.&lt;/p&gt;
&lt;p&gt;이상으로 [tsconfig의 모든 것] Compiler options / Modules 포스팅을 마친다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Everything About tsconfig] Compiler Options / Type Checking]]></title><description><![CDATA[This post covers the type checking options in tsconfig’s compiler settings. Most developers use TypeScript for the stability that comes from its powerful type system — something JavaScript doesn’t provide. Among TypeScript’s countless compiler options, type checking options manage the language’s core functionality.]]></description><link>https://evan-moon.github.io/2021/08/08/tsconfig-compiler-options-type-check/en/</link><guid isPermaLink="false">20210808-tsconfig-compiler-options-type-check-en</guid><pubDate>Sun, 08 Aug 2021 09:58:49 GMT</pubDate><content:encoded>&lt;p&gt;This post covers the type checking options in tsconfig’s compiler settings.&lt;/p&gt;
&lt;p&gt;Most developers use TypeScript for the stability that comes from its powerful type system — something JavaScript doesn’t provide. Among TypeScript’s countless compiler options, type checking options manage the language’s core functionality.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;TypeScript offers a wide variety of options, from simple ones that feel like “this code is forbidden” to ones whose behavior you can only understand if you know how the type system actually works.&lt;/p&gt;
&lt;p&gt;Most type checking compiler options strengthen TypeScript’s type safety, which is why the TypeScript team recommends enabling all of them when possible.&lt;/p&gt;
&lt;p&gt;But stronger type safety means the flip side: things that could previously slide by with &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; will no longer be allowed.&lt;/p&gt;
&lt;p&gt;If you’re gradually adopting TypeScript in an application, you could burn a lot of time just fixing type errors. Consider your organization’s business situation before enabling options.&lt;/p&gt;
&lt;p&gt;Let’s dive into how TypeScript’s type checking compiler options actually affect your code.&lt;/p&gt;
&lt;h2 id=&quot;unreachable-unused&quot; style=&quot;position:relative;&quot;&gt;Unreachable, Unused&lt;a href=&quot;#unreachable-unused&quot; aria-label=&quot;unreachable unused permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Options starting with &lt;code class=&quot;language-text&quot;&gt;Unreachable, Unused&lt;/code&gt; control how to manage unused code or code that can never execute.&lt;/p&gt;
&lt;h3 id=&quot;allowunreachablecode&quot; style=&quot;position:relative;&quot;&gt;allowUnreachableCode&lt;a href=&quot;#allowunreachablecode&quot; aria-label=&quot;allowunreachablecode permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Warn when encountering unreachable code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ignore unreachable code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error when encountering unreachable code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;allowUnreachableCode&lt;/code&gt; option controls how the compiler reacts when it encounters unreachable code. Unreachable code is code that can never execute.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Unreachable code detected.ts(7027)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt; function unconditionally returns a value and exits in either branch of the &lt;code class=&quot;language-text&quot;&gt;if-else&lt;/code&gt;, so the final &lt;code class=&quot;language-text&quot;&gt;return true&lt;/code&gt; can never execute. This is unreachable code.&lt;/p&gt;
&lt;p&gt;Even with default settings, this option warns about such code rather than ignoring it, providing some protection against unreachable code.&lt;/p&gt;
&lt;p&gt;Still, meaningless statements left in source code can cause developers to misunderstand the application’s flow. And since this dead code doesn’t affect the application anyway, I recommend enabling this option to error at compile time. &lt;small&gt;&lt;del&gt;(Though sometimes deleting such code mysteriously causes bugs…)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h3 id=&quot;allowunusedlabels&quot; style=&quot;position:relative;&quot;&gt;allowUnusedLabels&lt;a href=&quot;#allowunusedlabels&quot; aria-label=&quot;allowunusedlabels permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Warn when encountering unused labels.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ignore unused labels.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error when encountering unused labels.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;allowUnusedLabels&lt;/code&gt; option controls how the compiler reacts when it encounters unused labels in code.&lt;/p&gt;
&lt;p&gt;If you haven’t been programming long, “labels” might be unfamiliar. This feature isn’t TypeScript-specific — other languages have it too.&lt;/p&gt;
&lt;p&gt;I used labels when learning C in school six years ago, but haven’t used them since.&lt;/p&gt;
&lt;p&gt;Labels target specific statements, letting you name &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statements, &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops, etc. You can then access those statements by name to control them with commands like &lt;code class=&quot;language-text&quot;&gt;break&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;continue&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; j&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

outerLoop&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  innerLoop&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Unused Label&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;j &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// If both i and j are 1, skip the outer loop&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt; outerLoop&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;i=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;i&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, j=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;j&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Loop &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; done&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-text line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;i=0, j=0
i=0, j=1
i=0, j=2
Loop 1 done
i=1, j=0
i=2, j=0
i=2, j=1
i=2, j=2
Loop 3 done&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, when both &lt;code class=&quot;language-text&quot;&gt;i&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;j&lt;/code&gt; equal &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; in the inner &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop, it skips the outer &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop. Looking at the output, after &lt;code class=&quot;language-text&quot;&gt;i=1, j=0&lt;/code&gt; prints, “Loop n done” doesn’t print and the third iteration starts immediately.&lt;/p&gt;
&lt;p&gt;The outer loop’s label &lt;code class=&quot;language-text&quot;&gt;outerLoop&lt;/code&gt; is used in the inner loop, but the inner loop’s label &lt;code class=&quot;language-text&quot;&gt;innerLoop&lt;/code&gt; is never used. This is an Unused Label, and the &lt;code class=&quot;language-text&quot;&gt;allowUnusedLabels&lt;/code&gt; option controls how TypeScript reacts to unused labels.&lt;/p&gt;
&lt;p&gt;But labels often reverse the normal top-to-bottom program flow, and they don’t have clear scopes or separated concerns like functions, making code hard to read. &lt;small&gt;(Labels + goto from the assembly era are considered anti-patterns even in C.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Don’t worry about whether to enable this option — just don’t use labels at all.&lt;/p&gt;
&lt;h3 id=&quot;nounusedlocals&quot; style=&quot;position:relative;&quot;&gt;noUnusedLocals&lt;a href=&quot;#nounusedlocals&quot; aria-label=&quot;nounusedlocals permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error if unused local variables exist.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Ignore unused local variables.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noUnusedLocals&lt;/code&gt; option controls how to handle unused local variables inside functions. When this option is &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;, the compiler errors on unused local variables.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// &apos;bar&apos; is declared but its value is never read.ts(6133)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;True to its name, &lt;code class=&quot;language-text&quot;&gt;noUnusedLocals&lt;/code&gt; doesn’t error or warn about unused variables in global or module scopes, only function scopes. Keep this in mind.&lt;/p&gt;
&lt;h3 id=&quot;nounusedparameters&quot; style=&quot;position:relative;&quot;&gt;noUnusedParameters&lt;a href=&quot;#nounusedparameters&quot; aria-label=&quot;nounusedparameters permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error if unused parameters exist.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Ignore unused parameters.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noUnusedParameters&lt;/code&gt; option controls how to handle unused function parameters. When this option is &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;, the compiler errors on unused parameters.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// &apos;name&apos; is declared but its value is never read.ts(6133)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;prohibiting-implicit-declarations&quot; style=&quot;position:relative;&quot;&gt;Prohibiting Implicit Declarations&lt;a href=&quot;#prohibiting-implicit-declarations&quot; aria-label=&quot;prohibiting implicit declarations permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Many TypeScript type checking compiler options start with &lt;code class=&quot;language-text&quot;&gt;noImplicit&lt;/code&gt;, which means prohibiting “implicit something.”&lt;/p&gt;
&lt;p&gt;Implicit means silently performing something without providing any information, increasing the chance of problems occurring where developers don’t expect them.&lt;/p&gt;
&lt;p&gt;Enable all &lt;code class=&quot;language-text&quot;&gt;noImplicit&lt;/code&gt; options to prevent TypeScript from silently evaluating things behind your back at compile time.&lt;/p&gt;
&lt;h3 id=&quot;noimplicitany&quot; style=&quot;position:relative;&quot;&gt;noImplicitAny&lt;a href=&quot;#noimplicitany&quot; aria-label=&quot;noimplicitany permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prohibit implicitly using the &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; type for values that can’t be inferred and have no type declaration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Allow implicitly using the &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; type for values that can’t be inferred and have no type declaration.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;TypeScript evaluates values without explicit type declarations that can’t be inferred as &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;. The &lt;code class=&quot;language-text&quot;&gt;noImplicitAny&lt;/code&gt; option controls whether to error when such &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;-typed values exist.&lt;/p&gt;
&lt;p&gt;TypeScript warns about &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; types even without this option enabled, since they harm type safety.&lt;/p&gt;
&lt;p&gt;But warnings can be ignored at compile time, so using &lt;code class=&quot;language-text&quot;&gt;noImplicitAny&lt;/code&gt; to error and block compilation is much safer.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Parameter &apos;s&apos; implicitly has an &apos;any&apos; type.ts(7006)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;noimplicitoverride&quot; style=&quot;position:relative;&quot;&gt;noImplicitOverride&lt;a href=&quot;#noimplicitoverride&quot; aria-label=&quot;noimplicitoverride permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prohibit implicit overriding in subclasses.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Allow implicit overriding in subclasses.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noImplicitOverride&lt;/code&gt; option controls whether subclasses can implicitly override superclass member variables or methods.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Album&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;upload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SharedAlbum&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Album&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// This member must have an &apos;override&apos; modifier because it overrides a member in the base class &apos;Album&apos;.ts(4114)&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Explicit overriding with override keyword is allowed&lt;/span&gt;
  override &lt;span class=&quot;token function&quot;&gt;upload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the compiler doesn’t warn or error on implicit overriding, developers might unknowingly override superclass functionality. &lt;small&gt;(&lt;del&gt;You don’t memorize all superclass member names&lt;/del&gt;)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This could unintentionally break superclass functionality and cause unexpected errors, so I recommend enabling &lt;code class=&quot;language-text&quot;&gt;noImplicitOverride&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;noimplicitreturns&quot; style=&quot;position:relative;&quot;&gt;noImplicitReturns&lt;a href=&quot;#noimplicitreturns&quot; aria-label=&quot;noimplicitreturns permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prohibit functions implicitly returning &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Allow functions implicitly returning &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noImplicitReturns&lt;/code&gt; option controls how to handle functions that implicitly return &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Not all code paths return a value.ts(7030)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt; function returns &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; when its argument is &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; but returns nothing otherwise, so TypeScript infers it returns a &lt;code class=&quot;language-text&quot;&gt;boolean&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;But actually, calling &lt;code class=&quot;language-text&quot;&gt;foo(2)&lt;/code&gt; with an argument that doesn’t match the condition returns nothing explicitly and exits the function, implicitly returning &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. Try declaring any function in the browser dev tools to verify this.&lt;/p&gt;
&lt;p&gt;The problem: TypeScript inferred the return type as &lt;code class=&quot;language-text&quot;&gt;boolean&lt;/code&gt;, but the actual implicit return type &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; is included, making the final return type &lt;code class=&quot;language-text&quot;&gt;boolean | undefined&lt;/code&gt;. This contradiction creates opportunities for unexpected runtime errors.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noImplicitReturns&lt;/code&gt; option warns that the function isn’t properly returning values when it implicitly returns &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. With this option enabled, the &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt; function must explicitly return &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;noimplicitthis&quot; style=&quot;position:relative;&quot;&gt;noImplicitThis&lt;a href=&quot;#noimplicitthis&quot; aria-label=&quot;noimplicitthis permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prohibit cases where &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; is implicitly evaluated as &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Allow cases where &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; is implicitly evaluated as &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noImplicitThis&lt;/code&gt; option prohibits cases where &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; is implicitly evaluated as &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;. To understand this option’s behavior, you need to understand how JavaScript and TypeScript’s &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; works, but since this post isn’t about &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;, I’ll explain briefly. For deeper knowledge about &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;, check out this &lt;a href=&quot;https://poiemaweb.com/js-this&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;JavaScript’s &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; binds dynamically. What &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; points to depends on how the function is called.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Human&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sayThis&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; evan &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Human&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sayThis &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; evan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sayThis&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

evan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sayThis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Human {}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sayThis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// globalThis&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As shown, the same &lt;code class=&quot;language-text&quot;&gt;Human&lt;/code&gt; class method’s &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; changes dynamically based on how it’s called. JavaScript’s &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; is so unpredictable that we need methods like &lt;code class=&quot;language-text&quot;&gt;call&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;bind&lt;/code&gt; to explicitly set &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;, or ES6 arrow functions that don’t bind &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; at all.&lt;/p&gt;
&lt;p&gt;This dynamic binding causes situations where TypeScript can’t infer &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;’s type. A common example: accessing &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; in inner functions.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Human&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sayThis&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// &apos;this&apos; implicitly has type &apos;any&apos; because it does not have a type annotation.ts(2683)&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;say&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; evan &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Human&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
evan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sayThis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// globalThis&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, the &lt;code class=&quot;language-text&quot;&gt;sayThis&lt;/code&gt; method declares and calls a &lt;code class=&quot;language-text&quot;&gt;say&lt;/code&gt; function internally, and the inner function accesses &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;. Logically, this function’s &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; should be the &lt;code class=&quot;language-text&quot;&gt;Human&lt;/code&gt; class, but reality is cruel — &lt;code class=&quot;language-text&quot;&gt;globalThis&lt;/code&gt; pops out. &lt;small&gt;(Use arrow functions in these cases…)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This is when TypeScript can’t infer &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;. TypeScript implicitly binds &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; in the &lt;code class=&quot;language-text&quot;&gt;say&lt;/code&gt; function to &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;, breaking type safety.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;noImplicitThis&lt;/code&gt; option controls whether to tolerate situations where the &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; type is implicitly evaluated as &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;. Since there’s almost no use case for leveraging the global object binding to &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; in functions declared inside methods, I recommend enabling this option.&lt;/p&gt;
&lt;h2 id=&quot;strict&quot; style=&quot;position:relative;&quot;&gt;Strict&lt;a href=&quot;#strict&quot; aria-label=&quot;strict permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Strict&lt;/code&gt; options manage how strictly TypeScript evaluates types in normal situations.&lt;/p&gt;
&lt;p&gt;The TypeScript team calls these the Strict mode family, ranging from options that check for violations of JavaScript’s &lt;code class=&quot;language-text&quot;&gt;&apos;use strict&apos;&lt;/code&gt; directive to options that check covariance and contravariance, providing various ways to make TypeScript evaluate types more strictly.&lt;/p&gt;
&lt;h3 id=&quot;alwaysstrict&quot; style=&quot;position:relative;&quot;&gt;alwaysStrict&lt;a href=&quot;#alwaysstrict&quot; aria-label=&quot;alwaysstrict permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error when source code violates Strict rules.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Ignore Strict rule violations in source code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;alwaysStrict&lt;/code&gt; option errors when developers violate JavaScript’s Strict rules while using TypeScript. Setting this option to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; makes TypeScript parse each source file as if a &lt;code class=&quot;language-text&quot;&gt;use strict&lt;/code&gt; directive were declared at the top.&lt;/p&gt;
&lt;p&gt;Note that most TypeScript Strict mode options are for “non-module code.” TypeScript always compiles all module code in Strict mode according to ECMAScript 2015’s &lt;a href=&quot;https://262.ecma-international.org/6.0/#sec-strict-mode-code&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Strict Mode Code&lt;/a&gt; section definition.&lt;/p&gt;
&lt;p&gt;One thing to know: this option outputs the &lt;code class=&quot;language-text&quot;&gt;use strict&lt;/code&gt; directive to “source files,” not to the compiled output. Let’s look at an example.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.ts&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Octal literals are not allowed in strict mode.ts(1121)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; number &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The IDE shows the error &lt;code class=&quot;language-text&quot;&gt;Octal literals are not allowed in strict mode.ts(1121)&lt;/code&gt;, but compilation doesn’t error, and the compiled output doesn’t include the &lt;code class=&quot;language-text&quot;&gt;use strict&lt;/code&gt; directive. Source code parsing recognizes the error, but Strict mode isn’t guaranteed in compilation results.&lt;/p&gt;
&lt;p&gt;However, when using modules, TypeScript applies Strict mode to both source code parsing and compilation output, regardless of this option.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-js line-numbers&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.js (common.js)&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__esModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;strictbindcallapply&quot; style=&quot;position:relative;&quot;&gt;strictBindCallApply&lt;a href=&quot;#strictbindcallapply&quot; aria-label=&quot;strictbindcallapply permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check argument types when calling functions with &lt;code class=&quot;language-text&quot;&gt;call&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;bind&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Don’t check argument types when calling functions with &lt;code class=&quot;language-text&quot;&gt;call&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;bind&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;strictBindCallApply&lt;/code&gt; option checks whether correct argument types are passed when calling or declaring functions using methods like &lt;code class=&quot;language-text&quot;&gt;call&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;bind&lt;/code&gt; that can change function execution context.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sayHi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Hi, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;sayHi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;evan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Argument of type &apos;boolean&apos; is not assignable to parameter of type &apos;string&apos;.ts(2345)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sayHi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While changing function execution context doesn’t happen often, with this option disabled, TypeScript doesn’t check whether proper types are passed as function arguments when using &lt;code class=&quot;language-text&quot;&gt;call&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;apply&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;bind&lt;/code&gt;, potentially causing runtime type errors.&lt;/p&gt;
&lt;h3 id=&quot;strictfunctiontypes&quot; style=&quot;position:relative;&quot;&gt;strictFunctionTypes&lt;a href=&quot;#strictfunctiontypes&quot; aria-label=&quot;strictfunctiontypes permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Evaluates function parameters as contravariant types.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Evaluates function parameters as bivariant types.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;strictFunctionTypes&lt;/code&gt; option controls whether to evaluate function parameters contravariantly. Since this post isn’t about covariance and contravariance, check out this &lt;a href=&quot;https://seob.dev/posts/%EA%B3%B5%EB%B3%80%EC%84%B1%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;post&lt;/a&gt; if you want to learn more.&lt;/p&gt;
&lt;p&gt;I’ll explain covariance and contravariance briefly.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
Type &apos;(string | number)[]&apos; is not assignable to type &apos;string[]&apos;.
  Type &apos;string | number&apos; is not assignable to type &apos;string&apos;.
    Type &apos;number&apos; is not assignable to type &apos;string&apos;.ts(2322)
*/&lt;/span&gt;
foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; bar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I tried assigning the &lt;code class=&quot;language-text&quot;&gt;bar&lt;/code&gt; variable of type &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;string | number&gt;&lt;/code&gt; to the &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt; variable of type &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;string&gt;&lt;/code&gt;, and TypeScript says the &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; type can’t be assigned to a &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; type value.&lt;/p&gt;
&lt;p&gt;Why the error? Because the &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; type is a smaller concept than &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt;.&lt;/p&gt;
&lt;center&gt;
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b0ad89a090e9426b629aea7e838d5c43/38124/unionset.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 60.62500000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABsklEQVR42q2TX2+bMBTF+f7fZJqqSn1YXzZtT9vDlLSEAqEBG8JfQ+uQhjTb1HB6L4SUTOlbQQcsS/752PdcA4enbVus9Q6xWEHMHxA4FaKFxmO5xf6lBb/rPw2K5hHJkyKVUI3G5u8zrx4wMPjzQgsY5ExzODc57GkK9zYnFXAmOcSiQrIuIVcphE7pn0HqfixoTtEm+3b/BkxkDXuSwbcrTH76uLr4gctPX/Ht+jd85wG39xJmKJA2FX7ZE3z+comr79dwswAxuRU6gdrqHvhU78hVAc9S8GYKc5Nc3WS4mya0SQrHSzAjmBkIeEWMkNwtVAS/WnbjqM47sfuGjm+kYQ2XgTN11L1VHmUFIQHJoZC4i0JaXHSuWANsAJbk0uACsKsxsJNJbq0CliCglEdJnZ2ABrHbbFPBkN4HA88deSwriAgkRkfOz4orX25XfVHcUVH+d2nPh6JIeHmM5bp4F9j82w2x6TN4Fkpz5kLCiiQd6z13fUFOgs1Qdsph5jtldcGmjaRfIT0Em+8qrA/igHfB1qfBfmu9Z8QEDtyq09I/03qbofVU1yHceu2o9V4BQOhy3IbwEtMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;unionset&quot; title=&quot;&quot; src=&quot;/static/b0ad89a090e9426b629aea7e838d5c43/6af66/unionset.png&quot; srcset=&quot;/static/b0ad89a090e9426b629aea7e838d5c43/69538/unionset.png 160w,
/static/b0ad89a090e9426b629aea7e838d5c43/72799/unionset.png 320w,
/static/b0ad89a090e9426b629aea7e838d5c43/6af66/unionset.png 640w,
/static/b0ad89a090e9426b629aea7e838d5c43/38124/unionset.png 953w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;small&gt;The string | number type represents the union of string and number.&lt;/small&gt;
&lt;/center&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; type represents a union combining two types, so naturally the &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; type can’t contain the larger concept &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this case, we call the smaller concept &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; type a “subtype” of &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt;, and call the larger concept &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; a “supertype” of &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;. &lt;small&gt;(Subset and superset are also English terms. The names basically come from there.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Similarly, &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;string&gt;&lt;/code&gt; is also a smaller concept than &lt;code class=&quot;language-text&quot;&gt;Array&amp;lt;string | number&gt;&lt;/code&gt;. You can’t assign an array holding both &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; to an array declared to hold only &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;, so TypeScript errors.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When type &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; is a subtype of type &lt;code class=&quot;language-text&quot;&gt;T&apos;&lt;/code&gt;, if &lt;code class=&quot;language-text&quot;&gt;C&amp;lt;T&gt;&lt;/code&gt; is also a subtype of &lt;code class=&quot;language-text&quot;&gt;C&amp;lt;T&apos;&gt;&lt;/code&gt;, we say type &lt;code class=&quot;language-text&quot;&gt;C&lt;/code&gt; is &lt;strong&gt;covariant&lt;/strong&gt; or &lt;strong&gt;has covariance&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once you understand covariance, the rest is easy. Contravariance is the opposite of covariance. When type &lt;code class=&quot;language-text&quot;&gt;T&lt;/code&gt; is a subtype of type &lt;code class=&quot;language-text&quot;&gt;T&apos;&lt;/code&gt;, if conversely &lt;code class=&quot;language-text&quot;&gt;C&amp;lt;T&apos;&gt;&lt;/code&gt; is a subtype of &lt;code class=&quot;language-text&quot;&gt;C&amp;lt;T&gt;&lt;/code&gt;, we say type &lt;code class=&quot;language-text&quot;&gt;C&lt;/code&gt; is &lt;strong&gt;contravariant&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You might wonder if types need to be evaluated contravariantly. Surprisingly, it’s close at hand: function parameters, the subject of the &lt;code class=&quot;language-text&quot;&gt;strictFunctionTypes&lt;/code&gt; option.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Func&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; stringOrNumber&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Func&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; onlyString&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Func&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
Type &apos;Func&amp;lt;string&gt;&apos; is not assignable to type &apos;Func&amp;lt;string | number&gt;&apos;.
  Type &apos;string | number&apos; is not assignable to type &apos;string&apos;.
    Type &apos;number&apos; is not assignable to type &apos;string&apos;.ts(2322)
*/&lt;/span&gt;
stringOrNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; onlyString&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I said the &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; type is a subtype of &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; in the covariance example.&lt;/p&gt;
&lt;p&gt;If function parameters were evaluated covariantly, &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string&gt;&lt;/code&gt; would also be a subtype of &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string | number&gt;&lt;/code&gt;, meaning assigning &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string | number&gt;&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string&gt;&lt;/code&gt; should cause no problems.&lt;/p&gt;
&lt;p&gt;But this example shows that’s not the case. &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string | number&gt;&lt;/code&gt; is clearly a function type that accepts the supertype &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; as a parameter, but TypeScript errors when trying to assign a &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string&gt;&lt;/code&gt; type function that only accepts the subtype &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; as a parameter.&lt;/p&gt;
&lt;p&gt;Function parameters are evaluated contravariantly, operating opposite to covariant &lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt; types.&lt;/p&gt;
&lt;p&gt;This behavior might seem difficult, but think about it: the &lt;code class=&quot;language-text&quot;&gt;onlyString&lt;/code&gt; function is type &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;string&gt;&lt;/code&gt;, so it’s defined assuming the parameter is definitely &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we allowed this function to be recognized as one that can accept &lt;code class=&quot;language-text&quot;&gt;string | number&lt;/code&gt; parameters, developers could mistakenly pass &lt;code class=&quot;language-text&quot;&gt;number&lt;/code&gt; arguments to &lt;code class=&quot;language-text&quot;&gt;onlyString&lt;/code&gt;, which would die gloriously with a runtime type error.&lt;/p&gt;
&lt;center&gt;
  &lt;div style=&quot;max-width: 400px;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/300c81767ca8abe09ea1f7f958e3a5ae/80e3c/cube.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQADAAAAAAAAAAAAAAAAAAMCBAX/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/9oADAMBAAIQAxAAAAHtRRi95grMG6AX/8QAGhAAAgIDAAAAAAAAAAAAAAAAAhIAAQMQEf/aAAgBAQABBQIzShzPrNF6ddiU5BR6/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/ARIiv//EABgRAAIDAAAAAAAAAAAAAAAAAAARARAh/9oACAECAQE/AdYyK//EABwQAAIBBQEAAAAAAAAAAAAAAAABIQIQERJBUf/aAAgBAQAGPwImmyxL8KdnAzfos8m3/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARIRAxUUH/2gAIAQEAAT8hPQV8IVhguu4AFBkvo1fDNLB0Psa1mxQ6oVMJ704//9oADAMBAAIAAwAAABDL14L/xAAZEQACAwEAAAAAAAAAAAAAAAABIQAQEYH/2gAIAQMBAT8Qb0OdjgbX/8QAGREAAgMBAAAAAAAAAAAAAAAAAREAECFx/9oACAECAQE/ECeUDBqYOV//xAAcEAEBAAMBAAMAAAAAAAAAAAABEQAhMUEQUXH/2gAIAQEAAT8QpkXMAhFRdFyOYPM3RXZKl7M0/EK4Pn9cviwwp0+8W+3O9Rx5s8Rm/j//2Q==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cube&quot; title=&quot;&quot; src=&quot;/static/300c81767ca8abe09ea1f7f958e3a5ae/c08c5/cube.jpg&quot; srcset=&quot;/static/300c81767ca8abe09ea1f7f958e3a5ae/0913d/cube.jpg 160w,
/static/300c81767ca8abe09ea1f7f958e3a5ae/cb69c/cube.jpg 320w,
/static/300c81767ca8abe09ea1f7f958e3a5ae/c08c5/cube.jpg 640w,
/static/300c81767ca8abe09ea1f7f958e3a5ae/80e3c/cube.jpg 720w&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
  &lt;/div&gt;
  &lt;small&gt;It&apos;s like providing instructions saying you can somehow fit a star shape&lt;br&gt;into a hole made for squares only...&lt;/small&gt;
  &lt;br&gt;
  &lt;br&gt;
&lt;/center&gt;
&lt;p&gt;Because of this function characteristic, evaluating function parameters contravariantly is much safer, which is why TypeScript provides the &lt;code class=&quot;language-text&quot;&gt;strictFunctionTypes&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;With this option disabled, function parameters aren’t evaluated contravariantly, removing all assignment constraints shown in the example. As mentioned, this increases the chance of developers mistakenly passing wrong types as function arguments, causing runtime errors. Enable &lt;code class=&quot;language-text&quot;&gt;strictFunctionTypes&lt;/code&gt; when possible. &lt;small&gt;&lt;del&gt;(It’s not that inconvenient)&lt;/del&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h3 id=&quot;strictnullchecks&quot; style=&quot;position:relative;&quot;&gt;strictNullChecks&lt;a href=&quot;#strictnullchecks&quot; aria-label=&quot;strictnullchecks permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error when a value might be &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; in situations requiring a concrete value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Ignore when a value might be &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; in situations requiring a concrete value.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;strictNullChecks&lt;/code&gt; option errors when a value might be &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; in situations requiring a concrete value.&lt;/p&gt;
&lt;p&gt;Situations requiring a concrete value are mostly when trying to access an object’s property like &lt;code class=&quot;language-text&quot;&gt;foo.a&lt;/code&gt;. If the &lt;code class=&quot;language-text&quot;&gt;foo&lt;/code&gt; variable’s value is &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;, a runtime reference error occurs.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; people&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Person&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;evan&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; myPerson &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; people&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Uncaught ReferenceError: myPerson is not defined&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myPerson&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Array.prototype.find&lt;/code&gt; method is defined to return &lt;code class=&quot;language-text&quot;&gt;T | undefined&lt;/code&gt;, since &lt;code class=&quot;language-text&quot;&gt;find&lt;/code&gt; might or might not find the target element in the array.&lt;/p&gt;
&lt;p&gt;So the &lt;code class=&quot;language-text&quot;&gt;myPerson&lt;/code&gt; variable has type &lt;code class=&quot;language-text&quot;&gt;Human | undefined&lt;/code&gt;. Running this code, since there’s no element with name &lt;code class=&quot;language-text&quot;&gt;evan&lt;/code&gt; in the array, &lt;code class=&quot;language-text&quot;&gt;myPerson&lt;/code&gt; becomes &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;, causing a runtime reference error on the final console line.&lt;/p&gt;
&lt;p&gt;With &lt;code class=&quot;language-text&quot;&gt;strictNullChecks&lt;/code&gt; disabled, TypeScript gives no warning or error when accessing properties of &lt;code class=&quot;language-text&quot;&gt;myPerson&lt;/code&gt; even though it might be &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. With it enabled, you get this error:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber NaN&quot; class=&quot;language-ts line-numbers&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; people&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Person&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;evan&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; myPerson &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; people&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Object is possibly &apos;undefined&apos;.ts(2532)&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myPerson&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can solve this by explicitly checking if &lt;code class=&quot;language-text&quot;&gt;myPerson&lt;/code&gt; is &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; with an &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statement, or using optional chaining like &lt;code class=&quot;language-text&quot;&gt;myPerson?.name&lt;/code&gt; to maintain type safety.&lt;/p&gt;
&lt;h3 id=&quot;strictpropertyinitialization&quot; style=&quot;position:relative;&quot;&gt;strictPropertyInitialization&lt;a href=&quot;#strictpropertyinitialization&quot; aria-label=&quot;strictpropertyinitialization permalink&quot; class=&quot;anchor after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 