<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on IT Comparison</title><link>https://comparison.metacog.co.kr/posts/</link><description>Recent content in Posts on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Aug 2026 05:43:29 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Process vs Thread: Isolation vs Shared Execution</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-process-vs-thread-isolation-vs-shared-execution/</link><pubDate>Sun, 02 Aug 2026 05:43:29 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-process-vs-thread-isolation-vs-shared-execution/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;A process is an independently executing program instance with its own private address space, while a thread is a lightweight unit of execution that runs inside a process and shares that process&amp;rsquo;s memory with its sibling threads. The distinction matters because it determines how much isolation, communication overhead, and crash-safety you get versus how cheap context switching and data sharing are.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;
&lt;text x="95" y="35" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;Process&lt;/text&gt;
&lt;text x="475" y="35" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;Thread&lt;/text&gt;
&lt;rect x="20" y="55" width="110" height="250" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;text x="75" y="72" text-anchor="middle" style="fill:var(--primary)" font-size="11" font-weight="bold"&gt;Process A&lt;/text&gt;
&lt;rect x="30" y="80" width="90" height="24" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="75" y="96" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Code&lt;/text&gt;
&lt;rect x="30" y="108" width="90" height="24" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="75" y="124" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Data&lt;/text&gt;
&lt;rect x="30" y="136" width="90" height="34" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="75" y="157" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Heap&lt;/text&gt;
&lt;rect x="30" y="174" width="90" height="48" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="75" y="200" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Stack&lt;/text&gt;
&lt;rect x="170" y="55" width="110" height="250" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;text x="225" y="72" text-anchor="middle" style="fill:var(--primary)" font-size="11" font-weight="bold"&gt;Process B&lt;/text&gt;
&lt;rect x="180" y="80" width="90" height="24" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="225" y="96" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Code&lt;/text&gt;
&lt;rect x="180" y="108" width="90" height="24" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="225" y="124" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Data&lt;/text&gt;
&lt;rect x="180" y="136" width="90" height="34" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="225" y="157" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Heap&lt;/text&gt;
&lt;rect x="180" y="174" width="90" height="48" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="225" y="200" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Stack&lt;/text&gt;
&lt;line x1="131" y1="165" x2="169" y2="165" style="stroke:var(--secondary)" stroke-width="1.5" stroke-dasharray="4,3"/&gt;
&lt;text x="150" y="245" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;no shared memory&lt;/text&gt;
&lt;text x="150" y="258" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;(IPC only)&lt;/text&gt;
&lt;rect x="340" y="55" width="270" height="250" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;
&lt;text x="475" y="70" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;single process address space&lt;/text&gt;
&lt;rect x="355" y="82" width="240" height="50" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;
&lt;text x="475" y="103" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;Shared Code / Data / Heap&lt;/text&gt;
&lt;line x1="390" y1="132" x2="390" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;line x1="475" y1="132" x2="475" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;line x1="560" y1="132" x2="560" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;rect x="355" y="160" width="70" height="130" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;text x="390" y="176" text-anchor="middle" style="fill:var(--primary)" font-size="9" font-weight="bold"&gt;Thread 1&lt;/text&gt;
&lt;rect x="362" y="184" width="56" height="44" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="390" y="209" text-anchor="middle" style="fill:var(--content)" font-size="8"&gt;Stack&lt;/text&gt;
&lt;rect x="362" y="232" width="56" height="44" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="390" y="257" text-anchor="middle" style="fill:var(--content)" font-size="8"&gt;Registers&lt;/text&gt;
&lt;rect x="440" y="160" width="70" height="130" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;text x="475" y="176" text-anchor="middle" style="fill:var(--primary)" font-size="9" font-weight="bold"&gt;Thread 2&lt;/text&gt;
&lt;rect x="447" y="184" width="56" height="44" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="475" y="209" text-anchor="middle" style="fill:var(--content)" font-size="8"&gt;Stack&lt;/text&gt;
&lt;rect x="447" y="232" width="56" height="44" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="475" y="257" text-anchor="middle" style="fill:var(--content)" font-size="8"&gt;Registers&lt;/text&gt;
&lt;rect x="525" y="160" width="70" height="130" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;text x="560" y="176" text-anchor="middle" style="fill:var(--primary)" font-size="9" font-weight="bold"&gt;Thread 3&lt;/text&gt;
&lt;rect x="532" y="184" width="56" height="44" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="560" y="209" text-anchor="middle" style="fill:var(--content)" font-size="8"&gt;Stack&lt;/text&gt;
&lt;rect x="532" y="232" width="56" height="44" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;
&lt;text x="560" y="257" text-anchor="middle" style="fill:var(--content)" font-size="8"&gt;Registers&lt;/text&gt;
&lt;p&gt;&lt;text x="475" y="312" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;shared heap/code, private stack per thread&lt;/text&gt;
&lt;/svg&gt;&lt;/p&gt;</description></item><item><title>Authentication vs. Authorization: Verifying Identity vs. Granting Access</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-authentication-vs-authorization-verifying-identity-vs-granti/</link><pubDate>Sun, 02 Aug 2026 05:18:32 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-authentication-vs-authorization-verifying-identity-vs-granti/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Authentication (AuthN) confirms who a user or system claims to be, typically through credentials like passwords, biometrics, or tokens. Authorization (AuthZ) determines what an already-authenticated identity is permitted to do or access. The two are sequential and often conflated, but security bugs frequently trace back to confusing one for the other — e.g., checking that a user is logged in without checking they&amp;rsquo;re allowed to see a specific resource.&lt;/p&gt;</description></item><item><title>REST vs GraphQL: API Query Model</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-rest-vs-graphql-api-query-model/</link><pubDate>Sun, 02 Aug 2026 04:59:35 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-rest-vs-graphql-api-query-model/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;REST and GraphQL are both HTTP-based API paradigms that differ fundamentally in how clients request data. REST exposes multiple URLs with server-defined response shapes; GraphQL exposes a single endpoint where the client&amp;rsquo;s query body dictates exactly which fields and relationships to return. The distinction drives decisions around over-fetching, N+1 latency, HTTP cacheability, and schema contracts.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360"&gt;&lt;line x1="320" y1="8" x2="320" y2="352" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="160" y="26" text-anchor="middle" style="fill:var(--primary)" font-family="ui-monospace,monospace" font-size="17" font-weight="700"&gt;REST&lt;/text&gt;&lt;text x="160" y="43" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="10"&gt;multiple endpoints, fixed shape&lt;/text&gt;&lt;rect x="20" y="60" width="64" height="30" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="52" y="80" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Client&lt;/text&gt;&lt;rect x="130" y="52" width="150" height="24" rx="3" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;text x="205" y="68" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="10"&gt;GET /users&lt;/text&gt;&lt;rect x="130" y="82" width="150" height="24" rx="3" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;text x="205" y="98" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="10"&gt;GET /posts&lt;/text&gt;&lt;rect x="130" y="112" width="150" height="24" rx="3" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;text x="205" y="128" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="10"&gt;GET /comments&lt;/text&gt;&lt;line x1="84" y1="70" x2="128" y2="64" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="84" y1="74" x2="128" y2="94" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="84" y1="78" x2="128" y2="124" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="106" y="58" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;3 requests&lt;/text&gt;&lt;rect x="20" y="150" width="280" height="70" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="4,3"/&gt;&lt;text x="28" y="166" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;Each response = full object:&lt;/text&gt;&lt;text x="28" y="182" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;{ id, name, email, avatarUrl,&lt;/text&gt;&lt;text x="28" y="196" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; createdAt, role, prefs }&lt;/text&gt;&lt;text x="28" y="212" style="fill:var(--compare-a)" font-family="ui-monospace,monospace" font-size="9" font-weight="600"&gt;only name+email needed → over-fetch&lt;/text&gt;&lt;rect x="20" y="232" width="280" height="26" rx="3" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;text x="160" y="250" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="10"&gt;Related data → N+1 round-trips&lt;/text&gt;&lt;rect x="20" y="266" width="280" height="26" rx="3" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="160" y="284" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;Breaking change → new URL, e.g. /v2/&lt;/text&gt;&lt;text x="160" y="326" text-anchor="middle" style="fill:var(--compare-a)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;GET · cacheable · status codes&lt;/text&gt;&lt;text x="480" y="26" text-anchor="middle" style="fill:var(--primary)" font-family="ui-monospace,monospace" font-size="17" font-weight="700"&gt;GraphQL&lt;/text&gt;&lt;text x="480" y="43" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="10"&gt;one endpoint, client-declared shape&lt;/text&gt;&lt;rect x="340" y="60" width="64" height="30" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="372" y="80" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Client&lt;/text&gt;&lt;rect x="460" y="64" width="150" height="24" rx="3" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="535" y="80" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="10"&gt;POST /graphql&lt;/text&gt;&lt;line x1="404" y1="75" x2="458" y2="75" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="431" y="68" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;1 request&lt;/text&gt;&lt;rect x="340" y="100" width="140" height="110" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="410" y="115" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;query (client-authored)&lt;/text&gt;&lt;text x="348" y="133" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;query {&lt;/text&gt;&lt;text x="348" y="147" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; user(id: 1) {&lt;/text&gt;&lt;text x="348" y="161" style="fill:var(--compare-b)" font-family="ui-monospace,monospace" font-size="9" font-weight="600"&gt; name email&lt;/text&gt;&lt;text x="348" y="175" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; }&lt;/text&gt;&lt;text x="348" y="189" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; posts { title }&lt;/text&gt;&lt;text x="348" y="203" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;}&lt;/text&gt;&lt;rect x="490" y="100" width="126" height="110" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="553" y="115" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;SDL schema (server)&lt;/text&gt;&lt;text x="498" y="133" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;type User {&lt;/text&gt;&lt;text x="498" y="147" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; name: String!&lt;/text&gt;&lt;text x="498" y="161" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; email: String&lt;/text&gt;&lt;text x="498" y="175" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt; posts: [Post]&lt;/text&gt;&lt;text x="498" y="189" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;}&lt;/text&gt;&lt;rect x="340" y="220" width="276" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1"/&gt;&lt;text x="478" y="235" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;Response: exactly what was declared&lt;/text&gt;&lt;text x="348" y="252" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="9"&gt;{ user: { name, email }, posts: [{ title }] }&lt;/text&gt;&lt;rect x="340" y="266" width="276" height="26" rx="3" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="478" y="284" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;Schema evolves via @deprecated, no versioning&lt;/text&gt;&lt;text x="478" y="326" text-anchor="middle" style="fill:var(--compare-b)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;POST · typed schema · introspectable&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;REST&lt;/th&gt;
&lt;th&gt;GraphQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Endpoints&lt;/td&gt;
&lt;td&gt;One URL per resource type — &lt;code&gt;GET /users&lt;/code&gt;, &lt;code&gt;POST /orders&lt;/code&gt;, etc.&lt;/td&gt;
&lt;td&gt;Single URL (&lt;code&gt;POST /graphql&lt;/code&gt;); resource selection is in the query body&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response shape&lt;/td&gt;
&lt;td&gt;Fixed by the server; client receives all fields the endpoint defines&lt;/td&gt;
&lt;td&gt;Declared by the client per query; only the requested fields are returned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Over/under-fetching&lt;/td&gt;
&lt;td&gt;Chronic: server returns full objects; client discards unused fields or must make extra requests for missing ones&lt;/td&gt;
&lt;td&gt;Eliminated by design: resolvers return only fields the query specifies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP caching&lt;/td&gt;
&lt;td&gt;Native: &lt;code&gt;GET&lt;/code&gt; responses cache at CDN and browser level by URL + headers&lt;/td&gt;
&lt;td&gt;Non-trivial: queries are &lt;code&gt;POST&lt;/code&gt; bodies; requires persisted queries or APQ for cache-key stability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type system&lt;/td&gt;
&lt;td&gt;Optional — enforced only if you add OpenAPI/JSON Schema; not validated at runtime by default&lt;/td&gt;
&lt;td&gt;Mandatory SDL schema; all queries are parsed and validated against it before execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Versioning&lt;/td&gt;
&lt;td&gt;Breaking changes typically require new URL paths (&lt;code&gt;/v1/&lt;/code&gt;, &lt;code&gt;/v2/&lt;/code&gt;) or custom &lt;code&gt;Accept&lt;/code&gt; headers&lt;/td&gt;
&lt;td&gt;Additive schema evolution with &lt;code&gt;@deprecated&lt;/code&gt; directives; a single endpoint surface stays stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error handling&lt;/td&gt;
&lt;td&gt;HTTP status codes carry semantic meaning: 200, 404, 422, 500, etc.&lt;/td&gt;
&lt;td&gt;Always &lt;code&gt;200 OK&lt;/code&gt;; errors surface in an &lt;code&gt;errors[]&lt;/code&gt; array alongside any partial data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Introspection / discoverability&lt;/td&gt;
&lt;td&gt;Requires an external spec (OpenAPI/Swagger); not built into the protocol&lt;/td&gt;
&lt;td&gt;Built-in: query &lt;code&gt;__schema&lt;/code&gt; or &lt;code&gt;__type&lt;/code&gt; to get the full type graph at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;REST has one endpoint per resource; GraphQL has one endpoint for the entire API, and the query body — not the URL — determines what data comes back.&lt;/li&gt;
&lt;li&gt;REST responses return all server-defined fields for a resource (over-fetch), and fetching related data requires additional round-trips (N+1 problem). A single GraphQL query can traverse multiple types and return exactly the fields requested.&lt;/li&gt;
&lt;li&gt;REST uses standard HTTP verbs and status codes, making GET-based CDN and browser caching trivially available. GraphQL queries travel as POST bodies, breaking HTTP cache semantics by default and requiring explicit workarounds.&lt;/li&gt;
&lt;li&gt;GraphQL&amp;rsquo;s SDL provides a mandatory, introspectable type contract enforced at parse time. REST type contracts are optional add-ons (OpenAPI); the server can return anything without violating the protocol.&lt;/li&gt;
&lt;li&gt;REST breaking changes typically force a new URL version (&lt;code&gt;/v2/&lt;/code&gt;); GraphQL prefers additive schema evolution with &lt;code&gt;@deprecated&lt;/code&gt;, keeping a single endpoint surface over the API&amp;rsquo;s lifetime.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;REST&lt;/strong&gt; — Use REST when HTTP semantics matter: public APIs where CDN caching, stateless &lt;code&gt;GET&lt;/code&gt;-based reads, and broad ecosystem compatibility (browsers, curl, API gateways) are first-class requirements. Also the natural default when each resource type is consumed independently and maps cleanly to standard CRUD verbs.&lt;/p&gt;</description></item><item><title>Stack vs Heap: Memory Allocation Models</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-stack-vs-heap-memory-allocation-models/</link><pubDate>Sun, 02 Aug 2026 04:16:12 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-stack-vs-heap-memory-allocation-models/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;The stack and heap are two distinct memory regions used for different allocation strategies at runtime. The stack manages function call frames automatically via a single pointer increment/decrement, while the heap handles dynamic allocations with flexible lifetimes through an allocator. The distinction directly affects allocation speed, data lifetime, size constraints, and thread safety — core considerations in systems, embedded, and performance-sensitive programming.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360"&gt;&lt;line x1="320" y1="8" x2="320" y2="352" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="160" y="28" text-anchor="middle" style="fill:var(--primary)" font-family="ui-monospace,Menlo,monospace" font-size="17" font-weight="700"&gt;STACK&lt;/text&gt;&lt;text x="160" y="46" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,Menlo,monospace" font-size="10"&gt;grows downward, LIFO&lt;/text&gt;&lt;line x1="52" y1="60" x2="52" y2="300" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="52" y="56" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;high&lt;/text&gt;&lt;text x="52" y="314" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;low&lt;/text&gt;&lt;rect x="76" y="252" width="210" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="181" y="276" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="12"&gt;frame: main()&lt;/text&gt;&lt;rect x="76" y="209" width="210" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="181" y="233" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="12"&gt;frame: compute(n)&lt;/text&gt;&lt;rect x="76" y="166" width="210" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="2"/&gt;&lt;text x="181" y="190" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="12"&gt;frame: factorial(3)&lt;/text&gt;&lt;polygon points="290,166 302,160 302,172" style="fill:var(--compare-a)"/&gt;&lt;text x="306" y="172" style="fill:var(--compare-a)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;SP&lt;/text&gt;&lt;rect x="76" y="88" width="210" height="70" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="4,3"/&gt;&lt;text x="181" y="127" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="11"&gt;unused&lt;/text&gt;&lt;text x="181" y="326" text-anchor="middle" style="fill:var(--compare-a)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;auto-managed · O(1) · fast&lt;/text&gt;&lt;text x="181" y="341" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;~1-8 MB per thread&lt;/text&gt;&lt;text x="480" y="28" text-anchor="middle" style="fill:var(--primary)" font-family="ui-monospace,monospace" font-size="17" font-weight="700"&gt;HEAP&lt;/text&gt;&lt;text x="480" y="46" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="10"&gt;unordered, explicit lifetime&lt;/text&gt;&lt;rect x="356" y="60" width="248" height="240" rx="6" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="5,3"/&gt;&lt;rect x="372" y="76" width="90" height="42" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="417" y="101" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Object&lt;/text&gt;&lt;rect x="472" y="76" width="80" height="34" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="512" y="97" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Vec&amp;lt;T&amp;gt;&lt;/text&gt;&lt;rect x="372" y="128" width="60" height="30" rx="3" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="3,2"/&gt;&lt;text x="402" y="147" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;free&lt;/text&gt;&lt;rect x="442" y="120" width="110" height="50" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="497" y="149" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;HashMap&lt;/text&gt;&lt;rect x="372" y="172" width="55" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="399" y="196" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Box&lt;/text&gt;&lt;rect x="437" y="184" width="50" height="28" rx="3" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="3,2"/&gt;&lt;text x="462" y="201" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;free&lt;/text&gt;&lt;rect x="372" y="224" width="130" height="46" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="437" y="251" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;String data&lt;/text&gt;&lt;rect x="512" y="228" width="60" height="35" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="542" y="250" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Arc&lt;/text&gt;&lt;text x="480" y="326" text-anchor="middle" style="fill:var(--compare-b)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;manual/GC · flexible · fragments&lt;/text&gt;&lt;text x="480" y="341" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;limited by OS / RAM&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;th&gt;Heap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Allocation mechanism&lt;/td&gt;
&lt;td&gt;Pointer decrement — O(1), no bookkeeping&lt;/td&gt;
&lt;td&gt;Allocator call (malloc/new) — higher constant, free-list bookkeeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deallocation&lt;/td&gt;
&lt;td&gt;Automatic on scope/frame exit&lt;/td&gt;
&lt;td&gt;Explicit (free/delete) or garbage collector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data lifetime&lt;/td&gt;
&lt;td&gt;Bound to the declaring scope or call frame&lt;/td&gt;
&lt;td&gt;Arbitrary; can outlive any function call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size constraint&lt;/td&gt;
&lt;td&gt;Fixed at thread creation (typically 1–8 MB)&lt;/td&gt;
&lt;td&gt;Limited only by available virtual memory / RAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size known at compile time&lt;/td&gt;
&lt;td&gt;Required — compiler must know the type&amp;rsquo;s layout&lt;/td&gt;
&lt;td&gt;Not required — length/capacity decided at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fragmentation&lt;/td&gt;
&lt;td&gt;None — LIFO order keeps allocation contiguous&lt;/td&gt;
&lt;td&gt;Yes — internal and external fragmentation accumulate over time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thread ownership&lt;/td&gt;
&lt;td&gt;Each thread has its own stack; no synchronization needed&lt;/td&gt;
&lt;td&gt;Shared across threads; allocator must serialize internally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Stack overflow → immediate crash (SIGSEGV/signal)&lt;/td&gt;
&lt;td&gt;OOM → null / exception / OOM-killer; potentially recoverable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stack allocation is a single SP register decrement; heap allocation invokes an allocator with metadata updates, free-list traversal, and possible OS syscalls.&lt;/li&gt;
&lt;li&gt;Stack lifetime is strictly scoped to the function frame — data cannot be returned by pointer from the stack safely; heap memory can be returned, stored globally, or transferred across threads.&lt;/li&gt;
&lt;li&gt;Each thread has its own stack and needs no locking; the heap is process-wide and requires allocator-level synchronization on every alloc/free.&lt;/li&gt;
&lt;li&gt;Stack size is fixed and small (set by the OS or linker script); heap can grow dynamically, making it the only viable region for large buffers or runtime-sized collections.&lt;/li&gt;
&lt;li&gt;Heap fragmentation is a real operational concern in long-lived or allocation-heavy processes; the stack never fragments because it always grows and shrinks from one end in LIFO order.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stack&lt;/strong&gt; — Prefer the stack for local variables, function arguments, and fixed-size value types whose lifetime is bounded by the enclosing scope — it is faster, deterministic, and eliminates entire classes of memory bugs.&lt;/p&gt;</description></item></channel></rss>