<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>eddy_song.log</title>
        <link>https://velog.io/</link>
        <description>개발 지식을 쉽고 재미있게 설명해보자. ▶️ www.youtube.com/@simple-eddy</description>
        <lastBuildDate>Sat, 07 Mar 2026 07:10:14 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>eddy_song.log</title>
            <url>https://images.velog.io/images/eddy_song/profile/168d375a-aab0-472b-b134-be018b870d84/eddy-desc.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. eddy_song.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/eddy_song" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[대학생에게 Git branch와 merge를 설명해본다면? (Git 2편)]]></title>
            <link>https://velog.io/@eddy_song/git-3levels-5</link>
            <guid>https://velog.io/@eddy_song/git-3levels-5</guid>
            <pubDate>Sat, 07 Mar 2026 07:10:14 GMT</pubDate>
            <description><![CDATA[<p>Git이라는 버전 관리 시스템은 개발자라면 반드시 배워야 합니다.
하지만 한번에 다 소화하기엔 복잡하고 어렵죠.</p>
<p>하지만 <strong>초등학생도 이해할 수 있게 단순화시킨 설명</strong>을 들어보고,
대학생, 개발자로 <strong>차츰 더 수준을 높여간다면</strong> 훨씬 더 이해가 쉽지 않을까요?</p>
<ul>
<li>Wired의 <a href="https://www.wired.com/video/series/5-levels">1 concept in 5 levels</a>에서 영감을 받았습니다.</li>
<li>내용은 주로 <a href="https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control">Pro git</a>을 참고했습니다.</li>
</ul>
<hr>
<h2 id="설명할-개념">설명할 개념</h2>
<ul>
<li>가지치기 (Branch)</li>
<li>가지 합치기 (Merge)</li>
<li>충돌 (Conflict)</li>
</ul>
<hr>
<h2 id="👩🦱-대학생에게-설명하기">👩‍🦱 대학생에게 설명하기</h2>
<h3 id="지난-시간-복습">지난 시간 복습</h3>
<p>🧑‍🏫 저번에 git이 뭔지 얘기했었지? 기억나?</p>
<p>👩‍🦱 네. 개발자들이 쓰는 분산 버전 관리 시스템이요. 각자 자기 컴퓨터에 버전 기록이 있고, 중간중간 동기화하는 거.</p>
<p>🧑‍🏫 오, 잘 기억하네. 그때 마지막에 너가 좋은 질문을 했거든.</p>
<p>👩‍🦱 제가요? 뭐라고 했죠?</p>
<p>🧑‍🏫 &quot;각자 자기 컴퓨터에서 버전을 저장하다보면, 서로 저장한 버전 이력이 달라질 텐데 뭘 기준으로 하는 거냐&quot;고 물어봤잖아.</p>
<p>👩‍🦱 아 맞다. 그건 어떻게 해요?</p>
<p>🧑‍🏫 그걸 이해하려면 먼저 &#39;가지치기(Branch)&#39;라는 개념을 알아야 해.</p>
<hr>
<h3 id="왜-가지branch가-필요할까">왜 가지(Branch)가 필요할까?</h3>
<p>🧑‍🏫 팀플 상황을 다시 생각해보자. 너네 조 4명이서 PPT를 만들고 있어.</p>
<p>근데 너가 보기에 지금 PPT 디자인이 좀 별로야. 전체적으로 색감을 싹 바꿔보고 싶은 거지.</p>
<p>👩‍🦱 맞아요 그런 거 많죠. 근데 함부로 바꿨다가 다른 조원들이 &quot;뭐야 이게&quot; 하면 곤란하잖아요.</p>
<p>🧑‍🏫 그렇지. 그렇다고 아예 안 해볼 수도 없고.</p>
<p>이럴 때 어떻게 해?</p>
<p>👩‍🦱 음... 사본을 하나 만들어서 거기서 먼저 해보겠죠. &quot;디자인 시안 v2&quot; 이런 식으로.</p>
<p>🧑‍🏫 바로 그거야. Git에서 Branch가 딱 그 역할이야.</p>
<p>지금 다같이 작업하고 있는 버전이 있잖아? 이걸 <strong>&#39;메인(main)&#39;</strong> 이라고 불러. 팀플로 치면 &#39;발표용 최종본&#39;이지.</p>
<p>여기에 바로 이것저것 시도하면 조원들이 멘붕하잖아.</p>
<p>그래서 메인을 건드리지 않고, <strong>메인에서 갈라져 나온 별도의 작업 공간</strong>을 만드는 거야. 이게 Branch, 즉 &#39;가지&#39;야.</p>
<p>👩‍🦱 구글 슬라이드에서 &#39;사본 만들기&#39; 같은 건가요?</p>
<p>🧑‍🏫 비슷하지만 중요한 차이가 있어. 구글 슬라이드에서 사본을 만들면 파일 전체가 통째로 복사되잖아.</p>
<p>근데 Git에서 Branch를 만들면 파일을 복사하는 게 아니야. 커밋 위에 &#39;이름표&#39;를 하나 더 붙이는 거야.</p>
<p>👩‍🦱 이름표요?</p>
<p>🧑‍🏫 저번에 커밋이 기차처럼 줄줄이 연결된다고 했잖아?</p>
<p>![커밋이 연결된 모양 이미지]</p>
<p>지금 커밋이 A → B → C 순서로 쌓여있다고 해보자. 여기서 <code>main</code>이라는 건 사실 &quot;C 커밋을 가리키는 이름표&quot;야.</p>
<p>Branch를 새로 만든다는 건, 같은 C 커밋에 이름표를 하나 더 붙이는 거야. 예를 들면 <code>design-v2</code>라는 이름표를.</p>
<p>![같은 커밋에 이름표가 2개 붙은 이미지]</p>
<p>👩‍🦱 어, 그러면 파일이 2배가 되는 건 아니네요?</p>
<p>🧑‍🏫 맞아. 이름표 하나 추가하는 거니까 거의 비용이 없어. 가지를 10개 만들어도 저장 공간이 10배가 되지 않아.</p>
<p>👩‍🦱 오, 진짜 가볍네요.</p>
<p>🧑‍🏫 그래서 Git에서는 가지를 부담 없이 만들 수 있어. 뭔가 시도하고 싶으면 가지를 만들고, 필요 없으면 지우면 되니까.</p>
<hr>
<h3 id="가지-위에서-작업하기">가지 위에서 작업하기</h3>
<p>🧑‍🏫 자, 이제 <code>design-v2</code>라는 가지를 만들었어. 이 가지 위에서 작업을 시작하는 거야.</p>
<p>근데 여기서 하나 더 알아야 할 게 있어. <strong>HEAD</strong>라는 개념이야.</p>
<p>👩‍🦱 HEAD요? 머리?</p>
<p>🧑‍🏫 ㅋㅋ HEAD는 &quot;지금 내가 서 있는 위치&quot;를 가리키는 특별한 이름표야.</p>
<p>너가 <code>main</code>에서 작업하고 있으면 HEAD는 <code>main</code>을 가리키고 있어.
<code>design-v2</code>로 전환하면 HEAD가 <code>design-v2</code>를 가리키게 되지.</p>
<p>👩‍🦱 아 &#39;지금 내가 보고 있는 가지&#39;를 표시해주는 거네요.</p>
<p>🧑‍🏫 정확해. 가지를 전환하면 작업 폴더에 있는 파일들이 그 가지의 마지막 커밋 상태로 바뀌어.</p>
<p>👩‍🦱 파일이 바뀐다고요? 진짜요?</p>
<p>🧑‍🏫 응. 예를 들어서 <code>design-v2</code>에서 발표 자료 색상을 파란색으로 바꿔서 커밋을 했다고 치자. 그 상태에서 <code>main</code>으로 전환하면? 파일이 원래 색상으로 돌아가.</p>
<p>👩‍🦱 와... 그러면 가지별로 완전히 다른 상태를 왔다갔다 할 수 있는 거네요.</p>
<p>🧑‍🏫 그렇지. 그래서 팀플에서도 이렇게 쓸 수 있어.</p>
<p>조원 4명이 각자 가지를 만들어서 작업하는 거지. 한 명은 <code>intro-part</code>, 한 명은 <code>data-analysis</code>, 한 명은 <code>conclusion</code>. 메인에 직접 작업하는 사람은 없어.</p>
<p>![조원들이 각자 가지에서 작업하는 이미지]</p>
<p>👩‍🦱 각자 자기 가지에서만 작업하면 다른 사람 작업을 망칠 일이 없겠네요.</p>
<p>🧑‍🏫 바로 그거야. Branch의 핵심은 <strong>격리된 작업 공간</strong>이야.</p>
<hr>
<h3 id="가지-합치기merge--3가지-상황">가지 합치기(Merge) — 3가지 상황</h3>
<p>👩‍🦱 근데 결국에는 발표를 해야 되잖아요. 각자 가지에서 작업한 걸 하나로 합쳐야 하는 거 아니에요?</p>
<p>🧑‍🏫 맞아. 가지를 메인에 합치는 걸 <strong>머지(Merge)</strong>라고 해.</p>
<p>근데 합칠 때 상황에 따라 방식이 좀 달라져. 총 3가지가 있어.</p>
<hr>
<h4 id="상황-1-빨리-감기-fast-forward">상황 1: 빨리 감기 (Fast-forward)</h4>
<p>🧑‍🏫 제일 쉬운 경우부터 보자.</p>
<p>너가 <code>design-v2</code> 가지에서 커밋을 3개 했어. D, E, F.</p>
<p>근데 그 사이에 <code>main</code>에는 아무런 변화가 없었어. 여전히 C에 머물러 있는 거지.</p>
<p>![fast-forward 이전 이미지: main은 C, design-v2는 F를 가리킴]</p>
<p>👩‍🦱 그러면 main이 뒤쳐져있는 거네요.</p>
<p>🧑‍🏫 맞아. 이 상황에서 머지를 하면 어떻게 될까?</p>
<p>main 이름표를 그냥 F로 옮기면 끝이야.</p>
<p>![fast-forward 이후 이미지: main과 design-v2 둘 다 F를 가리킴]</p>
<p>👩‍🦱 어? 그냥 이름표만 옮기는 거예요? 뭔가 합치는 과정이 없네요.</p>
<p>🧑‍🏫 없어. 왜냐하면 main에서 갈라진 이후로 main 쪽에 새로운 게 없거든. 그냥 &#39;앞으로 빨리감기&#39;를 하면 되는 거야.</p>
<p>그래서 이걸 <strong>빨리감기 머지(Fast-forward merge)</strong>라고 불러.</p>
<p>👩‍🦱 진짜 빨리감기네요. 영상 빨리감기처럼 그냥 쭉 앞으로 가는 거잖아요.</p>
<p>🧑‍🏫 딩동댕.</p>
<hr>
<h4 id="상황-2-서로-다른-부분을-고친-경우">상황 2: 서로 다른 부분을 고친 경우</h4>
<p>🧑‍🏫 이번에는 좀 다른 상황이야.</p>
<p>너가 <code>design-v2</code>에서 색상을 바꾸는 동안, 다른 조원이 <code>main</code>에 서론을 수정해서 이미 머지를 해놓은 거야.</p>
<p>![양쪽에 커밋이 있는 이미지: main에도 새 커밋, design-v2에도 새 커밋]</p>
<p>👩‍🦱 아, 양쪽 다 변화가 있는 거네요. 이번에는 이름표만 옮기면 안 되겠다.</p>
<p>🧑‍🏫 맞아. 이름표를 옮기면 한쪽 변화가 사라지니까.</p>
<p>이럴 때 Git은 양쪽의 변화를 비교해. &quot;main에서 뭐가 바뀌었지?&quot; &quot;design-v2에서 뭐가 바뀌었지?&quot;</p>
<p>너는 색상을 바꿨고, 다른 조원은 서론을 고쳤어.
서로 <strong>건드린 부분이 다르니까</strong>, Git이 알아서 둘을 합쳐서 새로운 커밋을 하나 만들어줘.</p>
<p>![머지 커밋이 생긴 이미지: 양쪽에서 합쳐지는 모양]</p>
<p>👩‍🦱 오, Git이 자동으로 합쳐주는 거예요?</p>
<p>🧑‍🏫 응. 이렇게 합쳐서 새로 생긴 커밋을 <strong>머지 커밋(Merge Commit)</strong>이라고 해.</p>
<p>이 머지 커밋은 좀 특별해. 다른 커밋은 직전 커밋이 1개인데, 머지 커밋은 <strong>직전 커밋이 2개</strong>야. 양쪽 가지에서 온 거니까.</p>
<p>👩‍🦱 아하, 벌어졌던 길이 다시 하나로 만나는 지점이네요.</p>
<p>🧑‍🏫 아주 좋은 비유야. 그리고 머지가 끝나면 <code>design-v2</code> 가지는 역할을 다한 거니까 삭제해도 돼. 가지에서 작업했던 커밋 기록은 머지 커밋을 통해 남아있으니까.</p>
<p>👩‍🦱 근데 궁금한 게 있어요. 구글 독스에서는 여러 명이 동시에 편집해도 실시간으로 반영되잖아요. Git은 왜 이렇게 나눠서 합치는 방식을 쓰는 거예요?</p>
<p>🧑‍🏫 좋은 질문이야. 문서는 글자를 바꿔도 다른 글자에 영향이 없잖아.</p>
<p>근데 코드는 다르거든. 내가 함수 이름을 바꾸면, 그 함수를 호출하는 코드 수십 줄이 한꺼번에 영향을 받아. 이런 걸 &#39;의존성&#39;이라고 하는데, 코드는 이 의존성이 아주 복잡해.</p>
<p>그래서 실시간으로 동시에 편집하면 서로의 코드가 충돌하면서 프로그램이 터질 수가 있어. 각자 격리된 환경에서 작업하고, 의도적으로 합치는 게 훨씬 안전한 거지.</p>
<p>👩‍🦱 아... 그래서 일부러 가지를 나누는 거군요. 코드가 PPT랑은 차원이 다르긴 하네요.</p>
<hr>
<h4 id="상황-3-같은-부분을-고친-경우--충돌conflict">상황 3: 같은 부분을 고친 경우 — 충돌(Conflict)</h4>
<p>🧑‍🏫 마지막 상황. 이게 처음 겪으면 좀 당황스러운데, 원리를 알면 별 거 아니야.</p>
<p>너가 <code>design-v2</code>에서 결론 슬라이드의 핵심 문장을 이렇게 고쳤어.</p>
<blockquote>
<p>&quot;따라서 A 전략이 가장 효과적이다.&quot;</p>
</blockquote>
<p>근데 같은 시간에 다른 조원이 <code>main</code>에서 똑같은 결론 문장을 이렇게 고친 거야.</p>
<blockquote>
<p>&quot;따라서 B 전략을 우선 검토해야 한다.&quot;</p>
</blockquote>
<p>👩‍🦱 아... 같은 줄을 서로 다르게 고친 거네요. 😱</p>
<p>🧑‍🏫 이 상황에서 Git은 합칠 수가 없어. &quot;A 전략&quot;으로 해야 할지 &quot;B 전략&quot;으로 해야 할지 Git은 판단을 못 하거든.</p>
<p>이런 상황을 <strong>충돌(Conflict)</strong>이라고 해.</p>
<p>👩‍🦱 충돌이요? 그러면 에러가 나고 끝인 건가요?</p>
<p>🧑‍🏫 아니야. Git은 &quot;나 이거 못 합치겠으니까 네가 직접 골라줘&quot;라고 알려줘.</p>
<p>충돌이 난 파일을 열어보면 이런 식으로 표시가 돼있어.</p>
<pre><code>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD (main)
따라서 B 전략을 우선 검토해야 한다.
=======
따라서 A 전략이 가장 효과적이다.
&gt;&gt;&gt;&gt;&gt;&gt;&gt; design-v2</code></pre><p>👩‍🦱 오, 양쪽 버전을 둘 다 보여주는 거네요.</p>
<p>🧑‍🏫 그렇지. <code>=======</code>를 기준으로 위가 main 쪽, 아래가 네 가지 쪽이야.</p>
<p>너는 이 두 버전을 보고 판단을 내리면 돼.</p>
<p>&quot;A가 맞다&quot; 싶으면 B를 지우고, &quot;B가 맞다&quot; 싶으면 A를 지우고, 아니면 둘을 적절히 섞어서 새로운 문장을 만들어도 되지.</p>
<p>👩‍🦱 아, 그러면 그 표시들(<code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code>, <code>=======</code>, <code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code>)도 지우고 최종 버전만 남기면 되는 거예요?</p>
<p>🧑‍🏫 정확해. 그렇게 정리한 다음에 다시 커밋을 하면 머지가 완료되는 거야.</p>
<p>👩‍🦱 생각보다 무섭진 않네요. 그냥 &quot;둘 중에 뭘로 할래?&quot; 하고 물어보는 거잖아요.</p>
<p>🧑‍🏫 맞아. 처음에 충돌이 뜨면 좀 당황스러운데, 알고 보면 그냥 선택의 문제야.</p>
<p>실제로 개발자들은 매일같이 충돌을 해결해. 팀으로 일하면 피할 수 없거든. 그래서 &quot;충돌이 나는 건 실수가 아니다. 합치기 전에 리뷰하는 과정일 뿐이다.&quot; 이렇게 생각하는 게 좋아.</p>
<p>👩‍🦱 오... 충돌이 일어나는 게 자연스러운 거군요.</p>
<p>🧑‍🏫 응. 오히려 &quot;충돌이 한번도 안 나는 팀&quot;은 진짜 소통이 잘 되는 팀이거나, 혼자 다 하고 있는 거야. ㅋㅋ</p>
<hr>
<h3 id="정리">정리</h3>
<p>🧑‍🏫 오늘 내용을 정리해볼까?</p>
<p>👩‍🦱 네!</p>
<p>🧑‍🏫 <strong>Branch</strong>는 메인을 건드리지 않고 따로 작업할 수 있는 공간이야. 파일을 복사하는 게 아니라 커밋 위에 이름표를 붙이는 거라서 매우 가벼워.</p>
<p><strong>Merge</strong>는 가지를 메인에 합치는 거고, 상황에 따라 3가지 방식이 있어.</p>
<ol>
<li>메인에 변화가 없으면 → <strong>빨리감기(Fast-forward)</strong>. 이름표만 옮기면 끝.</li>
<li>양쪽 다 변화가 있는데 다른 부분을 고쳤으면 → Git이 자동으로 합쳐서 <strong>머지 커밋</strong>을 만들어줘.</li>
<li>양쪽이 같은 부분을 고쳤으면 → <strong>충돌(Conflict)</strong>이 나고, 사람이 직접 골라서 해결해야 해.</li>
</ol>
<p>👩‍🦱 정리하니까 깔끔하네요.</p>
<p>근데 한 가지 더 궁금한 거. 이 가지 만들고 합치는 걸 지금은 제 컴퓨터에서 하는 건데, 다른 조원들한테는 어떻게 공유하는 거예요? push, pull 이런 거 들어본 적 있거든요.</p>
<p>🧑‍🏫 오, 역시 좋은 질문이야. 그게 바로 원격 저장소(Remote)와 동기화하는 방법인데.</p>
<p>다음에 알아보도록 하자!</p>
<hr>
<h2 id="관련-링크">관련 링크</h2>
<p>🔗 <a href="https://velog.io/@eddy_song/git-3levels-1">초등학생에게 Git을 설명해본다면? (Git 1편)</a>
🔗 <a href="https://velog.io/@eddy_song/git-3levels-2">대학생에게 Git을 설명해본다면? (Git 1편)</a>
🔗 <a href="https://velog.io/@eddy_song/git-3levels-3">개발자에게 Git을 설명해본다면? (Git 1편)</a>
🔗 <a href="https://velog.io/@eddy_song/git-3levels-4">초등학생에게 Git branch와 merge를 설명해본다면? (Git 2편)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Default Argument로 안전하고 편리하게 인터페이스 설계하기]]></title>
            <link>https://velog.io/@eddy_song/default-argument</link>
            <guid>https://velog.io/@eddy_song/default-argument</guid>
            <pubDate>Sun, 29 Sep 2024 07:51:30 GMT</pubDate>
            <description><![CDATA[<h2 id="많은-일을-하면서도-이해하기-쉬운-인터페이스">많은 일을 하면서도, 이해하기 쉬운 인터페이스</h2>
<p>코딩하다보면 인터페이스를 많이 만든다. 함수, 생성자. 프로토콜 등. 하루에도 수십번씩 인터페이스를 어떻게 할지 결정해야 한다.</p>
<p>인터페이스를 만들 때 황금률이 있다. ‘구현은 많은 일을 하면서도, 인터페이스는 간단해야 한다’. 간단하게 말해 내부에서는 많은 일을 하지만, 밖에서는 그런 거 다 몰라도 쉽게 쓸 수 있으면 된다. 그러면 좋은 인터페이스다.</p>
<p>하나의 인터페이스를 다양한 곳에서 재사용할 수 있다면 인터페이스는 간단해진다. 그래서 사용하는 맥락이 달라질 때도 쓸 수 있도록 하고 싶을 때, 흔히 하는 표현으로 ‘파라미터를 뚫어준다’. 사용자가 직접 커스텀할 수 있는 파라미터를 넣도록 설계한다는 뜻이다.</p>
<p>흔한 예시로, 아래와 같은 코드가 있다.</p>
<pre><code class="language-swift">func queryValue(for key: String, caseSensitive: Bool) -&gt; String?</code></pre>
<p>특정 key에 대한 값을 조회하는 함수다. 보통은 대문자 key를 넣어도 소문자 key까지 알아서 조회해주면 편하다. 하지만 어떤 경우에는 대문자 key를 넣었으면 대문자 key만 나와야 한다. 그래서 둘다 가능할 수 있게 <code>caseSensitive: Bool</code> 이라는 파라미터를 뚫어준다.</p>
<p>다만 이게 항상 좋지는 않다. <code>caseSensitive: Bool</code> 같은 파라미터가 계속 늘어나면, 인터페이스가 복잡해진다. 파라미터가 너무 많으니 호출하는 쪽에서 이해하기 어려워진다. </p>
<p>그냥 잘 몰라도 알잘딱깔센으로 해주면 안돼? 하는 마음이 든다.</p>
<h2 id="인터페이스를-쉽게-만들어주는-default-argument">인터페이스를 쉽게 만들어주는 Default Argument</h2>
<p>그럴 때 쓰는 훌륭한 도구가 바로 Default Argument다. Swift 언어뿐만 아니라 대부분의 modern language에서 대부분 제공하는 기능이다.</p>
<p>함수를 선언할 때, default argument도 같이 선언한다. 사용하는 쪽에서는 이 argument가 optional parameter가 된다. 즉, 이 값을 굳이 넣지 않아도 컴파일 에러가 나지 않는다. 알아서 default 값으로 넣어준다.</p>
<pre><code class="language-swift">func queryValue(for key: String, caseSensitive: Bool = false) -&gt; String?</code></pre>
<p><code>caseSensitive: Bool</code> 에 default argument를 설정했다. 이제 호출하는 쪽이 간단해진다.</p>
<pre><code class="language-swift">let accountNumber = queryValue(for: &quot;accountNumber&quot;)</code></pre>
<p>default argument를 사용하면 구현에서 더 많은 기능을 하면서도, 인터페이스는 간단하다. 좋은 인터페이스를 만들 수 있는 효과적인 기능이다. 그래서 많은 개발자들이 애용한다.</p>
<h2 id="쓰기-전에-생각했나요">쓰기 전에 생각했나요?</h2>
<p>여기까지는 기본적인 내용. default argmuent에 대한 글을 쓰게 된 이유는 따로 있다. 생각없이 default argument를 썼다가 버그를 만든 경험을 몇번 하게 됐기 때문이다.</p>
<p>호출하는 쪽에서는 안 넣었는데, 알아서 값이 들어간다. 분명 편리한 기능이지만, 어떤 상황에서는 굉장히 짜증나는 버그를 만든다. 간단한 default argument 하나 때문에 몇 시간을 디버깅한 적도 있다.</p>
<p>몇 번 큰코 다치면서 default argument 를 쓸 때 주의해야하는 경우를 체득하게 되었다.</p>
<h2 id="1-argument가-잘못-들어갔을-때-위험할-수-있는-경우">1. Argument가 잘못 들어갔을 때 위험할 수 있는 경우</h2>
<p><code>skipAd: Bool</code> 이라는 파라미터를 default argument 로 지정한 코드가 있었다. 화면 여러개로 구성된 퍼널을 띄우는 인터페이스였다. </p>
<p>이 퍼널에는 마지막에 광고 단계가 있다. 이 광고 단계를 skip할 수 있게 만드는 파라미터였다. default argument는 <code>true</code>로 돼있었다.</p>
<p>대부분의 경우 광고는 보여준다. 특정 퍼널만 예외다. 그러면 default argument 를 <code>true</code> 로 설정하는 것? 문제가 없어보인다. 나도 그렇게 생각했다. </p>
<p>하지만 생각해보면 이 파라미터에는 애초에 안전한 default parameter라는 게 없었다. 왜냐하면 이 광고라는 게 굉장히 중요한 비즈니스 로직이었기 때문이다. </p>
<p>이 파라미터를 실수해서 발생할 수 있는 상황은 이렇다.</p>
<p>1/ 광고를 띄우면 안 되는데 광고를 띄웠다.
2/ 광고를 띄워야 하는데 광고를 안 띄웠다.</p>
<p>둘 중 하나가 별 문제 없는 상황이면 default 로 해도 된다. 하지만 이 퍼널을 통과하는 유저 트래픽과, 광고 매출의 중요성을 생각해봤을 때, 1번과 2번 둘다 매우 큰 문제였다. </p>
<p>광고를 실수로 안 띄웠을 경우, 매출에 타격이 갈 수 있다. 광고를 실수로 띄웠을 경우? 고객에게 항의를 받을 수 있다는 것이다. </p>
<p>즉, 잘 모르고 호출하면 안되는 종류의 파라미터였던 것이다.</p>
<p>또 하나 예를 들어보자면 이런 게 있다. <strong><a href="https://www.swiftbysundell.com/articles/default-arguments-in-swift/">Default arguments in Swift</a></strong> 라는 글에서 인용했다.</p>
<pre><code class="language-swift">enum ConflictResolution {
    case overwriteExisting
    case stopIfExisting
    case askUser
}

func store&lt;T: Storable&gt;(
    _ value: T,
    conflictResolution: ConflictResolution = .stopIfExisting
) throws {
    ...
}</code></pre>
<p>어떤 값을 저장하는 인터페이스다. 그런데 conflict가 있을 때 해결하는 방식을 optional parameter로 뚫어놓았다.</p>
<p>호출하는 쪽에서는 간단하게 이렇게 호출한다.</p>
<pre><code class="language-swift">try store(value)</code></pre>
<p>문제는 conflict가 있을 때 <strong>멈추는 것 (<code>stopIfExisting</code>)이 그렇게 뻔한 동작이 아니라는 점</strong>이다. 사용 하는 쪽에서는 store를 호출했으니 분명 값이 있기를 기대했다. 근데 기대와는 다르게 파라미터의 유무에 따라 아예 store 가 약속한 동작을 하지 않아버린다. </p>
<p>default argument 를 <strong>덮어쓰기 (<code>overwriteExisting</code>) 로 해도 위험한 건 마찬가지</strong>다. 기존에 있는 데이터가 예상치 못하게 날아가버릴 수 있기 때문.</p>
<p>이 경우에는, 편리하려고 쓴 <strong>default argument가 오히려 나중의 큰 버그를 만드는 불씨</strong>가 될 수 있다.</p>
<p>나는 이미 많은 곳에서 호출하고 있는 API를 바꿀 때는 default argument를 많이 쓰곤 했다. 왜냐하면 일일이 다 호출부를 바꾸지 않아도, 내가 원하는 곳에서만 파라미터를 넣으면 동작하니까. </p>
<p>하지만 그렇게 많은 곳에서 호출하는 인터페이스라면, 오히려 앱의 동작에 끼치는 영향은 더 크다고 볼 수 있다. 게다가 내가 optional로 만든 parameter가 예상과 전혀 다른 동작을 만들 수도 있다면? </p>
<p>그럴 때는 아무리 귀찮더라도, default argument를 안 쓰는 게 안전하다. <code>skipAd</code> 케이스에서 버그를 일으키고 내가 배운 경험칙이다.</p>
<h2 id="2-중요한-data-transfer-object-인-경우">2. 중요한 Data Transfer Object 인 경우</h2>
<p>Data transfer object의 정확한 정의는 조금씩 다 다른 것 같다. 값 객체라고 부르기도 하고. 불변 객체라고 하기도 하고. </p>
<p>아무튼 여기서 DTO는 1) 객체가 스스로 행동/기능을 갖지 않고. 2) 값만 다른 객체로 전달하기 위한 목적일 때를 말한다.</p>
<p>예를 들면 이런 객체.</p>
<pre><code class="language-swift">struct UserDTO: Codable {
    let id: Int
    let name: String
    let email: String?
    let age: Int?

    // You can also provide default values if needed
    init(id: Int, name: String, email: String? = nil, age: Int? = nil) {
        self.id = id
        self.name = name
        self.email = email
        self.age = age
    }
}</code></pre>
<p>클라이언트 개발을 하다보면, DTO 안에 들어있는 필드가 많은 경우, 그리고 각각의 필드가 채워지는 시점이 다른 경우가 꽤 있다. 사용자가 폼을 하나씩 채워가면서 그 안에 있는 값이 생긴다든지. 여러 개의 API를 서버로 호출해서 그 결과값을 받고, DTO에 저장한 다음, 최종적으로 마지막 API의 요청값으로 보낸다든지..</p>
<p>위의 코드에서 보다시피 이 DTO에는 default argument를 많이 쓴다. 특정 값은 없을 수도 있고. 나중에 채워질 수도 있고 하기 때문.</p>
<p>DTO는 1/ 전달이 되면서 복사, 생성이 많이 일어난다, 2/ 프로퍼티가 빈번하게 추가된다. </p>
<p>그러다보니 <strong>새로운 프로퍼티를 추가했을 때 생성, 복사 함수에 깜빡하고 파라미터를 넣지 않는 실수가 자주 발생</strong>한다.</p>
<p>그러다보면 이런 버그가 발생한다. 특정 퍼널을 시작할 때 분명히 age를 24로 넣고 시작했다. 그런데 화면을 몇개 지나 최종적으로 서버에 올라가는 값이 nil이다? 이거 왜 그러지?</p>
<p>컴파일 에러가 발생하지 않고 중간에 값이 바뀌기 때문에 디버깅하기가 어렵다. DTO가 여러 컴포넌트에 걸쳐 쓰이고 있다면 더더욱 짜증이 난다.</p>
<p>그래서 크고 중요한 DTO일 때는 가급적이면 default argument를 안 쓴다.</p>
<h2 id="3-프로토콜-익스텐션에서-default-parameter를-제공하는-경우">3. 프로토콜 익스텐션에서 default parameter를 제공하는 경우</h2>
<p>다른 언어에서는 <code>interface</code> 를 정의할 때 보통 구현은 추가할 수 없다. 하지만 swift의 가장 큰 특징 중 하나인 <code>protocol</code>은 인터페이스를 정의하는데 쓰이면서도, 기본 구현을 추가할 수 있다. 이것을 protocol extension이라고 한다. (이 protocol extesion을 적극적으로 쓰는 것을 protocol-oriented programming 라고 부르기도 한다.)</p>
<p>Protocol은 추상화된 타입이다. default argument 기능을 제공하지 않는다. 하지만 protocol extension 으로 사용해서 default argument 기능을 만들 수 있다. </p>
<p>protocol extension 안에서 protocol 내부에 선언된 함수를 한번 더 호출하면 된다. 이 패턴을 쓰면, 외부에서는 알 수 없지만, message 파라미터를 넣지 않았을 때 자동으로 2번 함수가 불린다. 그리고 2번 함수는 default argument와 함께 1번 함수의 구현체를 호출한다.</p>
<pre><code class="language-swift">protocol Greetable {
    func greet(message: String) // 1) 여기서는 default argument 불가능
}

extension Greetable {
    func greet(message: String = &quot;Hello&quot;) { // 2) extension의 구현부에서는 default argument 가능
        greet(message: message)
    }
}</code></pre>
<p>위의 케이스와 다르게, protocol extension에 default arugment를 꼭 쓰지 말아야하는 것은 아니다. 하지만 잘못 하면 실수할 수 있는 여지가 있다. 예를 들면, <code>greet</code>에 파라미터가 2개 추가되었다고 하자.</p>
<pre><code class="language-swift">protocol Greetable {
    func greet(message: String, name: String, emoji: String) // 1
}

extension Greetable {
    func greet(message: String = &quot;Hello&quot;, to name: String = &quot;Guest&quot;, withEmoji emoji: String = &quot;😊&quot;) {
        greet(message: message, name: name, emoji: emoji) // 2
    }
}
</code></pre>
<p>그런데 깜빡하고 (!) 구현체에는 파라미터를 추가해주지 않았다.</p>
<pre><code class="language-swift">struct Person: Greetable {
    func greet(message: String) { // 3
        print(message)
    }
}</code></pre>
<p>그렇지만 다음과 같이 구현체에 greet 을 호출했을 때 컴파일 에러가 나지 않는다. </p>
<pre><code class="language-swift">let person = Person()
person.greet()</code></pre>
<p>왜냐하면, person에게는 Greetable의 extension이 이 준 기본 구현 함수 (2)가 있기 때문이다. </p>
<p>대신 여기서 개발자는 이상한 에러를 겪는다. <strong>protocol 내부에서 ‘무한 루프’</strong>가 일어난다.</p>
<ul>
<li>person.greet() 을 했을 때 2번이 호출되고, 이 2번은 1번에 연결된 구현체를 찾으려 한다. </li>
<li>하지만 구현체에 파라미터를 추가해주지 않았다. 따라서 구현체에는 파라미터 3개가 모두 있는 함수가 없는 상황. </li>
<li>파라미터가 3개가 있는 함수는 결국 extension으로 딸려온 2번 함수밖에 없다. </li>
<li>따라서 2번 함수는 자기 자신을 호출한다. </li>
<li>무한 루프가 일어난다.</li>
</ul>
<p>이것이 protocol extension을 사용해서 default parameter를 사용했을 때의 함정이다. 무한 루프는 곧 크래시로 이어진다. 1번, 2번 케이스처럼 크래시도 안 나고 아예 동작을 이상하게 해버리는 경우보다 좀 낫긴 하다.</p>
<p>하지만 실수하기 좋은 코드인데 컴파일 에러가 나지 않는다. 개발자를 어리둥절하게 만드는 케이스다. 조심해서 써야 한다.</p>
<h2 id="결론">결론</h2>
<p>원칙은 쉽고 도구는 많다. 하지만 실제로 써보면서 상황에 맞게 판단하고 위험할 때를 알아야 한다. 편리하면 실수하기 쉽다. 어려우면 실수하기 어렵다. 그 밸런스는 결국 시행착오 과정에서 배우는 것 같다.</p>
<h2 id="요약">요약</h2>
<ul>
<li>Default Argument는 인터페이스를 간단하게 유지하면서도 많은 일을 하게 해준다.</li>
<li>편리한 만큼, 버그를 일으킬 위험이 있으므로 조심해서 써야 한다.</li>
<li>파라미터가 Argument가 잘못 들어갔을 때 위험할 수 있는 경우. 중요한 Data Transfer Object인 경우에는 가급적 쓰지 말자.</li>
<li>Protocol Extension을 활용한 default argument 사용 시, 잘못하면 무한 루프가 생길 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[부트캠프 끝나면 뭐해야 되지?]]></title>
            <link>https://velog.io/@eddy_song/rejection</link>
            <guid>https://velog.io/@eddy_song/rejection</guid>
            <pubDate>Wed, 03 Jan 2024 13:28:13 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eddy_song/post/06d346ff-1f2d-4f5e-838c-0bb1d6d1ff66/image.jpeg" alt=""></p>
<p>가끔 부트캠프를 다니는 분들과 상담을 할 때가 있어요. 그러면 &#39;부트캠프 끝나고 뭘 해야 하나?&#39;라는 질문이 많이 나와요. </p>
<p>부트캠프는 커리큘럼 대로 하면 되는데 이제 끝난다고 바로 취업이 되는 건 아니니까, 그때부터 이제 뭘 해야 되는지 막막한 거죠.</p>
<h2 id="부트캠프-후-할-일">부트캠프 후 할 일</h2>
<p>그땐 뭘 해야 할까요? 생각해 보면 기술 면접, 코딩 테스트, 프로젝트 준비 이런 걸 해야겠죠. 이런 걸 얘기할 수도 있겠지만... 저는 조금 다른 관점의 생각에 대해서 말씀드리려고 합니다.</p>
<p>저는 부트캠프 끝나면 뭘 해야 하냐? 저는 <strong>&#39;거절을 당해봐야 된다&#39;</strong>고 생각해요. 여러분이 일부러 거절을 당하려고 해봐야, 여러분의 취업이 더 빨라질 겁니다.</p>
<h2 id="부족하니까-준비하자-마인드셋">부족하니까 준비하자 마인드셋</h2>
<p>제가 왜 이런 생각을 하게 됐냐면, 생각보다 이런 분들이 많더라고요. </p>
<p><strong>부트캠프가 끝났는데 실제로 회사에 지원을 하지 않는</strong> 거예요. </p>
<p>왜 지원 안 하는지? 물었어요. </p>
<blockquote>
<p>&quot;나는 아직 부족해서 지원 할 수가 없다&quot;, 
&quot;모집 공고에 A도 필요하고 B도 필요하다고 써있는데 저는 다 몰라서 안될 것 같다&quot; 
&quot;이력서 쓰는 중인데 너무 쓸 게 없어서 이걸 다 채우고 지원을 해야 될 것 같다&quot; 
&quot;아직 해본 프로젝트가 없어서 지원 못할 것 같다&quot;</p>
</blockquote>
<p>공통적으로 담겨있는 마인드가 뭐냐면 &#39;부족하니까 준비하자&#39;예요. </p>
<p>나는 아직 부족하니까 나대지 말고 일단 혼자 준비하자, 그리고 아예 시도 자체를 안 해버리는 거죠.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/469006ca-45e8-4557-974f-8f0cb5bd36f0/image.png" alt=""></p>
<h2 id="부족하니까-시도하자">부족하니까 시도하자</h2>
<p>저는 반대로 생각해요. 부족하니까 오히려 더 시도를 해야 된다고 생각하는 파거든요.</p>
<p>&#39;부족하니까 준비하자&#39;라는 마인드를 들여다보면, 어차피 내가 시도를 안 해봐도 내가 이게 부족하고, 지금 이게 안 되는 걸 뻔히 아니까, 굳이 시도할 필요가 없다고 생각할 수도 있죠. </p>
<p>하지만 저는 다른 생각을 갖고 있습니다.</p>
<p>개발자 채용은 막 수능이나 자격증 시험 같은 게 아니에요. 회사마다 뽑는 기준이 다 다르고, 채용 공고에 적혀있는 것도 절대적인 기준이 아닙니다. </p>
<p>예를 들어, &#39;3년 이상 경력 개발자&#39;라고 써놓는다고 해서 3년 미만이면 무조건 탈락? 이런 건 아니에요. &#39;TDD에 대한 이해&#39;라고 써놓는다고 해서 TDD 안 해봤으면 무조건 떨어뜨린다? 이런 것도 아니고요.</p>
<h2 id="거절을-경험하는-중요성">거절을 경험하는 중요성</h2>
<p>여러분이 진짜로 떨어질지, 안 떨어질지, 어디가 어떻게 부족할지는 모르는 거예요. 그래서 일단 한번 부딪히고 거절을 당해보면서 감을 익혀야 됩니다. </p>
<p>특히 신입 개발자 채용의 경우에는 더 그렇다고 생각해요. 신입은 &#39;포텐셜&#39;을 보는 거거든요. 그렇기 때문에 절대적으로 내가 못해서 떨어지는 것도 아니고, 절대적으로 내가 잘해서 붙는 것도 아니에요. </p>
<p>저는 개인적으로 여러분들이 부족하더라도 일부러 더 지원도 하고, 떨어져도 봐야 훨씬 더 빨리 붙는다고 생각해요.</p>
<h2 id="거절에-대한-두려움-극복">거절에 대한 두려움 극복</h2>
<p>물론 이게 말이 쉽지 실천은 쉽지 않은데요, 그 이유는 &#39;두려움&#39;입니다. 거절에 대한 두려움이죠. </p>
<p>&#39;부족하니까 준비하자&#39;라는 마인드셋이 되는 이유는 부족하니까 나는 거절당할 거고, 부정적인 반응을 받으면 내가 부족하다는 것을 자꾸 실감하게 되니까 그게 싫은 거거든요. </p>
<p>이거는 저도 너무 공감을 합니다. 지난 영상에서 말했다시피 저도 수없이 떨어져 본 사람으로서 멘탈이 진짜 힘들었거든요. </p>
<p>그럴 때 저한테 도움이 많이 된 영상이 있습니다.</p>
<h2 id="지아-장의-거절당하기-연습">지아 장의 &#39;거절당하기 연습&#39;</h2>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/9e921d09-b4e1-4576-bff4-22ed58728dfe/image.jpeg" alt=""></p>
<p><a href="https://www.ted.com/talks/jia_jiang_what_i_learned_from_100_days_of_rejection?language=ko">지아 장의 TED 영상</a>에서 본 이야기입니다. </p>
<p>지아 장은 어릴 때부터 꿈이 사업가였어요. 근데 사업을 시작하려고 하니 투자도 거절당하고, 고객한테도 거절당하는 일이 많았어요. 거절당하는 게 무서웠던 그는, 어떻게 했을까요?</p>
<p>지아 장은 일부러 거절당하는 연습을 하기로 합니다. 모르는 사람한테 갑자기 돈을 빌려달라고 하거나, 햄버거 가게에서 햄버거를 리필해 달라고 하는 등, 당연히 안 될 것 같은 시도를 100일 동안 챌린지로 해요.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/f0d9966d-f83f-4d46-b062-c0e55e9b0ae8/image.png" alt=""></p>
<p>그 과정에서 많은 재미있는 일이 일어나는데요. 자세한 내용은 한번 봐보시길 추천해요.</p>
<p>아무튼 이 &#39;거절당하기 연습&#39;을 통해, 지아 장은 거절이 나의 부족함이 아니라 상대방의 의견이라는 걸 배우게 됩니다. 부정적인 반응을 당해도 쉽게 포기하지 않는 체력을 기르게 되죠.</p>
<h2 id="우리한테-적용하기">우리한테 적용하기</h2>
<p>저는 &#39;일부러 거절당하기&#39;가 우리한테도 되게 필요하다고 생각해요. </p>
<p>&#39;내가 부족하니까 방에서 열심히 준비하자가 아니라, </p>
<p><strong>&#39;내가 부족한 걸 알지만 그럼에도 불구하고 나가서 시도를 해보자</strong>는 거죠.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/5411fd7e-7cdf-406f-a368-3093570e8bcd/image.jpeg" alt=""></p>
<p>여러분의 첫 이력서, 첫 면접, 첫 프로젝트는 사실 무조건 구릴 수밖에 없어요. 아무리 방에서 혼자 준비를 해도 마찬가지입니다. 실전을 처음부터 잘 하는 사람은 없단 말이죠.</p>
<p>그래서 저는 여러분들이 부트캠프가 끝나셨다면 일부러 거절당할 만한 시도를 열심히 해 보라고 말씀드리고 싶어요. </p>
<p>지금 회사를 지원해 보세요. 부족하다고 느껴도, 일단 한번 가서 거절당해 보세요. </p>
<p>코딩테스트 떨어질 것 같으면 일단 지원해보세요. </p>
<p>면접 준비 제대로 못 했으면, 그래도 일단 봐 보세요.</p>
<p>하다 보면 점점 더 잘해지게 돼요. 실전을 해 보면서 느는 거죠. 저도 제가 처음에 봤던 면접보다 세 번째, 네 번째 보는 면접이 훨씬 더 잘 보더라고요. 연습 게임, 모의고사라고 생각하고 일단 지원은 꼭 해보세요.</p>
<h2 id="가고-싶지-않은-회사부터-지원하기">가고 싶지 않은 회사부터 지원하기</h2>
<p>여기서 팁은, 내가 &#39;가고 싶지 않은 회사&#39;부터 우선적으로 지원하는 거예요. 처음에는 잘 못 하니까 일단 가고 싶지 않은 회사를 상대로 연습을 하는 거죠. 혹시라도 붙으면 그때 가서 갈지 안 갈지는 여러분이 결정하면 되는 거고요.</p>
<h2 id="피드백-요청하기">피드백 요청하기</h2>
<p>일부러 거절 당해야 되는 곳이 또 하나 있어요. 바로 주변에 개발자를 같이 준비하는 <strong>동기나 부트캠프 선후배들</strong>입니다.</p>
<p>그 중에서 내가 보기에 잘하는 사람이 있을 거예요. 그 사람들한테 내 이력서나 내 프로젝트를 보여주고 피드백을 해달라고 꼭 부탁하세요. </p>
<p>회사를 지원해서 그냥 서류 탈락을 했다고 하면 왜 떨어졌는지 알 수가 없어요. 그러니까 피드백을 받을 수가 없죠. 그럴 때는 주변 사람들의 도움을 받는 게 좋아요.</p>
<p>제가 본 대부분의 사람들은 주변 사람들한테 생각보다 이런 피드백 요청을 잘 못 하더라고요. </p>
<p>&#39;일부러 거절 당하기&#39;를 여기다 적용해보면, <strong>여러분이 엄청 친한 관계가 아니더라도 거절 당할 것 같더라도 일단 한 번 부탁</strong>을 해보는 거예요. </p>
<p>장담하는데 여러분 생각보다 훨씬 더 많은 훌륭한 피드백을 받으실 거예요.</p>
<p>도움을 일방적으로 요청하는 게 아니라 서로 도와줄 수 있는 구조를 만들면 더 좋겠죠? 제가 예전에 올렸던 <a href="https://youtu.be/7mBU3GeOI8M?si=shA7jilRpXLh-NJS">&#39;뎁스터디&#39;</a>가 약간 그런 건데요. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/5783011e-df45-4854-93e1-dd27b720e38d/image.png" alt=""></p>
<p>영상으로 보기
👉 <a href="https://youtu.be/7mBU3GeOI8M?si=shA7jilRpXLh-NJS">https://youtu.be/7mBU3GeOI8M?si=shA7jilRpXLh-NJS</a></p>
<p>저도 부트캠프 동기들과 함께 했던 건데, <strong>서로 면접관이 되어서 질문을 해주고 서로서로 피드백</strong> 해주면서 되게 많이 늘었었어요.</p>
<p>이런 식으로 다른 사람들과 함께 할 기회를 어떻게든 만들어 냅니다. 피드백을 받고 그걸 개선해서 다음에 또 만나고, 이런 사이클을 만들어 보셔야 해요. </p>
<p>혼자서 완벽하게 준비하려고 하는 것보다 이게 훨씬 더 효율적입니다.</p>
<h2 id="마지막">마지막</h2>
<p>제 글에도 댓글로 의견을 남겨주시면 정말 감사하겠습니다. 어떤 점이 부족했는지, 어떤 콘텐츠를 보고 싶었는지 많은 피드백 주세요. 조금씩 개선해 나가겠습니다. 감사합니다!</p>
<hr>
<p>영상으로 보기
👉 <a href="https://youtu.be/KM-hXjrrwmo?si=89_fodUpSk5ePjCu">https://youtu.be/KM-hXjrrwmo?si=89_fodUpSk5ePjCu</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[멘탈이 건강해지는 가장 좋은 방법]]></title>
            <link>https://velog.io/@eddy_song/meditation</link>
            <guid>https://velog.io/@eddy_song/meditation</guid>
            <pubDate>Sat, 30 Dec 2023 13:43:43 GMT</pubDate>
            <description><![CDATA[<h1 id="내-인생을-바꿔준-습관">내 인생을 바꿔준 습관</h1>
<p>저는 2018년부터 지금까지 한 5년 정도 꾸준히 명상을 하고 있어요. 제 인생을 가장 크게 바꿔준 습관 3개 안에 드는 거 같아요. 기회가 있을 때마다 주변에 항상 명상을 추천하고 있습니다. </p>
<p>명상을 하면 뭐가 좋냐고요? 간단하게 말하면, 명상은 마음을 위한 운동이에요.</p>
<blockquote>
<p>(Calm 앱에서 명상한 기록)
<img src="https://velog.velcdn.com/images/eddy_song/post/27ab9063-b656-4bd8-be79-e7a7886f1143/image.png" alt=""></p>
</blockquote>
<h1 id="마음의-체력">마음의 체력</h1>
<p>누구나 스트레스를 받잖아요? 여러분도 이번 한 주만 생각해 보셔도 분명히 내 마음처럼 안 되는 것들, 날 화나게 하는 것들, 걱정되는 것이 있으실 거예요. </p>
<p>근데 모두가 그런 걸 겪을 때, 잘 살아가느냐 차이를 만드는 게 &#39;마음의 체력&#39;인 거 같아요. 몸의 건강, 체력이 중요하듯이 저는 이 &#39;멘탈&#39;, 마음의 체력이 인생을 살아가면서 너무 중요한 거 같습니다. </p>
<p>우리가 건강하고 멋있게 살기 위해서 운동을 하듯이, 마음이 건강하고, 멋있는 사람이 되기 위해서 하는 거죠.</p>
<p>명상이라는 방법은 최근에 과학적으로도 그 효과가 수없이 많이 입증됐습니다. </p>
<p>멘탈의 차이라는 것을 평소에는 잘 못 느낄 수 있지만, 어려운 일에 도전하고 계시는 분들한테는 정말 중요한 거 같아요. 왜냐면 우리가 뭔가를 이루려면 실패하고, 거절당할 수밖에 없고, 그럼에도 불구하고 꾸준하게 나아갈 수 있느냐가 중요한데 결국 그 차이는 이 정신적 체력에서 오는 거 같거든요.</p>
<p>그래서 입시, 취직, 이직, 이렇게 어려운 일을 하고 계시는 분들을 보면 저는 항상 명상을 추천하고 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[당장 해볼 수 있는 4가지 방법]]></title>
            <link>https://velog.io/@eddy_song/4-habits</link>
            <guid>https://velog.io/@eddy_song/4-habits</guid>
            <pubDate>Sat, 30 Dec 2023 13:28:58 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-해결형-개발자가-되려면">문제 해결형 개발자가 되려면</h1>
<p><a href="https://velog.io/@eddy_song/problem-solver">지난 글</a>에서 제가 회사 사람들에게 &#39;훌륭한 개발자는 어떤 개발자인가요?&#39;라고 물었는데요. 답을 종합해보니 팀원들이 같이 일하고 싶어하는 개발자와 그렇지 않은 개발자의 차이가 뚜렷하게 드러났죠.</p>
<p>스펙 구현형 개발자는 솔루션에 집중하기 때문에 &#39;아 그건 안 돼요&#39;라는 말을 많이 하게 되지만, 문제 해결형 개발자는 단순히 &#39;된다, 안 된다&#39;가 아니라 문제를 해결하는 것에 집중합니다. 그래서 &#39;이건 어떤 문제를 풀기 위한 건가요?&#39;라는 질문을 먼저 합니다.</p>
<p>문제 해결하는 개발자가 되어야 한다고 말하기는 쉽지만, 실제로 그렇게 변화하기는 어렵습니다. 커뮤니케이션은 마치 지금 여러분이 스마트폰을 보고 있는 자세처럼 몸에 배어 있는 것이고, 쉽게 고쳐지지 않습니다.</p>
<p>실제로 지속 가능한 변화를 만들기 위해서는 추상적인 말보다는 구체적이고 행동 가능한 습관이 필요합니다. 문제 해결형 개발자가 될 수 있는 <strong>좋은 습관 4가지</strong>를 고민해보았습니다.</p>
<h1 id="1-해결하려는-문제와-맥락에-대해서-먼저-묻는다">1. 해결하려는 문제와 맥락에 대해서 먼저 묻는다.</h1>
<p>첫번째 습관입니다. </p>
<p>요구사항에 대해서 들으면, 된다 안된다 말을 하기 전에 그것이 해결하려는 문제와 맥락에 대해서 먼저 묻는다. </p>
<p>스펙 구현형 개발자가 가장 많이 하는 실수는 문제에 대해서 생각해보지 않고 곧장 해결책으로 집중하는 건데요. 엔지니어로서는 항상 솔루션에 초점이 가는 본능이 있는 것 같아요. 그렇기 때문에 의도적으로 문제에 초점을 맞춰야 되는데요. </p>
<p>실전에서 이걸 해보는 방법은 간단합니다. 그냥 한 번 더 물어보면 돼요. 내가 당장 뭔가를 대답하고 싶은 욕구를 잠시 내려놓고요. 무조건 한 번 더 물어봅니다. </p>
<p>&#39;어? 이건 어떤 문제를 해결하는 것일까요? 어떤 의도와 맥락을 가진 것일까요?&#39; </p>
<p>재질문하는 것만으로도 공동의 목표와 문제로 초점을 좁힐 수가 있습니다.</p>
<h1 id="2-상대방의-말을-듣고-내가-이해한-바를-공유한다">2. 상대방의 말을 듣고 내가 이해한 바를 공유한다.</h1>
<p>여러분 그런 경험 하신 적 있을 거예요. </p>
<p>분명히 서로 같은 단어를 써서 말을 하는데, &#39;어? 저 사람 잘못 이해한 것 같은데? 쎄한데?&#39; 이런 느낌 드실 때가 있죠. </p>
<p>만약에 상세 화면에 대한 얘기를 하고 있고, 상대방도 상세화면에 대한 얘기를 하고 있는데 저는 상세화면이 시간대에 따른 내역을 보여주는 거라고 생각했는데 상대방은 추가적인 액션을 하는 그런 상세화면이라고 생각할 수도 있는 거고요. 왜냐하면 사람들은 같은 단어를 보고도 서로 다르게 이해할 수 있기 때문이에요. </p>
<p>커뮤니케이션을 잘 하는 사람들은 내가 이 단어를 썼다고 해서 당연히 저 사람도 이렇게 이해했겠지라는 가정을 잘 하지 않아요. </p>
<p>이걸 싱크하는 가장 좋은 방법이 상대방의 말을 듣고 내가 이해한 바를 한번 요약해서 되물어 보는 거예요. </p>
<p>저는 이런 말투를 많이 써요. &#39;제가 이해한 바로는 이러한 이러한 거라고 이해를 했는데, 이 내용이 맞을까요?&#39;라고 하면서 다시 물어보곤 해요. 이게 내가 이해한 게 맞으면 상대방이 나에 대한 신뢰도가 올라가고, 만약에 내가 이해한 게 좀 틀렸으면 앞으로의 비효율을 막을 수 있으니까 굉장히 좋은 거고요.</p>
<h1 id="3-안-되는-이유-대신-상대방-관점에서-대안을-제시한다">3. 안 되는 이유 대신, 상대방 관점에서 대안을 제시한다</h1>
<p>개발자로 일하다 보면 종종 &#39;이거 왜 안 돼요?&#39; 같은 질문을 받게 되잖아요? 이때 대부분은 기술적인 설명으로 대답하게 되죠. 예를 들어, &#39;기술적으로 어려워서요&#39;, &#39;이 DB가 분리되어 있어서...&#39; 이런 식으로 말이죠. </p>
<p>하지만 사실은, 다른 팀원들, 특히 다른 직군 사람들이 진짜 알고 싶어하는 건 그게 기술적으로 왜 어려운지가 아니에요. 그들은 이 문제를 해결할 다른 방법이나, 그들이 해야 할 행동이 무엇인지가 궁금한 거죠.</p>
<p>그래서 개발자로서, 어떤 이유를 설명하려고 할 때 복잡하게 돌아가지 말고, 바로 핵심을 짚어요. &#39;이 문제가 어떤 제약 조건 때문에 어렵다&#39;고 말하고, &#39;그럼 이 제약 조건을 좀 더 줄일 수 있는 다른 방법은 뭐가 있을까요?&#39;, &#39;이걸 어떻게 우회할 수 있을까요?&#39; 이렇게 대화를 이어가 보세요. </p>
<p>이렇게 하면, 대화가 훨씬 쉽게 풀린다는 걸 알게 될 거예요. </p>
<p>중요한 건, &#39;어렵다&#39;는 걸 납득시키려는 게 아니라, 대안에 집중하는 거예요. 왜냐하면, 우리가 해야 할 일은 그냥 스펙을 구현하는 게 아니라, 문제를 해결하는 거니까요.</p>
<h1 id="4-문제를-해결할-또-다른-방법은-없을지-고민해본다">4. 문제를 해결할 또 다른 방법은 없을지 고민해본다</h1>
<p>개발을 하다 보면 항상 딜레마에 빠지게 됩니다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/e0a2ff4d-0635-48cc-bf84-3f373826db54/image.jpeg" alt=""></p>
<p>예를 들어, 로그인하는 동안 외부 API를 써서 인증을 구현하는데, 응답이 너무 늦게 온다고 가정해볼게요. 사용자 입장에서는 인증하는데 시간이 오래 걸리니 이탈하게 되겠죠. 인증 API를 다른 걸로 바꾸거나 직접 구현하면 몇 개월의 개발이 들어가는 상황입니다. 그래서 &#39;이거 인증 빠르게 할 수 없어요?&#39;라는 질문에 &#39;안 돼요&#39;라고 답하고 싶어집니다.</p>
<p>하지만 이 딜레마를 해결하는 실제 방법이 있었어요. 순서를 바꿔서, 인증 응답이 오기 전에 다음 화면으로 넘어가고, 그 다음에 인증 응답이 와서 결과를 보고, 필요한 게 있으면 추가적인 화면을 진행하거나 그냥 통과시켜주는 거였죠. </p>
<p>이렇게 되면 대부분의 사람들은 로딩을 기다리지 않고 로그인을 끝낼 수 있어요.</p>
<p>이건 제가 일하는 회사에서 실제로 있었던 사례인데요, 여기서 말씀드리고 싶은 건, 충분히 고민을 해보면 &#39;한다/안 한다&#39;라는 것 말고도 세상엔 많은 해결책이 있다는 겁니다. 개발자가 문제 해결을 하는 사람이라고 생각한다면, 단순히 &#39;한다/안 한다&#39;의 사고에 갇히지 말아야 해요.</p>
<p>예를 들어, &#39;버튼을 추가하면 유저는 편하지만 개발자의 리소스가 많이 든다&#39;라고 할 때, 섣불리 결론을 내지 않고 &#39;유저가 편하면서도 개발자의 공수가 적게 드는 방법은 없을까?&#39; 한 번 더 고민해보는 거죠. 이런 마인드를 가진 사람들은 새로운 요청 사항이 들어왔을 때 &#39;아 그건 안 돼요&#39;가 아니라 &#39;혹시 다른 방법은 없을까요?&#39; &#39;이런 건 어떨까요?&#39;라는 말이 나오게 됩니다.</p>
<p>중요한 것은 빨리 결론을 내지 않고, &#39;좀 다른 방법이 없을까?&#39;라고 생각을 해보는 거예요.</p>
<h1 id="요약-정리">요약 정리</h1>
<p>마지막으로 습관 네 가지를 정리해볼게요.</p>
<ol>
<li><p>개발 스펙과 관련된 질문, 요청을 들었을 때 바로 답을 하는 대신에, 이 <strong>요구사항이 해결하는 문제와 의도, 제약 조건</strong>을 먼저 물어봅니다.</p>
</li>
<li><p>상대방의 말을 듣고 나서 바로 내 답을 얘기하는 대신에,** 상대방의 말을 이해한 것을 한 번 더 공유**합니다.</p>
</li>
<li><p>상대방의 해결책이 어렵다고 생각될 때, 안 되는 이유를 납득시키는 대신에, <strong>제약을 덜 받는 다른 방향성이나 대안을 제시</strong>합니다.</p>
</li>
<li><p>하느냐, 안 하느냐의 딜레마 상황이라고 느껴질 때, &#39;아, 이건 안 될 것 같다&#39;라고 단정하는 대신에, <strong>둘 다 만족시킬 수 있는 다른 방법은 없을까</strong> 한 번 더 고민해 봅니다.</p>
</li>
</ol>
<p>문제 해결형 개발자라는 것은 그렇게 거창한 것이 아니에요. </p>
<p>여러분들이 지금 개발을 하고 계신다면, 제가 방금 말씀드린 그 순간들이 분명히 있으실 거고요. </p>
<p>그때 본능적으로 나오는 행동 대신에, 오늘 말씀드린 습관을 한 번이라도 시도해보신다면, 그런 하루하루가 작지만 쌓여서 어느새 다른 팀원들이 너무나 같이 일하고 싶어하는 개발자가 되어있을 거라고 확신합니다. </p>
<hr>
<p>영상으로 보기
👉 <a href="https://youtu.be/yWwMM5Lnqhg?si=G5b2iSFio3oLz77m">https://youtu.be/yWwMM5Lnqhg?si=G5b2iSFio3oLz77m</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA['안 돼요'라고 말하지 않는다]]></title>
            <link>https://velog.io/@eddy_song/problem-solver</link>
            <guid>https://velog.io/@eddy_song/problem-solver</guid>
            <pubDate>Sat, 08 Jul 2023 10:56:30 GMT</pubDate>
            <description><![CDATA[<p>저는 회사에 입사하고 나서 주변에 이런 질문을 되게 많이 했어요.</p>
<blockquote>
<p>00님이 보시기에 이 사람 진짜 훌륭한 개발자다, 이런 사람이 있었나요?</p>
</blockquote>
<p>궁금하잖아요. </p>
<p>근데 디자이너나 PM이나 QA나 이런 분들한테 물어보면 다들 비슷한 포인트를 얘기하시더라고요</p>
<p>&#39;바로 커뮤니케이션이 잘 된다&#39;, &#39;말이 잘 통한다&#39;라는 거였어요</p>
<p>제가 생각했을 때 훌륭한 개발자, 슈퍼 개발자라고 하면 진짜 한 달에 걸릴 기능을 하루 만에 해내고, 되게 Low-level까지 아는 그런 이미지였거든요.</p>
<p>근데 같이 일하는 팀원들의 관점에서는 그게 아니더라고요.</p>
<p>사실 그분들한테는 제일 중요한 게 커뮤니케이션 능력이에요.</p>
<p><strong>말이 잘 통하고 협업이 잘되는 사람이 그들한테 훌륭한 개발자</strong>인 거죠.</p>
<p>어떤 분은 &#39;이 회사에 그런 (커뮤니케이션 잘하는) 개발자가 많아서 자기는 이 회사에서 계속 일하고 있다&#39; 라는 말까지 하시더라고요.</p>
<p>생각보다 개발자들 본인들한테 물어도, 다른 개발자가 좋은 개발자일지를 판단할 때 다른 직군과 커뮤니케이션 능력을 거의 1순위로 뽑으시더라고요</p>
<h1 id="커뮤니케이션-잘하는-개발자가-뭔데">커뮤니케이션 잘하는 개발자가 뭔데..?</h1>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/fc0a341b-82dd-48bf-954e-1e6c4f5554d1/image.png" alt=""></p>
<p>그런데 말이죠. 저는 여기서 약간의 의문을 가졌습니다.</p>
<p>사실 &#39;커뮤니케이션&#39;이라는 건 굉장히 넓잖아요. 다들 커뮤니케이션이라고 퉁쳐서 말을 하는데 서로 다 다른 걸 얘기하고 있는 건 아닐까?</p>
<p>말을 잘 하는 것부터 해서, 정보 수집을 잘하는 것, 다른 사람들한테 공감을 잘해주는 것, 복잡한 내용을 정리하는 것 등등 &#39;커뮤니케이션&#39;이라는 말이 굉장히 다양한 상황과 능력을 다 포함한단 말이죠.</p>
<p>나름 제가 전직 기자로서 커뮤니케이션에 대한 관심이 많은 사람이거든요.</p>
<p>근데 개발자로서 커뮤니케이션을 잘한다는 것이 도대체 무엇인가, 좀 더 구체화할 수는 없을까?</p>
<p>갑자기 기자 정신이 올라오더라고요. 회사를 돌아다니면서 물어보기 시작했어요</p>
<p>대표부터 해서 디자인 리드, 프로덕트 리드 데이터 분석가, 사업개발 QA 엔지니어 등등..</p>
<p>다들 연차가 꽤 있으시고 개발자하고 긴밀하게 일한 경험들이 있는 분이었어요.</p>
<blockquote>
<p>어떤 사람이 커뮤니케이션을 잘하는 개발자예요? 개발자랑 일하기 진짜 힘들었을 때가 언제예요?</p>
</blockquote>
<p>다들 개발자하고 일하면서 힘들었던 경험이 다 하나씩은 있으시더라고요.</p>
<p>이분들이 일하고 싶은 개발자와 아닌 개발자의 얘기를 들어본 결과 어떤 공통점이 보였어요. 어떤 기본 전제가 있더라고요.</p>
<p>그게 뭐였을까요?</p>
<h1 id="문제-해결형-개발자">문제 해결형 개발자</h1>
<p>커뮤니케이션을 잘하는 개발자의 공통점은 &#39;안 된다&#39;라는 말을 그냥 하지 않는다는 거예요.</p>
<p>디자이너가 버튼을 이쪽에서 이쪽으로 &#39;옮기고 싶다&#39;라고 말했을 때 &#39;아 그거는 구조상 안 돼요&#39; 이렇게 말하지 않아요.</p>
<p>&quot;그럼 뭐 개떡 같은 요구사항이 와도 된다고 해야 되는 거야?&quot; 라고 오해할 수가 있는데요. 그들이 예스맨이라는 얘기가 아닙니다. 이상한 요구를 다 받아준다는 얘기가 아니에요.</p>
<p>다만 그 실제로 버튼을 옮기는 게 말도 안 되게 어렵다고 해도 그들은 안 된다고 말하는 게 아니라 다시 물어보는 거죠.</p>
<p>이게 풀려고 하는 문제가 무엇인지? 아 그렇다면 지금 버튼은 이런 이유로 어려우니까 그 문제를 해결하기 위해서
이런 이런 솔루션 어때요? 라고 제안한다고 하더라고요</p>
<p>그들이 안 된다는 말을 안 하는 이유는 &#39;안 되는 그것&#39;이 핵심이 아니라는 거죠.</p>
<p>요구받은 그 상황을 구현 하는 게 쉽냐 어렵냐, 이게 아니라 그걸 가지고 정말 고객과 사업의 문제를 풀 수 있느냐 집중을 하는 거죠.</p>
<p>그래서 어떤 스펙을 받았을 때 된다 안 된다보다는 그 의도와 맥락을 이해해서 더 좋은 스펙을 만들어 내려고 합니다. </p>
<p>이런 특징을 가진 개발자를 저는 &#39;문제해결형 개발자&#39; 라고 부르려고 해요.</p>
<h1 id="스펙-구현형-개발자">스펙 구현형 개발자</h1>
<p>&#39;문제 해결형&#39;의 반대는 무엇일까요. 이거는 &#39;스펙 구현형&#39; 개발자 라고 이름을 붙여 봤어요.</p>
<p>말 그대로 주어지는 스펙을 구현하는 것에 초점을 맞추는 게 스펙 구현형 개발자예요.</p>
<p>저희 QA님이 얘기를 해 주신 사례인데요.
이 분이 이제 입사한지 얼마 안 됐을 상태였는데 로그를 심어야 되는 상황이었어요</p>
<p>이 분이 로그랑 파라미터를 정의해 가지고 개발자한테 전달했는데 개발자가 댓글로</p>
<blockquote>
<p>아 그거는 스트림에서 비동기로 받아 온 거라서 서버 api 구조를 바꾸지 않으면 이 화면에서 찍는 거는 안 된다</p>
</blockquote>
<p>이런 식으로 답을 딱 한 거예요. 거기서 그냥 쓰레드가 끝났대요.</p>
<p>이 분이 멘붕이 온 거예요.</p>
<blockquote>
<p>비동기? 스트림? API?
아니 나는 이거 로그 분석할 때 필요한 데 그럼 이거 어떻게 해야 되지?</p>
</blockquote>
<p>그냥 안 된다고만 하니까 되게 힘들었다고 하시더라고요. 너무 당연한 듯이 말하니까 이게 물어보기도 힘들었대요.</p>
<p>저는 이걸 듣고 그 개발자의 심리는 뭐였을까, 그런 생각을 해봤어요. 근데 아마 이런 이런 거지 않을까 싶어요.</p>
<p>나는 엔지니어니까 나한테 주어진 스펙을 만들어내고 디버깅하고 테스트해서 버그가 없도록 하는 게 임무인 거죠.</p>
<p>은연중에 요구사항은 구체화시켜서 가져와야지. 요구사항을 제대로 만드는 거는 기획자나 디자이너가 할 일이고 나는 구현할 사람이잖아. 라는 생각을 갖고 있는 거죠</p>
<p>그러다 보니까 버튼 옮기는 게 그렇게 쉬운 게 아니다, 그거는 비동기 스트림에서 받아오는 거라 안 된다, 하고 그냥 끝나버리는 일이 발생하는 거죠.</p>
<p>저는 그 개발자가 정말로 이기적이고 빌런이라기 보다는 그냥 시야가 좁은 경우가 많지 않을까 해요.</p>
<p>일단 지금 많은 일이 밀려 있는데 빨리 그걸 내가 쳐내야 되는 게 내 문제고 그걸 잘 구현하는데 집중을 하려 하니까, 상대방의 문제나 입장까지는 생각을 못하는 거죠</p>
<p>저도 생각해 보면은 아직 스펙 구현형 개발자에 가까운 거 같아요. 일단 제가 구현을 어떻게 해야 될까 에 대한 고민을 많이 하다 보니까 진짜로 이게 해결하고자 하는 어떤 문제에 대해서는 생각을 잘 못하더라고요. </p>
<p>아직 좀 시야가 좁은 거죠.</p>
<h1 id="되게-만들려는-태도">되게 만들려는 태도</h1>
<p>근데 문제해결형 개발자는 초점이 다릅니다.</p>
<p>디자인 리드 분이 해주신 얘긴데 그대로 옮겨 볼게요</p>
<blockquote>
<p>소통이 안 되는 개발자는 목표가 아닌 수단에 집중하시는 분들이었던 기억이에요. 
예를 들어서 &#39;사용자가 구매를 편하게 하기 위해 버튼 위치를 여기로 옮기려고 하는데 어떨까요?&#39; 라고 하면
&#39;그 코드는 고치기 어려워요&#39; 대답을 하는 거죠
이런 대답을 들으면 디자이너는 힘이 빠지게 돼요. 상대방이 버튼이라는 수단에 집중하고 있으니까요.</p>
</blockquote>
<blockquote>
<p>근데 소통이 잘 되는 개발자는 &#39;구매를 더 편하게 한다&#39; 라는 목표에 집중을 해서 &#39;여기 코드는 바꾸기 어려운데
대신 이건 어떨까요?&#39; 라고 논의가 이어져요. 실제로 그 제안이 맞고 틀리고를 떠나서 안 된다 어렵다 바쁘다 등의 부정적인 태도가 아닌 어떻게든 되게 만들려는 태도가 중요한 거 같아요.</p>
</blockquote>
<blockquote>
<p>그런 태도가 느껴지는 분들은 실제로 일이 잘 안 되거나 구현이 오래 걸리더라도&#39;아 이 사람과 함께라면 어떻게든 문제를 해결할 수 있겠다&#39; 라는 상호신뢰가 쌓이게 돼요</p>
</blockquote>
<p>이렇게 말을 해 주셨는데, 저는 <strong>커뮤니케이션 잘하는 개발자는 구현을 잘 못하거나 일이 잘 안 되더라도 결국에는 신뢰를 쌓게 된다</strong>는 말이 되게 인상 깊더라고요.</p>
<h1 id="문제를-보는-시야">문제를 보는 &#39;시야&#39;</h1>
<p>또 다른 얘기가 있는데 지금 제품팀 리더로 일하는 분이 해주신 얘기예요.</p>
<blockquote>
<p>그런 (스펙 구현형) 개발자와 일하면 어려운 점이 내가 일을 다 구체화해서 갖다 줘야 된다는 압박이 있어요. 팀을 끌어가는데 있어서 상당한 부담이죠. 내가 정말 스펙을 아랫단계까지 정의하지 않으면 그분들은 어떤 것이 문제이고
어떤 것이 우선순위인지 판단해서 일하는 능력이 아직 없으니까.</p>
</blockquote>
<blockquote>
<p>근데 믿을만한 (문제 해결형) 개발자는 그 &#39;시야&#39;란 게 있어요. 불확실한 문제와 맥락을 전달을 해도 우리 팀의 우선순위, 리소스 같은 걸 보고 문제를 해결할 수 있는 스펙을 직접 만들어 낼 수 있는 사람인 거죠. 그럼 리더는 너무나 편하죠.</p>
</blockquote>
<blockquote>
<p>개발로만 문제를 푸는 게 아니예요. 자기가 하기 좀 그렇다면 다른 팀한테 도움을 요청 하기도 하고요. 중요하지 않다면 그냥 안 할 수도 있고요. 그런 걸 보면 &#39;헛일을 하지 않을 사람이구나&#39; 라는 생각이 들고, 그런 개발자 한 명이
팀에 있고 없고가 엄청난 차이를 만들어요.</p>
</blockquote>
<p>요런 말을 해 주셨는데, 저는 요 얘기를 들으면서 딱 떠오르는 게 있었는데요.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/4dc9b480-c327-40da-942c-7d2b1b58c1e4/image.jpeg" alt=""></p>
<p>혹시 유튜브에서 배달의 민족 김범준 전 대표가 인터뷰한 영상 보셨나요?
안 보셨으면 꼭 한번 보세요. 아니 두번 보세요. </p>
<p>거기 이런 말이 나와요.</p>
<ul>
<li>개발자는 코딩 실력도 굉장히 중요하지만 그보다 더 중요한 것은 문제 해결력이다</li>
<li>가장 좋은 방법은 프로그래밍 하는 것이 아니라 정책을 바꾸는 것일 수도 있다.</li>
<li>문제를 해결하기 위한 노력 중 80%는 우리가 풀고자 하는 문제가 무엇인지 정확히 이해하는데 투자해야 한다.</li>
</ul>
<p>저는 그 인터뷰가 제가 인터뷰했던 리더들의 생각하고 너무 맞닿아 있어서 되게 신기하더라고요</p>
<p>개발자는 코딩하는 기술자가 아니라 문제를 해결하는 사람이라는 거.
그렇기 때문에 그냥 &#39;안 돼요&#39;라는 말을 하지 않는다는 거.</p>
<h1 id="문제-해결형-개발자로-성장하기">문제 해결형 개발자로 성장하기</h1>
<p>물론 주니어 개발자로서는 솔직히 스펙 구현형 개발자에서 시작하게 될 수밖에 없다고 생각을 해요.</p>
<p>말이 스펙 구현이지, 개발이라는 게 뭐 쉬운 일이 아니잖아요.</p>
<p>하지만 점점 더 연차가 쌓이고 숙련도가 쌓이게 되면, 관점을 바꿔서 문제 해결형 개발자로 가려는 노력을 해야 되는 거 같아요.</p>
<p>내가 새로 나온 스택을 사용할 줄 알고, 코드를 클린하게 짜는 것도 좋지만 결국에 가치있고 희소한 개발자는 회사의 문제를 고민하고 해결하는 사람이라는 거죠. </p>
<p>그래야 단순히 연차만 높은 개발자가 아닌 진짜 시니어 개발자, 테크 리드가 되는 거 같아요.</p>
<p>근데 저도 아직은 햇병아리라서, 그저 스펙을 구현하기에 벅찬 개발자인데요.</p>
<p>이런 말을 들으면 맞는 말이고, 공감은 되는데 실제로 내가 문제 해결형 개발자로 성장하려면 어떻게 해야돼? 라고 하면 사실 저도 잘 모르겠더라고요.</p>
<p>여러분이 생각하기에 스펙 구현형 개발자에서 문제 해결형 개발자로 진화하려면 어떻게 해야한다고 생각하시는지 댓글로 달아주시면 큰 도움이 될 거 같습니다.</p>
<p>좀 더 고민해서 다음번에는 구체적인 실천 아이템들을 정리해서 가지고 와볼게요.</p>
<p><a href="https://youtu.be/fe6_wCixJwE">https://youtu.be/fe6_wCixJwE</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[전략을 짜지 말자]]></title>
            <link>https://velog.io/@eddy_song/no-strategy</link>
            <guid>https://velog.io/@eddy_song/no-strategy</guid>
            <pubDate>Sat, 06 May 2023 13:52:57 GMT</pubDate>
            <description><![CDATA[<p>부트캠프는 1월에 시작해서 6월에 끝났는데요.
5월, 6월 이때부터 이곳저곳 지원을 했습니다.</p>
<p>그때까지 제대로 된 포트폴리오도 없었고 코딩테스트 중간 난이도도
잘 못 풀었어요.</p>
<p>아직 이르단 느낌도 있었지만 그래도 경험을 쌓을 겸 일단 넣어봤습니다.</p>
<p>면접도 보다보면 는다고 하니까.</p>
<h1 id="할-게-너무-많다">할 게 너무 많다</h1>
<p>와 근데 진짜 우수수 떨어지더라고요.
불합격. 불합격. 불합격. 불합격.</p>
<p>두 달간 열 몇 곳 정도 지원을 했는데 코테 통과하고 면접에 간 회사는 하나도 없었어요.</p>
<p>에이, 떨어져도 돼 하면서 패기있게 지원했는데 막상 떨어지니까 진짜 괜찮지는 않더라고요</p>
<p>이게 점점 마음이 급해져요.</p>
<p>내가 아직 부족하구나.
이런 걸 더 해야 되나?
저런 걸 되야 되나?
이력서 고쳐야 되는데 언제 고치지?
프로젝트도 더 해야 될 것 같은데 내가 정말 최선을 다하고 있나?</p>
<p>제가 정한 기준에 제가 못 미치는 것 같더라고요.
이때 자존감이 정말 쭉쭉 바닥으로 빠졌어요.
심지어 이때는 사람 만나는 것도 싫더라고요.</p>
<p>요즘 어때? 물어보면 내 상황을 설명해야 되니까요.</p>
<p>또 이때 제가 입에 달고 산 말이 있는데요</p>
<blockquote>
<p>&#39;해야 할 게 너무 많다&#39;</p>
</blockquote>
<p>마음은 급한데 내 눈앞에 해야 될 게 너무 많은 거예요</p>
<p>이게 왜 그러냐면요. 개발을 배우고 어느 정도 단계에 진입하면 내가 모르는 게 폭발적으로 늘어나는 시기가 있어요.</p>
<p>아는 게 아니고 모르는 게 늘어나요. 왜냐면은 이전에는 보이는 게 많이 없으니까 모른다는 거를 모르잖아요.</p>
<p>근데 지식이 늘어나면서 모른다는 것을 알게 돼요. 아는 게 늘어나는 속도보다 모른다는 걸 알게 되는 속도가 더 빠른 거예요.</p>
<p>공부를 해도 자신감이 점점 쌓이는 게 아니고 압도감이 생기는 거죠.</p>
<blockquote>
<p>이거 언제 다 하냐
할 거 너무 많다</p>
</blockquote>
<p>이러면서 스트레스가 쌓였어요</p>
<p>근데 그때 누가 저를 보더니</p>
<blockquote>
<p>형 그거 너무 강박 증상인데?</p>
</blockquote>
<p>이러는 거예요. </p>
<p>머리가 띵- 하더라고요</p>
<p>제가 마음이 급하고 압도감을 느끼고 있으면서 제가 실제로 어떻게 느끼고 있는지 스스로는 인식하지 못 하는 거죠.</p>
<p>그래서 제 3자의 시선으로 관찰하려고 해봤어요.</p>
<p><strong>왜 이런 감정이 일어날까?</strong></p>
<h2 id="첫째-모든-걸-다-잘해야-한다는-집착">첫째, 모든 걸 다 잘해야 한다는 집착</h2>
<p>내가 적어도 앱 개발에 관해서는 모든 영역을 할 수 있어야 개발자가 될 수 있다는 집착이 있었어요.</p>
<p>근데 막 취업 준비하면 모바일 개발자 로드맵 프론트 개발자 로드맵 이런 게 있잖아요.</p>
<p>여기 보면 내가 모르는 엄청나게 많은 기술이 있어요.</p>
<p>거기서 유튜브 보면은 요즘에는 선언형UI 알아야 되고.. 크로스플랫폼이 뜨는 추세고.. 그럼에도 불구하고 본질은 컴퓨터 공학... 기초가 중요하고...</p>
<p>이런 것들을 듣게 되거든요? </p>
<p>이걸 다 해야 된다고 생각하니까 골이 너무 아픈 거예요.</p>
<p>근데 개발자가 된다는 건 막 과목별로 점수를 매기는 그런 자격증시험이 아니거든요.</p>
<p>제가 지금 확신하는 건데 신입 개발자가 &#39;앱 개발자에게 필요한 기술, 지식&#39; 이거를 절-대 전부 다 잘할 수가 없어요.</p>
<p>그리고 더 중요한 건 다 잘할 &#39;필요&#39;가 없어요.</p>
<p>대부분의 회사들이 신입 개발자를 뽑을 때는 </p>
<blockquote>
<p>&#39;흠 이 사람 앱 개발 A부터 Z까지 다 할 수 있어?&#39;</p>
</blockquote>
<p>이런 거 안 봐요.</p>
<p>왜냐하면 자기도 A부터 Z까지 모르거든요.
그때 그때 필요하면 처음 보는 거라도 해결하는 거예요.</p>
<p>대신 면접보는 사람들은 이 사람이</p>
<blockquote>
<p>지금은 A밖에 몰라도 얼마나 더 성장할 잠재력이 있는가
얼마나 문제를 해결할 수 있는가</p>
</blockquote>
<p>를 보는 거죠.</p>
<p>그래서 얼마나 넓게 하느냐가 별로 중요하지 않아요 오히려 깊이가 중요한데요.
(이건 나중에 따로 얘기해 볼게요)</p>
<h2 id="둘째-전략을-짜려는-집착">둘째, 전략을 짜려는 집착</h2>
<p>저는 계획이나 전략을 많이 짜는 성격이에요</p>
<p>일상에서는 뭐 그 정도는 아닌데 제가 막 커리어를 걸고 지금 모험을 하고 있다고 생각하니까 실패하면 안 될 것 같았어요.</p>
<p>그래서 막 머릿속에서 전략을 엄청 짜는 거예요.</p>
<blockquote>
<p>내가 잘못 가고 있는 건 아닌가
이 길이 맞나
최선의 길로 가고 있나</p>
</blockquote>
<blockquote>
<p>이렇게 많은 것 중에 뭐부터 해야 되지?
이게 더 중요한가? 
알고리즘을 더 해야 되나? 프로젝트를 해야 되나?</p>
</blockquote>
<p>이런 생각을 막 하면서 어떤 목표로 향하는 최적의 경로, 빠른 길을 찾으려고 했어요.</p>
<p>근데 소프트웨어 개발이라는 게 그렇게 뭐가 쉽게 보이는 크기가 아니거든요. 진짜 거대한 광야에요.</p>
<p>저는 거기서 장거리 달리기를 하고 있는 건데 심지어 코스도 안 정해져 있어요.</p>
<p>앞에 수많은 갈림길이 있고, 그 갈림길은 안 보이는 부분, 불확실한 부분이 진짜 많아요. </p>
<p>이 길이 어디로 이어진 지 알 수가 없다는 거죠</p>
<p>상상을 해보세요. 여러 코스가 앞에 펼쳐져 있는데 막 나침반하고 지도를
꺼내가지고 보면서. 어떻게든 내가 제일 빠른 길로 가고 있는지 아닌지 이걸 계속 확인하느라고, 오히려 가지를 못하고 그 앞에 멈춰 있는 거에요.</p>
<p><strong>어차피 뭔 길로 가든 마라톤 이거든요?</strong></p>
<p>근데 뭔가 빠른 길을 찾으려고 전략을 짜면서 오히려 제 속도는 느려지고 바닥에 주저앉게 되는 거죠.</p>
<p>내가 이런 생각을 했었구나. 
정리 해보니까 객관적으로 제 정신 상태가 보이더라고요.</p>
<p>그때부터 어떻게 했냐 &#39;시야를 좁혔어요&#39;.</p>
<h2 id="전략을-짜지-말자">전략을 짜지 말자</h2>
<p>물론 마음속에 전략을 짜려는 충동이 들지만 참았습니다. 일단 &#39;눈 앞에 있는 거 딱 한 번만 보자&#39; 생각했어요.</p>
<p>그래서 뭔가 머릿속이 복잡해질 때마다 제가 해야하는 거 딱 하나만 정했어요.
일단 이거부터 치자.</p>
<p>이렇게 하면은 하나 치고 나서 오히려 에너지가 생기더라고요.</p>
<p>앞으로 나아가는 느낌?</p>
<p>물론 여전히 쉬운 건 아닌데 압도당해서 주저앉는 게 좀 줄어들더라구요</p>
<p>이렇게 그냥 떨어지든 말든 &#39;그냥 눈 앞에 있는 거 하나만 하자.&#39; 생각하면서 하다 보니까 어느 순간 기대도 하지 않았을 때 갑자기 합격 소식이 오더라고요.</p>
<p>근데 저는 출시해본 앱도 하나도 없었고 혼자 한 프로젝트도 없었고 코테도 잘 못했거든요.</p>
<p>전략적인 관점에서 보면 한참 멀었던 건데 오히려 포텐셜을 보고 뽑아 주시더라고요.</p>
<p>천생 문과로서 기자 일을 하다가 어떻게 개발자가 되기로 마음 먹었는지 그 이후 어떤 과정을 겪고 개발자로 일하게 됐는지 말씀드렸는데요.</p>
<p>제 감정이나 걱정, 생각 그리고 그걸 어떻게 극복했는지 얘기를 훨씬 더 많이 한 거 같아요.</p>
<p>왜냐면 그게 가장 중요하다고 생각하니까요.</p>
<p>무슨 기술을 배웠고, 면접은 어떻게 봤고, 회사는 어디 지원했고, 이런 것도 중요하지만... </p>
<p>결국 그 중에서 가장 중요한 거는 <strong>꺾이지 않는 멘탈이더라고요</strong></p>
<p>흔해 빠진 말일 수도 있지만 저는 그렇게 생각을 해요.</p>
<p>전략보다 여러분의 멘탈이 꺾이지 않는 게 더 중요합니다.</p>
<p>제 얘기가 거기에 조금이나마 도움이 되었으면 좋겠고요.
여기까지입니다. 감사합니다.</p>
<p><a href="https://youtu.be/kcfi8-YTZEE"><img src="http://img.youtube.com/vi/kcfi8-YTZEE/0.jpg" alt="Video Label"></a></p>
<p><a href="https://youtu.be/kcfi8-YTZEE">https://youtu.be/kcfi8-YTZEE</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[부트캠프는 학원이 아니었고, 개발은 자격증 시험이 아니었다.]]></title>
            <link>https://velog.io/@eddy_song/on-my-own</link>
            <guid>https://velog.io/@eddy_song/on-my-own</guid>
            <pubDate>Mon, 01 May 2023 13:38:42 GMT</pubDate>
            <description><![CDATA[<p>22년 1월. 드디어 바라던 부트캠프에 입성합니다.</p>
<p>그치만 초반 2개월은 정말 고난의 연속이었어요. 
왜 힘들었냐?</p>
<p>2가지였던 거 같아요.</p>
<p>첫번째, 어? 왜 이렇게 빠르지?
두번째, 어? 왜 이렇게 아무런 가이드가 없지?</p>
<h1 id="어-왜-이렇게-빠르지">어? 왜 이렇게 빠르지?</h1>
<p>첫번째부터 말씀드리면. </p>
<p>제가 다녔던 부트캠프의 경우, 처음 들어가면 백엔드든, 프론트엔드든, 모바일이든 먼저 공통 과목을 들었어요.</p>
<p>‘컴퓨터 공학’인데요.</p>
<p>네. 근본있는 개발자라면 꼭 배워야한다는 바로 그 유명한 ‘전공 지식’이죠.</p>
<p>이제부터는 편하게 그냥 CS라고 부를게요.</p>
<p>한 10주 동안 CS 기초를 빠르게 배웠어요.</p>
<p>‘아니 대학교에서 4년 동안 가르치는 걸 10주만에 배운다고?’</p>
<p>놀랍게도 맞습니다.
당연히 대학교에서처럼 강의를 하는 건 아니고요.
과제 위주로 빠르게 진행이 돼요.</p>
<p>만약 메모리를 배운다면,
OS의 메모리 할당을 따라하는 프로그램 만들기.</p>
<p>인프라를 배운다면,
도커를 설치하고 원리 설명해보기.</p>
<p>네트워크를 배운다면,
간단한 HTTP 소켓을 직접 구현해보기.</p>
<p>요런 거죠.</p>
<p>근데 그전까지 저는
겨우 이차원 배열 사용해서 별 모양 만들어본 
그런 수준이었거든요?</p>
<p>갑자기 과제가 너무 어려운 거예요.</p>
<p>게다가 이 과제를 하는데 이틀을 줬어요. </p>
<p>과제를 보고, 어 이게 뭐지? 하고 벙쪄있으면, 이틀 뒤에 다음 주제로 넘어가는 거죠.</p>
<p>정신없이 털리고 있는데... 그 와중에 다른 사람들은 별로 질문이 없더라고요?</p>
<p>뭔가 과제 이미 제출한 사람도 있는 거 같고…</p>
<p>이거 CS가 근본이라던데,  역시 나 근본으로 들어가니까 안 되나? 이 생각이 들더라고요.</p>
<h1 id="어-왜-아무-가이드도-안-주지">어? 왜 아무 가이드도 안 주지?</h1>
<p>두번째, 어? 왜 아무 가이드도 안 주지?</p>
<p>부트캠프의 진행 방식이 굉장히 자율적이었어요.</p>
<p>이번주에 해야할 과제랑, 
그걸 어떻게 만들었나 공유하는 회고 시간.</p>
<p>거의 요 정도만 정해져있더라고요?</p>
<p>어떻게 해야하는지 단계별로 알려준다든가,
어떤 도구를 써서 하라든가 이런 게 거의 없어요.</p>
<p>일단 멘땅에 헤딩해봐, 하고 던져놓는 느낌?</p>
<p>다른 동기들도 이걸 당황스러워하더라고요.</p>
<p>그냥 주고 해보라고 하니까.</p>
<p>이걸 어떻게 접근하는 게 맞는 거지?</p>
<p>이거 다 못할 수가 없을 거 같은데, 어디까지 풀어내야 되지?</p>
<p>이런 게 되-게 막막하고, 쉽지 않더라고요.</p>
<p>근데 제가 나중에 알게 된 거는,</p>
<p>어? 왜 이렇게 빠르지? 
어? 왜 아무 가이드도 안 주지? </p>
<p>이 2가지 문제가 결국 같은 곳에서 오는 거더라고요? </p>
<h1 id="개발은-자격증-시험이-아니다">개발은 자격증 시험이 아니다</h1>
<p>그건 뭐냐면, 제 마음속에 있는 관념이었어요.</p>
<p><em>개발자가 되기 위한 어떤 절대적인 교육과정,</em>
<em>공부 범위, 평가 기준이 있다</em>는 생각이에요.</p>
<p>이게 한국에서 교육받은 사람들한텐 상식적인 개념이거든요.</p>
<p>여러분, 수능이나 뭐 아니면 자격증 공부 생각해보세요.</p>
<p>범위와 교육과정이 있죠.
명확한 출제자의 의도 있죠.
유형별로 푸는 방법 있죠.
평가 기준 있죠.</p>
<p>내가 열심히 해서 
뭐 1급이든 2급이든, 
800점이든 900점이든.</p>
<p>딱 평가 기준을 넘으면, 대학 가고 공무원 합격하는 거잖아요.</p>
<p>그러니까 ‘개발자’라는 것도 
프론트면 프론트, 백엔드면 백엔드. 
각각 정해진 교육과정이 있고, 
내가 그 교육과정을 성실하게 이수하고,
평가 기준을 충족시키면,
개발자라는 ‘자격’을 가질 수 있는 거다. 
이렇게 생각을 하게 되는 거 같아요.</p>
<p>저같이 부트캠프에 온 사람이라면 더 그렇죠.</p>
<p>저 같은 사람들이 왜 부트캠프에 올까요? </p>
<p>내가 개발자가 된다는 게 어떤 건지 잘 모르니까.
커리큘럼이나 평가 기준이나 이런 걸 잘 모르니까,
혼자서 공부하면 불안하단 말이에요.</p>
<p>이미 그 과정을 잘 알고 권위가 있는 마스터한테 
그런 커리큘럼을 들어야 한다고 생각하니까,  수많은 개발자를 배출했다는 부트캠프에 돈 내고 가는 거죠.</p>
<p>A, B, C 순서대로 배우고, 이건 필수고. 
주어지는 과제 요렇게 구현해서, 완성하면
이제 개발자로 지원할 자격이 되는 거겠지?</p>
<p><em>이런 무의식적인 기대를 갖고 있으니까, 아까 제가 말씀드린 그런 어? 뭐지? 반응이 나오게 돼요.</em></p>
<p>컴퓨터 공학 과제? 
나 아직 다 못 풀었는데? 
왜 이렇게 빨리 나가지?</p>
<p>이게 괴로운 이유는, 이게 어떤 정해진 교육과정이고, 내가 이 과제를 이수해야만 개발자의 자격이 주어진다고 생각하기 때문이거든요.</p>
<p>왜 가이드를 안 주지? 이것도 마찬가지죠.</p>
<blockquote>
<p>‘개발자의 자격’을 얻기 위해 필요한 기준과 방법이 있을 텐데. 왜 그런 걸 안 알려주지?</p>
</blockquote>
<blockquote>
<p>내가 알아서 했다가 내 방식이 정답이 아니면 어떻게 하지?</p>
</blockquote>
<p>이런 고민이 들었던 거죠.</p>
<p>그래서 힘들었어요.</p>
<p>근데 몇 달 지나고서, 
어느 순간 깨달은 시점이 있었어요.</p>
<p>아 부트캠프는 학원이 아니구나.
개발자는 자격증 시험이 아니구나.</p>
<h1 id="스스로-살아남아야-한다">스스로 살아남아야 한다</h1>
<p>이게 무슨 말이냐면,</p>
<p><strong>빨리 내가 공부에서 주체성을 찾아야 한다</strong>는 겁니다. </p>
<p>쉽게 말해, 자기 스스로 결정하고 실행해서,
*<em>알아서 살아남아야 돼요. *</em></p>
<p>아니 근데 그럴거면 왜 부트캠프에서 그 비싼 돈을 받는 거야? 이런 생각이 들수도 있는데,</p>
<p>저는 왜 부트캠프에서 이런 식으로 교육하는지도 이해가 됐어요.</p>
<p>왜냐하면 <strong>개발자라는 건 진짜 자격증 시험</strong>이 아니거든요. 현업에서 개발 할때 무슨 시험 범위 내에서 사지선다 문제 푸는게 아니에요.</p>
<p>현업 개발자들이 푸는 문제는 
전혀 구조화되지 않고,
정해진 해결책도 없고,
처음 보는 문제에서,
스스로 답을 찾아내야 하는 과정에 가깝죠.</p>
<p>그러니까 부트캠프에서도 이런 야생의 환경을 주고, 답을 찾아내라고 일부러 설계한 거예요.</p>
<p>왜냐? 그게 취업을 하면 하게될 일에 가장 가까우니까요.</p>
<p>모든 부트캠프가 다 그렇진 않겠지만, 제가 다닌 부트캠프는 그런 걸 굉장히 강조하는 곳이었어요.</p>
<p>물고기를 잡아주는 곳도 아니고, 심지어 물고기 잡는 법을 가르쳐주는 곳도 아니에요.</p>
<p>그냥 <strong>뗏목 태워서 야생에 던져주는 곳</strong>이에요.
너가 야생에서 직접 물고기 잡아보라는 거죠.</p>
<p>이걸 깨달은 순간 솔직히 좀 스트레스가 오긴 했어요.</p>
<h1 id="토익-학원과의-차이">토익 학원과의 차이</h1>
<p>어려분 혹시 토익 학원 다녀보셨나요?
저는 예-전에 군대 때문에 점수가 필요해서, 토익 공부를 한 적 있는데요.</p>
<p>처음에는 돈 아까우니까 독학해야지, 이러다가 결국 학원에 한번 갔거든요?</p>
<p>근데 가니까 
*<em>‘진짜 내가 이걸 왜 안 들었지?’ *</em>
싶은 거예요.</p>
<p>기출 유형 다 분석해서, 
푸는 방법 공식 다 알려주고.
2달 내에 몇점 하고 싶으면 이렇게,
3달 내에 몇점 하고 싶으면 이렇게 
뭐 이런 플랜까지 다 짜여져 있어요.</p>
<p>그니까 정말 마음이 편하더라고요.
그렇다고 쉬운 건 아니지만, 해야될 건 명확하잖아요.</p>
<p>근데 토익과 개발은 완전 달라요. 개발은 그렇게 명확한 게 없는 거죠. </p>
<p>내가 주체적으로 해야돼요. 뭘 하면 개발자가 된다, 딱 정해져있지 않으니까요. 이게 꽤 스트레스다 이말이죠.</p>
<p>근데 한편으로는 너무 납득이 돼요.</p>
<blockquote>
<p><strong>우리도 이미 알잖아요. 토익 점수랑 영어 실력이랑 상관없다는 거.</strong></p>
</blockquote>
<p>개발도 그런 자격증 시험처럼 공부한다면, 실제로 개발 실력을 갖추는 거하고는 멀어질 수 밖에 없겠다 싶더라고요.</p>
<p>그래서 어렵긴 하지만, 이렇게 배우는 게 맞다, 점점 받아들이게 되더라고요.</p>
<h1 id="달라진-공부-방식">달라진 공부 방식</h1>
<p>그 다음부터는 제 공부 방식이 완전히 달라졌어요.</p>
<p>몇 가지 예를 들어보면요.</p>
<p>원래 2주마다 새로운 프로젝트를 줘요.
근데 저는 새로운 프로젝트를 안 하겠다고 했어요.
왜냐하면 그 전 2주에 했던 프로젝트에 아쉬운 포인트가 있었거든요. 좀 더 그걸 개선하면 많이 배울 거 같았어요.</p>
<p>그래서 저 다음 프로젝트 안하고, 이거 다시 하겠다 이렇게 말하고 했었고요.</p>
<p>강의 같은 경우도 제가 당장 이해할 수 없고, 집중할 수 없는 주제다, 그러면 과감하게 안 들었어요.</p>
<p>그 시간에 뭐했냐?
제가 필요하다고 생각한 공부를 했습니다.</p>
<p>또 정해진 과제 외에  제가 필요하다고 생각하는 부분들이 있었는데. 뭐 코딩 테스트라든지, 코드 리뷰라든지, 면접 대비라든지, 이런 걸 별도로 다른 친구들과 스터디를 만들어서 진행했어요.</p>
<p>부트캠프 교육과정이 절대적인 게 아니고, 이 과정을 완벽하게 다 할 필요가 없다. 요 마인드셋이 생기는 거죠.</p>
<p>반대로 </p>
<blockquote>
<p><strong>&#39;내가 할 공부를 하는데 어떻게 부트캠프라는 환경을 써먹을까&#39;</strong></p>
</blockquote>
<p>이런 쪽으로 고민을 했던 거 같아요.</p>
<p>뭐… 이건 지난 얘기니까 있어보이게 말해봤는데요.</p>
<p>당연히 쉬운 건 아니었고, 고민도 많이하고 스트레스도 많이 받았어요.</p>
<p>근데 덕분에 <strong>‘야생의 개발자’가 되기 위한 체력</strong>을 많이 쌓았던 거 같아요.</p>
<p>이렇게 6개월 공부를 하고 나서 본격적인 회사 지원 단계로 가게 됩니다.</p>
<p>이 얘기는 다음에 또 풀어볼게요.</p>
<p><a href="https://youtu.be/umShWWiu1lA"><img src="http://img.youtube.com/vi/umShWWiu1lA/0.jpg" alt="Video Label"></a>
🎥 <a href="https://youtu.be/umShWWiu1lA">https://youtu.be/umShWWiu1lA</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[밑바닥을 막아주는 루틴]]></title>
            <link>https://velog.io/@eddy_song/upward-spiral</link>
            <guid>https://velog.io/@eddy_song/upward-spiral</guid>
            <pubDate>Sat, 22 Apr 2023 14:17:29 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eddy_song/post/dc0bf670-a3cf-4d53-beff-f81193b48e9d/image.png" alt=""></p>
<p>지난번에 이어서 제가 개발자가 된 얘기를 계속 해볼게요.</p>
<p>저번에 개발자가 되기로 마음먹은 이유 퇴사 얘기를 했는데요</p>
<p>그 다음에 뭘 했느냐?</p>
<p>일단 개발 부트캠프에 들어가기로 했습니다.</p>
<p>비전공자가 개발을 시작하는 가장 흔한 루트죠.</p>
<p>거기서 하라는 대로 열심히 하면 개발자로 만들어 주겠지?</p>
<p>솔직히 이런 마음이었던 것 같아요.</p>
<p>그래서 나름 이런저런 평판조사를 했고 가고 싶은 부트캠프를 정했습니다</p>
<h2 id="부트캠프-탈락">부트캠프 탈락</h2>
<p>하지만 부트캠프는 돈만 있다고 갈 수 있는 게 아니더라고요. 웬만한 곳들은 다 코딩테스트를 봐요.</p>
<blockquote>
<p>에이 설마 떨어지겠어?</p>
</blockquote>
<p>하고 봤는데 <strong>똑 떨어졌습니다ㅜ</strong></p>
<p>그 탈락메일을 보는데 힘이 탁 풀리더라고요. 침대에 확 누워버렸습니다.</p>
<p>&#39;겨우 이 정도 테스트도 내가 통과 못하다니..&#39;</p>
<p>사실 아직 별로 한 것도 없었지만 뭔가 계획대로 잘 나가다가 갑자기 확 꺾여버린 느낌이었어요.</p>
<p>지금 생각해보면 아무것도 아니었지만 제가 좀 장밋빛 미래만 기대하고 있었던 건지,</p>
<p>그 일이 꽤나 충격이었던 것 같아요.</p>
<p>그날 저는 완전히 회피모드가 되었어요.</p>
<p>머릿속이 복잡하니까 그냥 아무것도 안 하고 싶더라고요
폰을 켜고 인스타, 페북, 유튜브를 계~속 봐요.
일부러 평소보다 자극적이고 웃긴것만 봅니다.</p>
<p>스크롤을 막 올리다가, 아 이제 진짜 더 볼 것도 없다, 싶은 때가 됐어요</p>
<p>그 때 시계를 보니까 어느새 새벽 2시더라고요.</p>
<p>늦게까지 안자고 내가 뭐 하는 거지..</p>
<p><strong>이렇게 생각하니까 또 기분이 확 안 좋아지는 거예요.</strong></p>
<p>아 일단 자야겠다, 하고 불 끄고 누웠어요</p>
<p><strong>근데 잠도 잘 안 와요.</strong> 계속 머릿속이 복잡한 거죠. </p>
<p>누워서</p>
<blockquote>
<p> 아 내가 왜 그랬을까..</p>
</blockquote>
<blockquote>
<p>지금 생각해보니까 그 문제 알 것 같은데..</p>
</blockquote>
<blockquote>
<p>아 미리 이렇게 했었어야 되는데...</p>
</blockquote>
<blockquote>
<p>나중에 취업에 문제 되는 거 아니야?</p>
</blockquote>
<p>이런 생각을 하다 보니까 기분이 더 안 좋아집니다.</p>
<h2 id="운동-명상-글쓰기">운동, 명상, 글쓰기</h2>
<p>어쨌든 일단 잠이 들었고 다음날 아침이 됐어요.</p>
<p>저는 원래 오랫동안 해온 루틴이 있는데요.</p>
<p>운동, 명상, 글쓰기 세 가지에요.</p>
<p>그래서 일단 헬스장에 운동을 하러 갔어요.</p>
<p>그리고 운동갔다 와서 커피를 한잔하고, </p>
<p>또 십분 동안 명상을 했고, </p>
<p>그 다음에 타이머를 맞춰놓고 글을 썼어요</p>
<p>뭐 대단한 글이 아니라 그냥 제가 무슨 생각하고 있는지 쓰는 건데요.</p>
<p>그러고 나니까 어제하고 다르게 기분이 확 나아지더라고요.</p>
<p>빡세게 운동하고 오니까 생각이 좀 긍정적으로 바뀌었어요.</p>
<p>특히 명상을 하면 내가 계속 돌아가던 그 생각의 쳇바퀴 바깥으로 좀 빠져나오는 느낌이에요.</p>
<p>명상이 자기 생각을 3인칭 시점으로 보는 연습이거든요.</p>
<p>글쓰기도 머릿속에 꼬여 있는 생각들을 하나씩 뽑아서 정리를 하다보면 이성적인 마인드로 돌아오는 느낌이 있어요.</p>
<h2 id="하강-나선">하강 나선</h2>
<p>제가 이 얘기를 왜 굳이 길게 했냐면요.</p>
<p>그 후에 개발자로 취업준비를 하면서 이런 일이 일어나고, 일어나고 또 일어나는 완전 반복이었기 때문이에요.</p>
<p>내가 완전히 모르는 개발이라는 영역에 뛰어들었잖아요?</p>
<p>그러니까 계속해서 실패를 맛볼 수 밖에 없어요.</p>
<p>수업을 듣는데 이해가 안 돼요.
서류만 넣었는데 순식간에 탈락 메일이 와요.
코딩테스트를 봤는데 하나도 못 풀었어요. 
어딘가에 면접보는데 대답을 잘 못해서 떨어져요.</p>
<p>계속 반복이거든요.</p>
<p>근데 사실 이건 당연한 거에요</p>
<p>제가 뭔가 안 해본 거에 도전하는 상황이니까 생각한 대로 다 잘 풀리면 그게 이상한거죠</p>
<p>근데 문제는 그 1번이 아니라 우리가 멘탈이 깨지면서 <strong>&#39;하강 나선&#39;</strong>을 그리게 되는 거예요.</p>
<p>&lt;우울할 때 뇌과학&gt;이라는 책에 보면,</p>
<p>우리 뇌가 한번 부정적인 모드에 빠지면 이성적인 작용을 하는 전전두엽이 잘 작동하지 않고 일어난 일을 더 부정적으로 해석하게 돼요</p>
<p>그래서 스트레스나 불안이 더 생기게 되죠.</p>
<p>그니까 기분 좋을 때 칭찬받으면 </p>
<blockquote>
<p>&#39;감사하다&#39;</p>
</blockquote>
<p>이렇게 생각하지만 
우울할 때는 칭찬을 받아도</p>
<blockquote>
<p>&#39;왜 갑자기 칭찬을 하지?&#39;
&#39;내가 불쌍하게 보이나?&#39;</p>
</blockquote>
<p>이런 생각을 하게 돼요.</p>
<p>그러면서 기분이 더 나빠지고 한마디로 멘탈의 악순환을 만들게 되죠.</p>
<p>근데 우리가 마음처럼 안 되고 실패를 계속 맛보게 되면 계속해서 이런 상황이 생길 수밖에 없어요.</p>
<h2 id="밑바닥을-막아주는-루틴">밑바닥을 막아주는 루틴</h2>
<p>근데 제가 부트캠프 탈락의 실패를 경험하고 나서 깨달았던 거는, 제가 꾸준히 했던 루틴들이 제 멘탈이 하강나선을 타지 않도록 막아줬다는 거예요.</p>
<p>저는 개발자로 취업 준비하시는 분들 만나면 코딩이 아니라 &#39;명상&#39; &#39;운동&#39; &#39;글쓰기&#39; 이걸 제일 먼저 추천해요</p>
<p>왜냐면은 커리어 전환은 마라톤, 장기전일 수밖에 없잖아요</p>
<p>만약에 제가 100m 달리기를 했는데 한번 넘어지면 &#39;완전히 글렀다&#39; 생각할 수도 있겠죠</p>
<p>근데 이게 장거리 마라톤이라면요?</p>
<p>지금 넘어진 게 아니라 얼마나 빨리 잊고 툭툭 털고 일어날 수 있는지가</p>
<p>더 중요한 거 잖아요 그래서 어떻게든 이 밑바닥이 내려가지 않도록 막아줘야 돼요.</p>
<p>근데 이게 뭐 말이 쉽지.</p>
<p>사실 막상 그 상황에 있으면 쉽지가 않아요.</p>
<blockquote>
<p>나는 코딩이 아닌가봐..</p>
</blockquote>
<p>막 이런 생각을 하고 있는데 갑자기 머리에 힘을 빡! 준다고 긍정적인 뇌가 될까요? 그렇진 않죠.</p>
<p>누구나 자기 뜻대로 풀리지 않으면 다운이 될 수밖에 없어요.</p>
<p>근데 그럴 때 루틴이 최소한 그 방향을 바꿔주는데 도움이 됩니다..</p>
<p>실제 과학적으로 사람의 컨디션과 기분을 상승시켜주는 여러가지 활동들이 있거든요.</p>
<p>운동, 수면, 명상, 감사, 결정, 음악, 호흡 등등..</p>
<p>한마디로 정신 건강 면에서 좋은 습관의 자격을 갖춘 것들이 있어요. 별로 어렵지도 않고요.</p>
<p>저는 그래서 그 중에서 몇 가지를 꾸준하게 오랫동안 계속해왔는데요.</p>
<p><strong>다른 어떤 것보다도 이게 제가 취업에 성공하는데 가장 큰 역할을 했다</strong>고 생각을 해요</p>
<p>왜냐하면 제가 10개월 동안 많은 실패를 겪고 다운을 겪으면서도 이 멘탈이 꺾이지 않을 수 있게 잡아줬거든요.</p>
<p>물론 이런 걸 한다고 갑자기 행복해지고 짜릿하고 뭐 이런 건 아니에요.</p>
<p>하지만 툭툭 털고 일어날 수 있게 해준다는 거죠</p>
<p>밑바닥을 막아주는 게 장기적인 결과를 결정한다는 걸 이걸 통해서 배운 것 같아요</p>
<p>그렇게 첫 부트캠프 탈락을 잊고 다른 부트캠프를 알아봐서 가게 되는데요</p>
<p>다음엔 본격적으로 코딩을 공부하면서 느낀 점들에 대해서 또 말씀드리도록 하겠습니다.</p>
<hr>
<p>🎥 <a href="https://youtu.be/GDL6n4WLpZ8">https://youtu.be/GDL6n4WLpZ8</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[나는 어떻게 개발자가 되었나?]]></title>
            <link>https://velog.io/@eddy_song/how-I-become-developer</link>
            <guid>https://velog.io/@eddy_song/how-I-become-developer</guid>
            <pubDate>Sat, 22 Apr 2023 14:05:54 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요 에디입니다.</p>
<p>오늘은 제가 어떻게 개발자가 되었는지 스토리를 간단히 얘기해보려 합니다</p>
<p>저는 노베이스 비전공자로 시작을 해서, 현재 회사에 입사한지 이제 7개월이 지났네요.</p>
<p>이렇게 단순하게 보면 해피엔딩인데 사실 마냥 해피한 스토리는 아니었어요</p>
<p>회사를 퇴사하고, 부트캠프 다니고, 수십 번의 서류 탈락을 거쳐서, 결국 지금 회사에 오기까지 약 10개월 정도의 시간이 있었는데요.</p>
<p>그 스토리를 한번 풀어보려고 합니다.</p>
<p>첫째, 왜 개발자가 되기로 마음 먹었나
저는 예전에 창업, 투자, 전략컨설팅, 기자... 다양한 일을 해 봤는데요.</p>
<p>제가 일이 재밌을 때가 언제냐. 뭔가 &#39;만드는 느낌&#39;이 있을 때였어요.</p>
<p>제가 몰입해서, 무언가 직접 만들고, 그걸 사람들한테 전달하고.</p>
<p>그 반응을 보고, 세상에 조금이나마 유용한 거를 제 손으로 만들고 있다라는 느낌이 있을 때 굉장히 열정이 생기더라고요.</p>
<p>그리고 저의 관심 분야는 꽤 오랫동안 IT, 스타트업이었어요.</p>
<p>관심 분야가 IT, 스타트업이니까 만드는 일을 하는 IT직군에 관심을 가졌습니다.</p>
<p>일단 &#39;한번 코딩을 배워보자&#39; 라는 결론에 도달하게 돼요.</p>
<p>사실 진짜 &#39;개발&#39;을 하려던 생각은 아니었거든요.</p>
<p>그냥 맛을 보자. 알아두면 좋다. 어차피 IT 업계에서 일할 거니까.</p>
<p>이런 생각이었습니다</p>
<p>퇴근하고 나서 사이드로 한번 자바스크립트를 막 끄적끄적 시작을 해 본 거예요</p>
<blockquote>
<p>어?
이게 재밌네? 😳</p>
</blockquote>
<blockquote>
<p>뭐야, 나 개발자 해야 되나?
와 근데 내가 진짜 개발자 된다고?
이게 말이 되나?</p>
</blockquote>
<p>해서 주변 친구들한테 얘기해 봤어요.</p>
<p>저의 절친 중 한 명도 저와 비슷하게 문과에서 아무것도 없이 개발자 된 케이스가 있었거든요.</p>
<p>그 친구를 포함해서 주변에 개발자들이</p>
<blockquote>
<p>&#39;야 너 충분히 할 수 있어&#39;</p>
</blockquote>
<blockquote>
<p>&#39;너 원래 일 잘 하잖아&#39;</p>
</blockquote>
<blockquote>
<p>&#39;개발도 똑같아&#39;</p>
</blockquote>
<p>이런 말을 많이 해줬습니다.</p>
<p>결국은 용기를 얻어 가지고 퇴사를 하고 개발자가 되는 여정을 시작하게 됩니다.</p>
<p>그래서 이제 시작을 하게 되었는데 이 10개월을 생각하면 가장 먼저 떠오르는 장면이 있어요.</p>
<p>제가 사람들한테 아 저 회사 퇴사하고 개발해 보려고요, 말을 했을 때 사람들 반응이 있잖아요.</p>
<p>물론 대부분의 사람들은 응원하는 말을 해줍니다.</p>
<p>하지만 한 두 개 정도 섞여 들어오는 걱정어린 반응들이 있었거든요</p>
<blockquote>
<p>와.. 진짜 코딩 하러 간다고?</p>
</blockquote>
<blockquote>
<p>너 예전에 학교에서 코딩해본 적 있나?</p>
</blockquote>
<blockquote>
<p>아무리 그래도 이게 비전공자고 백그라운드가 아예 없는데 괜찮겠어?</p>
</blockquote>
<blockquote>
<p>야 요즘에 부트캠프에서 신입 개발자 막 쏟아져 나온대. </p>
</blockquote>
<blockquote>
<p>내가 봤을 때 너는 전략이나 사업 쪽에 소질이 있는 거 같은데 이쪽 커리어로 가는 게 그것보다 낫지 않겠어?</p>
</blockquote>
<p>모두 나쁜 의도로 하는 말은 아니죠.</p>
<p>근데 왠지 응원하는 말보다 이 말들이 머릿속에 더 세게 박히더라고요.</p>
<blockquote>
<p>&quot;한번 해 봐야죠&quot;</p>
</blockquote>
<p>라고 아무렇지 않은 척 했어요.</p>
<p>근데 집에 돌아오면 마음이 착잡해지더라고요.</p>
<p>침대에 누워서 자려고 하면 막 저 말들이 떠올랐어요.</p>
<p>그게 다 제 마음속에 있는 말들이었거든요.</p>
<blockquote>
<p>내가 이제 와서 할 수 있을까?
그냥 하던 일 하는 게 낫지 않았을까?
그저 그런 개발자 중에 한 명이 되는 건 아닐까?</p>
</blockquote>
<p>근데 이 걱정들이 어느 날 갑자기 사라지지도 않아요.</p>
<p>10개월 동안 준비하는 내내 계속 있었어요.</p>
<p>&#39;올해는 (개발자) 공채 채용이 확 줄었다던데&#39;
&#39;요즘 iOS는 채용이 별로 없고 안드로이드가 급하대&#39;</p>
<p>신입 개발자는 기피 현상이 엄청 심하다던데 이런 말을 들을 때마다 계속 걔네들이 다시 올라오는 거에요.</p>
<p>마치 피리소리에 반응하는 코브라처럼 제 안에 불안감이 계속 스물스물 올라오더라고요. 그래서 커리어 전환을 하면서 가장 힘들었던 건 코딩도 아니고 CS 공부도 아니었어요.</p>
<p>바로 이 질문이었어요</p>
<blockquote>
<p>혹시 내가 잘못된 선택을 한 건 아닐까?</p>
</blockquote>
<p>지난 10 개월은 제 마음속에서 계속 올라오는 그 두려움들을 컨트롤하면서 어찌되었건 한 발씩 걸음을 옮기는 그런 일의 연속이었던 것 같아요.</p>
<p>🎥 <a href="https://youtu.be/F61ZdwUzdeY">https://youtu.be/F61ZdwUzdeY</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[상위 25% 스킬을 조합하기]]></title>
            <link>https://velog.io/@eddy_song/top-25-skill-c8jcigq7</link>
            <guid>https://velog.io/@eddy_song/top-25-skill-c8jcigq7</guid>
            <pubDate>Sun, 16 Apr 2023 03:11:29 GMT</pubDate>
            <description><![CDATA[<p>혹시 스콧 애덤스라는 사람을 들어보셨나요?</p>
<p>잘 모르는디? 하시는 분이 많을 거예요.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/54911024-248e-4655-9f3e-70614d20c758/image.png" alt=""></p>
<p>근데 그런 분들도 아마 요 캐릭터는 한번쯤 보셨을 거 같습니다. </p>
<p>‘딜버트’라는 캐릭터고. 직장인 풍자 만화의 제목이기도 한데요. 미국에서 굉장히 오랫동안 인기 있는 국민 만화죠. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/5622d23f-13a1-499d-a84b-0b025d9bf915/image.jpeg" alt=""></p>
<p>이걸 그린 작가가 누구냐? 바로 ‘스콧 애덤스’인데요. </p>
<p>거의 우리나라로 치면 이말년? 침착맨 느낌이라 해야하나. 아무튼 굉장히 유명하고 성공한 만화가죠.</p>
<p>근데 이 사람은 글도 되게 잘 쓰거든요? 
자기계발, 말하기 등등 다양한 주제로 책을 많이 썼어요. </p>
<p>역시 개그 만화가니까 글이 되게 재밌고, 또 조언들이 되게 뜬구름잡지 않고, 직설적이고 현실적이더라고요. 그래서 저는 스콧 애덤스가 쓴 ‘책’을 통해서 이 사람을 알게 됐어요. </p>
<p>이 사람이 옛날에 블로그에 쓴 ‘글’이 있는데요. 제목이 Career advice. 커리어로 성공하고 싶으면 어떻게 해야하냐. 이런 내용이에요.</p>
<h1 id="자본주의는-희소성에-보상을-준다">자본주의는 희소성에 보상을 준다</h1>
<p>여러분이 커리어로 성공해야 된다라고 하면 뭘 해야될 거 같으세요?</p>
<p>쉽게 말해 누군가가 이렇게 물어봐요. 저 진짜 연봉 엄청 많이 받고, 이 성공한 사람이 되고 싶은데 어떻게 해야할까요? 그럼 무슨 답이 떠오르시나요?</p>
<p>일단 딴 거 안하고 일 열심히 해야되고, 또 그 일을 좋아하고, 남들보다 훨씬 잘해야겠죠? 저는 그런 게 떠오르는데요.</p>
<p>근데 여기서! 스콧은 그 관점을 바꿔야 한다고 해요. 그러면서 딱 한 마디 합니다. </p>
<blockquote>
<p><strong>자본주의는 ‘희소성’에 보상을 준다.</strong></p>
</blockquote>
<p>이게 무슨 말이냐. 단순히 무엇을 열심히 하고, 잘한다고 바로 성공이 아니라는 거죠. </p>
<p>시장의 관점에서 보면 결국 중요한 건 수요-공급이거든요. 결국 사람들이 필요로 하는 어떤 능력이 있는데, 그걸 잘 하는 사람은 별로 없고 구하기가 힘들다? 그러면 시장은 거기에 보상을 해준다는 거예요. </p>
<p>물론 저는 사람의 커리어에 있어서 단순히 몸값이 높아지고 희소해지는 게 전부는 아니라고 생각합니다만, 어쨌든 중요한 부분이란 말이죠.</p>
<h1 id="희소해지는-2가지-방법">희소해지는 2가지 방법</h1>
<p>그럼 어떻게 희소해질 수 있는데? 스콧은 2가지 방법이 있다고 해요.</p>
<p><strong>첫번째, 한 가지 스킬을 정말 최고로 잘한다.</strong></p>
<p>이거 뭐 너무 당연한 말이죠. </p>
<p>제가 축구를 손흥민급으로 잘하면 당연히 희소하지 않겠습니까? 랩을 비와이처럼 잘하면 당연희 희소하겠죠. 아니면 현실적으로 iOS 개발을 진짜 상위 1%로 잘해서 막, 남들 3명이 할 걸 혼자 한다? 당연히 희소하겠죠.</p>
<p>근데 이 전략은 쉽지가 않아요. 말이 쉽지. 세상에 고수가 얼마나 많습니까. 저도 개발을 잘하고 싶은 사람이지만, 내가 개발 실력으로 상위 1%에 들 수 있을까? 이렇게 생각하면 막막-하거든요.</p>
<h1 id="3가지-스킬에서-25등하기">3가지 스킬에서 25등하기</h1>
<p>근데 2번째 전략이 있대요. </p>
<p>하나가 아니라 3가지 스킬에서, 상위 25%가 되는 거예요.</p>
<p>** 상위 1% 아니고, 상위 25%. **</p>
<p>100명 중에 25등 정도 안에 드는 실력인거죠. </p>
<p>스콧이 자기 예를 드는데, 자기는 그림을 진짜 잘 그리는 아티스트 수준은 아니지만,
대부분의 사람들보다는 잘 그림을 그린대요. 
그리고 막 TV에 나오는 개그맨 수준은 아니지만, 대부분의 사람들보다는 유머 감각이 뛰어나요.</p>
<p>나만큼 그림을 잘 그리고, 나만큼 웃긴 사람은 많아.</p>
<p>그런데.. ‘그림을 잘 그리면서 말도 이 정도 재밌게 하는 사람’은 별로 없다는 거에요.</p>
<p><strong>2가지의 ‘조합’이 스콧 애덤스라는 사람을 희소하게 만드는 거</strong>죠.</p>
<p>게다가 스콧 애덤스는 배경이 독특한 게, 사실 딜버트 만화를 그리기 전에 꽤 오랜 시간 은행, 통신사 등에서 직장인 생활을 하고 관리자까지 한 사람이거든요. 경영대학원 MBA까지도 졸업을 했고요. 비즈니스를 잘 알겠죠.</p>
<p>그러다보니까, 자기는 <strong>비즈니스 + 풍자 + 만화</strong>라는, 그 어떤 만화가도 하기 어려운 주제를 개척한거예요. 그래서 자기가 희소해졌다는 거죠.</p>
<p>첫번째 전략으로 하나의 스킬에서 최고가 되려한다면, 상위 1%는 되야 합니다. </p>
<p>근데, <strong>대부분의 사람들보다는 쪼끔 더 잘하는 정도, 상위 25%를 노린다면</strong> 어떨까요. 그리고 상위 25등하는 3개를 모아서 남들이 해보지 않는 조합으로 섞는다면?</p>
<p>25%의 세제곱이니까 1.25%네요. 뭐 단순 계산이지만, 첫번째 전략만큼 희소해질 수 있다는 거예요.</p>
<p>다시 말해 내 스킬이 세계 최고가 아니어도, 희소해지고, 엄청 큰 보상을 받을 수 있다는 얘기입니다. 어떻게 하면? ‘조합’을 무기로 만들면 된다는 거죠.</p>
<h1 id="조합을-무기로-삼기">조합을 무기로 삼기</h1>
<p>저는 이 말을 듣고, 제 커리어를 보는 관점에 많은 변화가 생겼어요.</p>
<p>여러분이 마케팅을 할 수도 있고, 엔지니어일 수도 있고, 미대생일 수도 있어요. </p>
<p>근데 우리 모두 어쨌든 그 일을 선택한 이상, 이 일로 정말 잘해서 돈도 많이 벌고 성공하고 싶잖아요? </p>
<p>근데 저는 그러면 그냥 열심히 일하고, 그 일을 정말 미친듯이 잘해서, 성과를 내는 거지. 뭐 이렇게 생각했어요. </p>
<p>근데 조-끔 관점을 바꿔보자 이거에요. 희소성에 초점을 맞춥니다. 그러면 어떻게하면, <strong>이미 내가 가지고 있는 거, ‘남들보다 좀 잘하는 스킬’을 가지고, 요걸 어떻게 잘 연결하고 조합하고, 확장해가지고 내가 희소해질까?</strong> 이런 전략으로 바꿀 수가 있어요.</p>
<p>이런 방식으로 생각하니까 저는 진짜 좋은 점이 뭐였냐면, <strong>제가 비교를 덜하고 불안한 게 줄어들더라고요.</strong> </p>
<p>제 커리어가 마치 올림픽처럼 1등만 알아주는 세상이어가지구, 세계 최고가 되어야 하는 게임이라고 생각하면, </p>
<p>누가 저보다 잘하는 걸 봤어요. 그럼 무슨 생각을 해요? 아 나는 저 사람보다 못하는 거 같은데, 나는 이 종목에서 성공하긴 글렀구나.. 망했다. 이런 생각을 하게 되잖아요? </p>
<p>상위 25% 조합을 노린다 그러면, 그런 비교가 의미 없어지거든요. </p>
<blockquote>
<p>어차피 남들과 나는 조합이 다른데. </p>
</blockquote>
<p>나는 내가 잘하는 것들을 잘 섞어서 어떻게 세상이 원하면서도 희귀한 사람이 될 것이냐, 이것만 고민하면 되는 거거든요.</p>
<p>저도 저보다 개발을 잘하시는 분들을 보면 불안할 때가 있거든요. 너무 잘하고 지식도 많아가지고 살짝 물어봤는데, 막 저보다 3-4살 어린 거예요. 불안하죠. 쫄리고.</p>
<p>저는 그걸 이겨낼려고 저는 제가 가진 걸 뭔가 연결해보려는 시도를 많이 해요.</p>
<p>처음 개발자로 취업을 준비할 때도 그랬는데요. 저는 블로그에 굉장히 시간 투자를 많이 했었거든요. </p>
<p>그게 왜냐하면 제가 <strong>개발은 신입 개발자 중에서 상위 1%가 아니겠지만, 적어도 개발하는 사람들 중에서, 글쓰는 건 상위 25% 안에 들 자신</strong>이 있었거든요.</p>
<p>글로 하는 커뮤니케이션과 문서화가 개발자 현업에서도 원하는 역량이라는 걸 알고 있었어요. 제 조합을 가지고 저를 어떻게든 희소하게 만들어보려고 했던 거죠.</p>
<p>여러분은 어떠신가요? 여러분이 남들보다 꽤 잘할 수 있는 스킬은 무엇일까요? 만약 그런 거 3가지를 조합한다면 뭘 고르실 건가요? </p>
<p>댓글로 달아주시면 재미있을 거 같습니다!</p>
<p><a href="https://youtu.be/4fgN3uoKM38"><img src="https://img.youtube.com/vi/4fgN3uoKM38/0.jpg" alt="상위 25% 스킬을 조합하기"></a>
<a href="https://youtu.be/4fgN3uoKM38">https://youtu.be/4fgN3uoKM38</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인풋 말고 아웃풋]]></title>
            <link>https://velog.io/@eddy_song/input-output</link>
            <guid>https://velog.io/@eddy_song/input-output</guid>
            <pubDate>Sat, 08 Apr 2023 11:36:47 GMT</pubDate>
            <description><![CDATA[<p>가끔 이런 질문을 들을 때가 있습니다.</p>
<blockquote>
<p>제가 IT업계 취준을 준비하고 있는데요. 업계 지식을 쌓기에 좋은 책이나 채널이 있을까요?</p>
</blockquote>
<blockquote>
<p>저도 개발 배우고 싶은데, 어떤 강의나 책을 추천하시나요?</p>
</blockquote>
<blockquote>
<p>굉장히 많이 읽으시는 거 같아요. 그렇게 많이 읽고 자신의 생각으로 소화하려면 어떻게 해야하나요?</p>
</blockquote>
<p>왜 이런 질문을 들으면 상당히 공감이 됩니다. 저도 항상 그러거든요.</p>
<p>저는 성장하고 싶은 욕구가 큰 사람이에요.</p>
<p>그래서 <strong>본능적으로 인풋을 늘리려는 경향</strong>이 항상 있단 말이죠.</p>
<p>좋은 노하우. 
좋은 책. 
좋은 지식. 
좋은 사례...</p>
<p>특히 저는 서점 가서 이 책 저 책 뒤지면서 쇼핑하는 거 되-게 좋아합니다.</p>
<p>심지어 코세라나 유데미 같은 강의 플랫폼 가서 어떤 강좌가 나왔나 구경하는 것도 재밌거든요. </p>
<p>남들이 좋은 지식 콘텐츠가 있다고 추천한다? 
무조건 찾아가서 구독이죠.</p>
<p>결국 위에서 받은 질문들도 다 &#39;인풋&#39;에 초점을 둔 질문들이에요.</p>
<p>그럼 반대로 아웃풋은 뭘까요. </p>
<p>내가 말하거나,
질문에 대답하거나, 
설명하거나, 
쓰거나 직접 만들어보는 것. </p>
<p>이런 게 아웃풋이죠.</p>
<p>근데 &#39;내가 어떤 순간에 가장 많이 배웠지?&#39; 라고 돌아봤을 때 깨닫게 됩니다.</p>
<p>진짜 빨리 배우고 싶다면, 인풋이 아니라 아웃풋에 신경을 써야한다는 거.</p>
<p>누군가 생각할 거예요.</p>
<blockquote>
<p>아니, 인풋이 있어야 아웃풋이 나오는 거 아니야?
아무것도 몰라서 배우려고 하는데 어떻게 아웃풋을 내?</p>
</blockquote>
<p>물론 틀린 말은 아닙니다.</p>
<p>근데** 인풋을 넣고 정리하면 저절로 아웃풋이 나올 거라고 생각하는 것<strong>과
어떤 **아웃풋을 뽑는 걸 목표로 인풋을 넣는 건</strong> 완전히 달라요.</p>
<p>사실 우리도 어느 정도 알고 있습니다.</p>
<p>직접 하면서 배워야 빠르다...
아는 걸 말로 설명해야 오래 간다...</p>
<p>하지만 여전히 우리는 인풋 기반의 노력을 더 많이 하고, 아웃풋 기반의 노력을 잘 하지 않아요.</p>
<p>왜냐하면 상대적으로 불편하고 두렵거든요.</p>
<h2 id="인풋-중심과-아웃풋-중심의-예">인풋 중심과 아웃풋 중심의 예</h2>
<p>예를 들어, &#39;IT 업계 쪽으로 취준을 하고 있다. 그래서 지식을 좀 쌓고 싶은데, 어떤 좋은 책이나 채널이 있냐?&#39; 이런 질문이 있었는데요.</p>
<p>&#39;내가 지식을 쌓으려면 IT 업계 소식을 알려주는 좋은 책 뉴스를 찾아서 많이 읽어야겠다 &#39; 이런 생각이 깔려있는 거예요.</p>
<p>하지만, 반대로 이런 건 어떨까요?</p>
<p>SNS 계정 하나를 일단 만듭니다. 
거기에 IT 업계 뉴스를 사람들이 볼 수 있게 매일 요약 정리해서 올리는 거예요.</p>
<p>아웃풋을 목표로 잡는 거죠. 그러면 인풋은 자연스럽게 될 수밖에 없어요. </p>
<p>왜냐, 내가 IT 업계를 잘 모르는데, 오늘 IT 업계 뉴스를 정리해서 올려야 하잖아요. </p>
<p>그러면 그냥 뉴스를 읽는 것과 완전히 효율이 다른 학습을 하게 됩니다.</p>
<p>또 하나 예를 들어보자면, 내가 사진을 잘 찍고 싶어요. </p>
<p>그러면 대부분 사진 잘 찍는 법. 입문자용 추천 카메라 이런 걸 보겠죠? </p>
<p>근데 아웃풋 중심은 뭐냐면. 인스타그램 계정 하나 파는 거예요. 프로필에다가 내가 찍은 사진을 매일매일 올린다고. 이렇게 써요. </p>
<p>아니면 내 사진으로 1달 뒤에 온라인 전시회를 하겠다! 이렇게 선언 포스팅을 올릴 수도 있고요. </p>
<p>그리고 그때부터 그걸 준비하는 거죠. 확실히 학습의 퀄리티가 다를 거 같지 않나요?</p>
<p>우리는 아는 것과 모르는 것. 배운 것과 안 배운 것이 있다고 생각하지만.
그냥 단순하게 아는 것과, 정말로 깊게 이해한 것 사이에는 굉장히 넓은 스펙트럼이 있어요.</p>
<p>아웃풋으로 지식을 쌓으면, 이쪽 깊이있는 쪽에 쌓입니다.</p>
<h2 id="설명하면서-배우기">설명하면서 배우기</h2>
<p>제가 기억나는 에피소드가 하나 있습니다.</p>
<p>제가 부트캠프 다니면서 코딩을 배우는데. 처음 MVC 패턴을 배웠어요. </p>
<p>중요한 거라는데, 강의를 들어도 너무 이해가 안 되는 거예요.</p>
<p>막 열심히 아티클 찾아보고 읽고 했는데. </p>
<p>그래도 뭔가 딱 머릿속에 정리된 느낌이 아니었어요. </p>
<p>한 50%밖에 이해가 안됐던 거 같아요.</p>
<p>근데 딱 눈치를 보니까 다른 사람들도 다 이해를 잘 못한 거 같더라고요. </p>
<p>제가 점심 시간에 잠깐 줌으로 모이세요. 제가 한번 설명해볼게요! 
막 화이트보드에 그림 그려가면서 설명을 했어요.</p>
<p>그랬더니 그분들도 이해도가 올라갔지만, 오히려 제가 공부가 되더라고요. </p>
<p>최대나 쉽게 비유를 해서 설명하고, 사람들 질문에 답을 하려고 노력하다보니까, 오히려 제가 퍼즐이 맞춰지는 느낌이었어요. </p>
<h2 id="기록이-아니라-설명">기록이 아니라 설명</h2>
<p>저는 블로그에도 시간 투자를 많이 했었는데, 그것도 마찬가지였어요.</p>
<p>대부분 개발 블로그 하시는 분들이 어떻게 하냐면요. 자기가 보고 들은 거. 배운 거를 필기하는 것처럼 글을 써요. 내가 들은 인풋을 &#39;기록&#39;하는 느낌이에요. </p>
<p>근데 저는 아웃풋스럽게 쓰려고 했어요. 똑같은 내용이라도, 내가 누군가에게 질문을 받았다? 그 사람이 나보다 잘 모르는 사람이라고 가정하고 설명하듯이 썼던 거죠.</p>
<p>물론 나도 잘 모르지만, 뭐 어때요. 적어도 나보다 모르는 사람한텐 도움이 될 거잖아요. 근데 그렇게 얻은 지식들은 아직도 생생하게 기억에 남아있어요.</p>
<h2 id="생각이-있어야-쓸-수-있다는-고정관념">생각이 있어야 쓸 수 있다는 고정관념</h2>
<p>아웃풋 중심으로 학습을 하려면, 고정관념 하나를 깨야돼요.  </p>
<blockquote>
<p>&#39;내가 대-단한 생각이 있고, 뛰어난 지식이 있어야 남들에게 설명을 하거나 글을 쓸 수 있다&#39; 라는 고정관념</p>
</blockquote>
<p>여러분이 뭔가를 배우고 있어요. </p>
<p>그럼 머릿속에 정리 안 된 생각이 있고, 아직 익숙해지지 않은 스킬이 있겠죠?
아웃풋을 한번 만들어보세요. </p>
<p>일단 생각을 표현해보시고,
다른 사람한테 설명해보겠다고 하세요.</p>
<p>설익은 결과물이라도 던져보세요.</p>
<p>불편할 수 있지만, 그러면서 저는 지식이 단단해지고 수준을 높아지더라고요.</p>
<h2 id="인풋은-카운트하지-마세요">인풋은 카운트하지 마세요</h2>
<p>결론. 가장 빠르게 스킬과 지식을 쌓는 방법은, 아웃풋 중심의 노력을 하는 것이다.</p>
<p>내가 읽은 책의 갯수가 아니라, 내가 쓴 독후감의 갯수를 목표로 잡으세요.  </p>
<p>좀 과장해서 말하면 그냥 인풋은 카운트를 하지 마세요. 
내가 노력을 얼마나 했는지를 아웃풋으로 계산하세요. 그걸 목표로 잡으세요. </p>
<p>여러분의 성장 속도가 훨씬 더 빨라질 거라고 장담합니다.</p>
<p><a href="https://youtu.be/kA_nLyRWP84"><img src="https://img.youtube.com/vi/kA_nLyRWP84/0.jpg" alt="인풋 말고 아웃풋"></a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[좋은 프로그래밍은 글쓰기와 닮아있다]]></title>
            <link>https://velog.io/@eddy_song/writing-and-programming</link>
            <guid>https://velog.io/@eddy_song/writing-and-programming</guid>
            <pubDate>Sat, 08 Apr 2023 11:27:47 GMT</pubDate>
            <description><![CDATA[<p>처음 코딩을 배우기 시작했을 때, 
&#39;개발자를 직업으로 삼아야겠다!&#39;
이런 확신은 없었어요.</p>
<p>그때 누군가 너가 지금 시작해서 컴공 전공한 사람이나, 이미 경험 많은 사람만큼 잘할 수 있을까? </p>
<p>이런 얘기를 한적이 있었거든요. 그런 걱정이 저도 마음속에 있었어요. </p>
<blockquote>
<p>아 내가 정말 이걸 직업으로 했을때 경쟁력이 있고 잘할 수 있고, 내가 이 일을 좋아할까?</p>
</blockquote>
<p>그때는 누가 요즘 뭐 하냐고 물어보면. &#39;요즘 코딩을 배우고 있다.&#39; 라고 했어요. </p>
<p>근데 나 이거 진지하게 하는 거 아니야. 나 그냥 앱 만들어보고 싶었어. </p>
<p>굳이 이렇게 얘기했던 거 같아요. 왜냐하면 아직 저도 확신이 없으니까. 
아직 진지한거 아니라고. 일부러 방어를 하는거죠.</p>
<p>그랬던 제가 근데 그게 딱 깨지면서 ‘아 나 정말 개발자라는 직업을 해볼 수 있겠는데? 재미있겠는데?’ 했던 순간이 있어요. </p>
<p>그 얘기를 간단하게 해보려고 합니다.</p>
<h2 id="코딩은-수학-퀴즈">코딩은 수학 퀴즈?</h2>
<p>처음에 저는 코딩이 수학 문제 같은 거라고 생각했어요. </p>
<p>컴퓨터라는 기계가 있고. 제가 원하는 동작이 있는데. 그 기계는 내가 뭘 하고 싶은지 모르죠. 프로그래밍은 그걸 시키는 거잖아요. 그게 약간 수학 문제 같았어요.  </p>
<p>‘막대기 2개랑 뭐 상자 하나가 주어지는데 이걸 가지고 초가 벽에서 떨어지게 하라.’ 뭐 이런 퀴즈 아시죠? </p>
<p>프로그래밍은 그런 느낌의 문제를 수학이나 컴퓨터과학 지식을 가지고 푸는 거라고 생각했어요.</p>
<p>다시 말해, ‘컴퓨터가 작동’하도록 하는 게 프로그래밍인 줄 알았어요. </p>
<p>근데 공부를 하다보니까 그게 아니었더라고요. </p>
<p>물론 컴퓨터가 원하는 대로 작동하게 코딩하는 건 기본이에요. </p>
<p>그런데 더 중요한 건 다른 사람, 다른 개발자가 이해할 수 있는 코드를 써야해요. 이게 소프트웨어 개발의 마스터들이 다들 입을 모아서 하는 얘기거든요. </p>
<blockquote>
<p>‘컴퓨터가 알아듣는 코드를 쓰는 것은 아무나 하는 것이다. 진짜 좋은 개발자는 다른 사람이 쉽게 알아볼 수 있게 쓰는 코드를 쓴다’ </p>
</blockquote>
<p>그래야 다른 개발자들이 이해하고 수정하는 비용이 줄어들고, 그게 진짜 개발에서 중요한 부분이라는 거에요.</p>
<p>그런 말들을 들으면서 어느 순간 딱 느꼈어요. </p>
<blockquote>
<p>아 이게 내가 글을 써왔던 과정이랑 굉장히 비슷하구나. </p>
</blockquote>
<p>(여기서 말하는 글은 비문학적인 글)</p>
<h2 id="작동한다고-끝이-아니다">작동한다고 끝이 아니다</h2>
<p>첫번째로, 글을 생각해보면, 단순히 정보를 다 담았고, 문법이 맞게 문장을 구성했다고 해서 끝이 아니거든요. </p>
<p>프로그래밍도 마찬가지였던 거에요. 단순히 제대로 작동한다고 끝이 아닌거죠. </p>
<p>유튜브 조회수 높은 것부터 정렬해서 보여줘. 구독 버튼 눌렀을 때 이 사용자가 이 채널 구독하는 상태로 만들어줘. 이런 기능을 구현하는 코드는 많이 있을 거에요. </p>
<p>하지만 그게 진짜 좋은 코드라면, 도대체 어떻게 정렬을 하고 있는 거고, 어떤 동작을 의도한 건지 코드만 보고도 쉽게 이해가 돼야 한다는 거죠. </p>
<h2 id="구조가-핵심이다">구조가 핵심이다</h2>
<p>두번째, 글쓰기의 핵심은 구조를 짜는 거에요. </p>
<p>글쓰기는 쓰는 사람이 맥락과 독자를 고려해서, 어떻게 구조를 짜느냐에 따라서 잘 읽히는 정도가 완전히 달라져요. </p>
<p>문장을 어디에서 끊을 건가, 어디서 단락을 나누고, 소제목을 어떻게 붙이고, 어떻게 서로 다른 예시들을 하나의 주제로 묶을 것인가. 이런 것들을 고민하는 구조의 아트거든요. </p>
<p>근데 코드도 똑같아요. 복잡한 문제, 복잡한 동작들을 더 이해하기 쉽게, 더 깔끔하게 만들기 위해서 함수를 쪼개고, 이름을 붙이고, 객체로 묶거든요. </p>
<p>좋은 프로그래밍의 기술이라고 하는 것들, 객체지향이니 함수형이니 뭐 이런 것들도 다 결국은 이런 구조화하는 아트의 일종이거든요. </p>
<p>개발자들이 이름짓기가 제일 어렵다고 하는 것도 같은 맥락이고요.</p>
<h2 id="잘하려면-인간을-고려해야-한다">잘하려면 인간을 고려해야 한다</h2>
<p>세번째로, 좋은 글이든 좋은 코드든 ‘인간’을 고려해야한다는 게 비슷해요. </p>
<p>왜냐하면 우리가 글쓰기를 할 때는 어떤 ‘나와 다른 지식, 생각를 가진 다른 사람들이 이걸 읽고 이해하기를 바라면서 글을 쓰잖아요. 그렇기 때문에 좋은 글을 쓰려면 읽는 사람의 인지와 마음을 생각해야 해요. </p>
<p>근데 코드도 똑같아요. 코드를 실행할 컴퓨터도 중요하지만, 코드를 읽는 다른 개발자들은 인간이거든요. </p>
<p>컴퓨터에만 초점을 맞춘다면 우리는 굳이 뭐 어렵게 함수 나누고 클래스 짜고 할필요가 없어요. </p>
<p>하지만 프로그래밍을 잘하려면 ‘사람’에게 초점을 맞춰야 돼요. 사람은 기억력과 인지력, 받아들일 수 있는 복잡성에 한계가 있거든요. </p>
<p>좋은 코딩 스킬이라고 하는 것들은, 이것과 연관이 되어있어요. 중요하지 않은 정보는 안으로 숨긴다. 사람들이 많이 하는 현실의 개념으로 이름을 붙인다. </p>
<p>코드를 작성한 사람의 의도를 다른 개발자, 혹은 미래의 나한테 전달한다. 이런 과정도 모두 개발자의 일상이고 프로그래밍의 일부이거든요.</p>
<h2 id="해볼-수-있겠는데">해볼 수 있겠는데?</h2>
<p>저는 이걸 그때 당시에 아주 어렴풋하게 깨달았는데요. 그때 딱 ‘아 이거 내가 잘할 수 있겠다’라는 생각이 들었어요. </p>
<p>저는 글쓰기를 좋아하고, 특히 글쓰기 안에서도 저렇게 논리적으로 구조화하는 부분을 굉장히 좋아하거든요. 저는 주장1 근거1 근거2 이런 식으로 논리적인 글쓰기를 되게 좋아했고, 예전에 수능에서도 국어가 가장 자신이 있었어요. </p>
<p>내가 수학이나 알고리즘, 컴퓨터라는 기계에 대해서는 잘 모르겠지만. 논리적으로 구조화하는 거, 이건 내가 컴공과 나온 사람만큼 잘할 자신이 있는데? 라는 생각이 들었어요. 글쓰기랑 비슷하다고 생각하니까, ‘국문학과 나왔다고 글쓰기 잘하는 거 아니 잖아?’ 라는 생각이 들면서 자신감이 생기더라고요.</p>
<p>그 지점에서 갑자기 개발이라는 게 ‘내 거’ 같다는 생각이 들기 시작했어요. </p>
<p>그때부터 확신을 가지고 개발 공부를 하기 시작했고, </p>
<p>&#39;어떻게 코드를 읽기 좋게 구조화할 것인가&#39;</p>
<p>이게 실제로 지금까지도 제가 가장 재미있어하고 좋아하는 분야입니다.</p>
<p><a href="https://www.youtube.com/watch?v=Klo_VQvIPYA"><img src="https://img.youtube.com/vi/Klo_VQvIPYA/0.jpg" alt="좋은 프로그래밍은 글쓰기와 닮아있다"></a></p>
<p>📹 <a href="https://youtu.be/Klo_VQvIPYA">https://youtu.be/Klo_VQvIPYA</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[노베이스에서 토스 합격까지]]></title>
            <link>https://velog.io/@eddy_song/retrospective</link>
            <guid>https://velog.io/@eddy_song/retrospective</guid>
            <pubDate>Fri, 02 Sep 2022 12:45:04 GMT</pubDate>
            <description><![CDATA[<p>다른 사람들의 합격 후기처럼 정보성 글을 기대했다면 죄송하다. 이 글은 정보성이 아니라 공감성에 가깝다. </p>
<p>해피 엔딩이지만, 마냥 해피하지만은 않았던 지난 10개월.</p>
<p>잘 다니던 직장을 퇴사하고, 
코드스쿼드에서 공부하고, 
개발 블로그를 시작하고, 
탈락에 괴로워했던 과정까지. </p>
<p>개인적으로 가장 기억나는 장면과, 거기서 배운 점들을 얘기해보려 한다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/0058e15e-858c-452e-b952-cbb4621b1899/image.png" alt=""></p>
<h1 id="1-가장-큰-적">1. 가장 큰 적</h1>
<p>먼저 떠오르는 장면이 있다. 처음 사람들에게 &#39;회사를 그만두려고 합니다&#39;, &#39;개발을 해보려고요&#39; 라고 말했을 때. 사람들의 다양한 반응이다.</p>
<blockquote>
<p>“진짜 코딩하러 간다고?”</p>
</blockquote>
<blockquote>
<p>“흠… 너 예전에 학교에서 코딩해본 적 있나? 아무리 그래도 비전공자고 백그라운드가 아예 없는데 괜찮겠어?”</p>
</blockquote>
<blockquote>
<p>“요즘에 부트 캠프에서 신입 개발자들 쏟아져 나온대.”</p>
</blockquote>
<blockquote>
<p>“난 너가 전략이나 사업 쪽에 소질이 있다고 생각해. 이쪽 커리어 타도 분명 잘 될 수 있을 거야.”</p>
</blockquote>
<p>악의를 가진 말은 아니었지만, 저 말들이 내 마음을 강하게 찔렀다. </p>
<p>겉으로는 짐짓 단호한 척했다. 속으로는 저 말들이 천둥처럼 크게 들렸다.</p>
<blockquote>
<p>&#39;저도 생각해봤어요. 여전히 고민되긴 하는데, 그래도 한번 가보려고요&#39;</p>
</blockquote>
<p>웃으면서 적당히 대답했다. 하지만 집에 돌아오면 착잡해졌다. 침대에 누울 때 쯤 저 말들이 다시 한번 떠오르곤 했다. </p>
<p>왜냐면 다 내 마음 속에 있는 말들이었기 때문이다. 내 마음속 불안감을 그대로 표현한 말들이었다. 남들의 말은 트리거였을 뿐이다.  </p>
<p>분명 한 쪽의 나는 ‘해보자’라고 패기를 발산하고 있었다. 하지만 또 다른 쪽의 나는 의심하고 있었다. </p>
<p>‘내가 이제 와서 할 수 있을까?’ 
‘그냥 하던 일 하는게 낫지 않았을까?’ 
‘그저 그런 개발자 중 한 명이 되는 건 아닐까?’</p>
<p>그 후 10개월 동안에도 이런 일은 반복됐다.</p>
<p>‘올해는 공채 채용이 확 줄었다더라’
‘요즘 iOS는 채용이 별로 없고, 안드로이드가 급하다더라’
‘신입 개발자는 기피 현상이 심하다더라’</p>
<p>이런 비슷한 말을 들을 때마다 속으로 상당한 데미지를 받았다. *<em>내 마음속의 불안감, 두려움이 스멀스멀 올라왔다. *</em>마치 피리 소리에 반응하는 코브라 같았다. </p>
<p>커리어 전환을 하면서 <strong>나를 가장 힘들게 했던 적(enemy)은, 코딩이나 CS가 아니었다.</strong></p>
<blockquote>
<p>혹시 내가 잘못된 선택을 한 건 아닐까?</p>
</blockquote>
<p><strong>자기 확신이 없음에서 오는 스트레스</strong>였다. </p>
<p>물론 남들은 ‘잘하고 있다&#39; ‘응원한다&#39;라는 말도 해준다. 분명 개발이 재밌는 순간들도 있었다. </p>
<p>하지만 사람이 참 간사한 게, 불안감을 자극하는 얘기들만 골라서 듣는다. 그런 말을 들으면 걱정과 함께 내 안의 자격지심이 활활 불타오른다. 그 시간에 그냥 코딩을 한 줄 더하는 게 낫다는 걸 알면서도.</p>
<blockquote>
<p><a href="https://youtube.com/shorts/IGWZy9mlg9g?feature=share">그렇지만 어쩌겠나. 그래도 해내야지.</a> </p>
</blockquote>
<p>지난 10개월은, 내 마음 속에서 계속 올라오려는 두려움을 잘 컨트롤하면서, 어찌되었건 한 발씩 걸음을 옮기는, 그 일의 연속이었다.</p>
<h1 id="2-바닥을-막아주는-습관">2. 바닥을 막아주는 습관</h1>
<p>나에게는 다 계획이 있었다. </p>
<p>그리고 그 계획의 첫단추는 부트캠프에 들어가는 것이었다.</p>
<blockquote>
<p>“안타깝게도 이번 모집에서는 합격의 기쁜 소식을 전해드리지 못하게…”</p>
</blockquote>
<p>흐음… 하고 나도 모르게 한숨이 새어나왔다. 상처를 주지 않으려는 정중한 이메일이었다. 하지만 다 읽지도 않고 창을 꺼버렸다. </p>
<p>힘이 빠져 침대에 확 누워버렸다. 망쳐버린 코딩 테스트가 자꾸 생각이 났다. 그땐 코딩 테스트가 무엇인지도 잘 몰랐다. 문제 푸는 환경이 익숙하지 않아서, 당황해서인지 2문제를 모두 풀지 못했다. </p>
<p>제출하고 나니까 그제서야 창의적인 풀이가 마구 떠올랐다. </p>
<blockquote>
<p>&#39;그렇게 어려운 문제도 아니었네&#39; 
&#39;지금 와서 그 생각하면 뭐가 달라지냐?&#39;</p>
</blockquote>
<p>퇴사하기 전 나름 이런저런 평판 조사를 거쳐서, 가고 싶은 부트캠프를 정했다. 하지만 웬만한 부트캠프는 돈만 내는 게 아니라, 코딩 테스트를 본다. </p>
<p>속으로는 쉽게 통과할 수 있을 줄 알았다. 퇴사, 부트캠프, 취업 이런 것들이 머릿속에서 생각한대로 착착 이뤄질 줄 알았다.</p>
<p>그런데 저 이메일을 받았다. (아직 뭐 한 것도 없었지만) <strong>계획대로 잘 나가다가 갑자기 꺾여버린 느낌</strong>이었다.</p>
<blockquote>
<p>겨우 이 정도 테스트도 통과 못하다니. </p>
</blockquote>
<p>(지금 생각하면 아무것도 아니었지만, 장밋빛 미래만 생각했던 나에게는 꽤나 충격이었던 거 같다.)</p>
<p>즉각적인 반응은 회피였다. 머릿속이 복잡하다. 그냥 아무 생각도 안하고 싶었다.</p>
<p>나도 모르게 폰을 켜고 무한 스크롤을 했다. 일부러 평소보다 자극적이고 웃긴 컨텐츠만 클릭해서 봤다. 인스타, 페북, 유튜브… 계속 스크롤을 올리다가 더 볼것도 없네, 싶어서 시계를 봤다. 어느새 새벽 2시다. </p>
<blockquote>
<p>아… 안 자고 이게 뭐하는 짓이지.</p>
</blockquote>
<p>잠깐 괜찮아졌던 기분이 다시 다운됐다.</p>
<p>잠을 자보려고 한다. 여전히 머릿속이 복잡해서 잘 안 된다. 뒤척이다가 다시 시계를 보니 3시. 나도 모르게 한숨이 나온다.</p>
<p>다음 날 아침. 여전히 기분이 꿀꿀했다. </p>
<p>일단 매일 아침 루틴을 하기로 한다. 내 루틴은 운동, 명상, 글쓰기 3가지다. 헬스장에 운동하러 간다. 갔다 와서 커피를 내린 다음 명상을 한다. 타이머를 맞춰 놓고 글을 쓴다.</p>
<p>근데 그러고 나니 <strong>기분이 확 달라졌다.</strong> </p>
<p>빡세게 운동하고 오자 생각이 긍정적으로 바뀌었다. 뇌에 <code>F5</code>를 눌러준 느낌. </p>
<p>명상을 하면 생각의 쳇바퀴 바깥으로 빠져나올 수 있었다. 내 생각을 3인칭 시점으로 볼 수 있다. </p>
<p>나는 생각이 많을 때 글을 자주 썼다. 머릿속에서 계속 &#39;아씨 어떡하지&#39; &#39;아 왜 그랬지&#39; 아우성치던 생각들이 조금 가라앉았다. 음... 그래. 그래서 어쩔 건데? 라는 이성적인 마인드로 돌아왔다.</p>
<p>맨날 하던 거지만, 그날따라 이 루틴이 얼마나 중요한지 새삼 느꼈다. 이 날의 깨달음 덕분에, 그 후 10개월 동안 내 멘탈을 부여잡을 수 있었던 거 같다.</p>
<h3 id="just-start-over">Just Start Over</h3>
<p>나는 이 말을 참 좋아한다. 이 말에 내가 개인적으로 부여하는 의미는 이런 거다.</p>
<p>인생은 장거리 게임이다. 안 넘어지는 건 불가능하다. 멈추지 않는 건 불가능하다. 진짜 중요한 것은, 걸려 넘어지더라도 그게 끝이라고 생각하지 않는 것. 아무 일 없었다는 듯이 다시 일어나는 것.</p>
<p>그때는 넘어진 게 세상 무너지는 일 같다. 하지만 장거리 게임을 생각하면, 크게 중요하지 않다. 빨리 잊고 툭툭 털고 일어날 수 있는지가 더 중요하다. 얼마나 넘어졌는지가 아니라, 넘어지고도 그냥 다시 시작할 수 있는지, 그게 결과를 결정한다.</p>
<p>나에게 Just start over는 저런 생각을 압축한 3단어다. 물론 말이 쉽지 실천은 어렵다.</p>
<p>내가 하고 싶은 말은, *<em>확실히 좋은 습관이 있으면 &#39;Just Start Over&#39;가 쉬워진다는 것이다. *</em></p>
<p>커리어 전환, 취업 준비는 마치 삼진이 없는 타석에 서는 것과 같다. 상대는 프로 투수고, 변화무쌍한 공을 던진다. 우리는 계속해서 헛스윙을 할 것이다. </p>
<p>하지만 스트라이크가 없기 때문에 나를 타석에서 내릴 수 있는 것은 나밖에 없다. 그러니 내가 지치지 않고 계속해서 방망이를 휘두를 수 있는 게 중요하다.</p>
<p>경험상 &#39;빡세게 해야지!&#39; &#39;헛스윙해도 풀죽지 말자&#39; 이렇게 다짐하는 건 별로 오래가지 못한다. 그런 노오력보다는 차라리 운동 한번 하고, 명상 한번 때리는 게, 그것도 정 안 되면 일단 푹 자는 게, 훨씬 낫다.</p>
<p>이 마인드가 지난 10개월 간 나에게 정말 큰 도움을 줬다. 사람의 기분은 한번 바닥으로 가기 시작하면, 쉽게 악순환을 탄다. </p>
<p>넘어졌을 때 바닥을 막아주고, 다시 회복할 수 있게 도와주는 좋은 습관을 꼭 만들자.</p>
<blockquote>
<p>더 알고 싶다면, &lt;<a href="https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=134947105">우울할 땐 뇌과학</a>&gt; &lt;<a href="https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=246058716&amp;start=slayer">더 시스템</a>&gt;을 추천한다.</p>
</blockquote>
<h1 id="3-뚜껑을-열어보는-재미">3. 뚜껑을 열어보는 재미</h1>
<p>처음 떨어졌던 부트캠프는 잊고, 다른 부트캠프를 알아봤다. 결과적으로 <a href="https://codesquad.kr/">&#39;코드스쿼드&#39;</a>를 듣게 됐다.</p>
<p>2021년 11월, 5주 정도 진행했던 <strong>프리 과정(코코아)</strong>을 들었고, 처음 Swift를 배웠다. 1월부터 6월까지 <strong>6개월 동안 iOS 개발 마스터즈 과정</strong>을 다녔다.</p>
<p>초반 프리 코스는 꽤 재미있었다. GUI가 없는 아주 단순한 앱을 만들면서 Swift를 익혔다. 코로나 때문에 풀 온라인으로 진행되었다. 예상보다 빡세지도 않았다. (그래서 재미있다고 기억하는지도?)</p>
<p>코코아 과정에서 유난히 기억에 남는 한 순간이 있다.</p>
<blockquote>
<p>Swift의 모든 타입은 <code>struct</code>, <code>class</code>, <code>enum</code>으로 이뤄져 있다.</p>
</blockquote>
<p>이 문장을 봤을 때였다.</p>
<p>말로 설명하긴 어려운데, 되게 놀라웠다. 내장 타입도 다 미리 만들어둔 Named type일 뿐이구나. 뭔가 그 동안 배운 게 &#39;타탁&#39;하고 이해가 됐다. <strong>저 문장을 보는 순간이 되게 강렬했다.</strong></p>
<p>내가 단순 조작법만 알던 기계의 안쪽을 우연히 까보게 되었는데, 내부의 설계가 굉장히 심플하면서도 왜 이렇게 했는지 딱 이해되는 느낌이었달까?</p>
<p>소프트웨어가 하는 일은 엄청나게 복잡하다. 하지만 잘 설계한 소프트웨어들은 비교적 단순하다. 간단한 모듈들을 조합해서 복잡한 기능을 만들어낸다. 동시에 복잡한 조합 방법은 겉으로 드러내지 않는다. </p>
<p>Swift의 타입 시스템이 구현된 원리를 깨닫고 정말 신기했다. 그래서 그 때 “Swift의 모든 타입은 struct, class, enum으로 이뤄져 있다.”라는 문장을 크게 노트에 적어두었다. 아마 <strong>‘좋은 설계&#39;라는 걸 느꼈던 순간</strong> 중 하나인 거 같다. </p>
<p>난 문돌이치고는 <a href="https://velog.io/@eddy_song/system-programming-study">CS 공부를 꽤 즐기는 편</a>인데, 그것도 비슷한 재미가 있어서다. </p>
<p>내가 CPU 스케줄링을 만들거나, 소켓을 구현할 일은 거의 없다. 그냥 ‘좋은 개발자가 되려면 필요하다&#39;라면서 억지로 했으면 재미가 없었을 게 뻔하다.</p>
<p>하지만 나는 내가 아무 생각없이 쓰고 있는 *<em>그 기술의 뚜껑을 열어보는 게 재미있었다. *</em>실제로 어떻게 구조화되어있고, 설계되어있는지 이해했을 때 묘한 쾌감이 있다. (물론 이해 못하면 머리가 아프다) 덕분에 지루한 CS도 조금은 재밌게 공부했던 거 같다.</p>
<p>이런 순간을 여러번 거치면서 나는 확신이 쌓였다. 개발이 나랑 맞는 부분이 있구나.</p>
<p>프로그래밍은 단순히 주어진 작업을 절차대로 컴퓨터에게 시키는 일이 아니다. 원하는 작업을 하는 것은 기본이다.</p>
<p>나아가 어떻게 하면 단순하고 이해하기 쉬운 구조로 만들지 고민해야 한다. 모듈, 객체, 인터페이스를 구상한다. 중요한 것과 중요하지 않은 것을 판단해 추상화한다.</p>
<p>*<em>흔히 ‘설계’라고 부르는 부분이다. 나는 그런 쪽이 가장 흥미로웠다. *</em></p>
<ul>
<li>잘 설계된 인터페이스의 뚜껑을 열어보고 그 원리가 이해가 됐을 때</li>
<li>엄청나게 많은 디테일을, 영리한 방법으로 잘 숨겨놓고 조작 시에는 몰라도 되도록 만들었을 때. </li>
<li>같은 코드라도 훨씬 더 사람이 이해하기 좋은 체계적인 구조를 만들었을 때.</li>
<li>기존 코드를 그대로 두면서 새로운 모듈을 갈아끼워서 기능을 만들어낼 때.</li>
</ul>
<p>이런 순간에 짜릿함을 느끼는 성격이었다.</p>
<p>동시에 이건 <strong>‘글쓰기랑 비슷하다’</strong>는 생각이 들었다. </p>
<p>문법에 맞게 정보만 넣는다고 좋은 글이 아니다. 같은 글이라도 수없이 다양한 방식으로 구조화하고 전달할 수 있다. </p>
<p>읽는 사람들의 생각과 감정을 고려해서, 그 사람들을 설득하거나 울림을 줄 수 있도록 <strong>구조와 스토리를 짜는 것</strong>, 그게 <strong>진짜 글쓰기 실력</strong>이다.</p>
<p>나는 글쓰기를 업이자 취미로 해온 사람이라, 이 깨달음이 ‘내가 개발의 어떤 측면을 재밌어하고, 어떤 면에 강점이 있구나.’ 확신이 생기는 데 큰 도움을 줬다.</p>
<p>(이 내용은 &#39;<a href="https://velog.io/@eddy_song/pleasure-and-sorrow">개발의 기쁨과 슬픔</a>&#39;에 쓴 적이 있다.)</p>
<h1 id="4-극도의-자율성">4. 극도의 자율성</h1>
<p>그렇게 프리(코코아)를 과정을 마치고** 본 게임인 마스터즈**로 넘어갔다.</p>
<p>코드스쿼드 마스터즈 과정은 <strong>‘CS10’</strong>으로 시작한다. <strong>10개의 Computer Science 주제를 5주 동안 압축적으로 배우는 기간</strong>이다. (옛날에는 CS30이었다가 줄였다나..) </p>
<p>이 때를 생각하면 좀 혼란스럽고, 벙쪘던 기억이 난다. </p>
<p>일단  부트캠프 전체가 온라인으로 진행되었는데, 익숙하지 않은 환경에 아직 동기들과 어색한 때였다. </p>
<p>게다가 과제들이 만만치 않았다. 나는 이제 겨우 이차원배열을 다룰 수 있는 수준이었는데. </p>
<p>커널의 메모리 할당을 시뮬레이션해라. 
도커를 설치해서 원리를 설명해봐라. 
간단한 소켓을 구현해봐라. 
(+ 이틀 안에 해라)</p>
<p>CS10 내내 계속 머리 위에 물음표를 띄우고 있었던 거 같다.</p>
<ul>
<li>어느 정도까지 물어봐도 되는 걸까?</li>
<li>이 과제는 내가 어느 정도의 시간을 써야할까?</li>
<li>어떻게 접근해서 이 문제를 해결해야할까?</li>
<li>다른 사람들은 별 말이 없네… 다 잘 풀고 있는 건가?</li>
</ul>
<p>지금 다시 보면 이 과제들이 잘 만들어졌다는 생각이 든다. 하지만 그때는 어렴풋한 느낌만 받을 뿐 제대로 뭔가를 이해하진 못했던 거 같다. (물론 마스터는 &#39;맛만 보는 거&#39;라고 강조하긴 했다.)</p>
<hr>
<p>이쯤에서 코드스쿼드의 교육 방식에 대해서 잠깐 언급하고 넘어가자.</p>
<p>내 생각에 코드스쿼드는 <strong>‘극도의 자율성&#39;을 추구하는 교육 기관</strong>이다.</p>
<p>부트캠프라고 하면 막 스파르타 재수학원 같은 빡센 이미지를 떠올리시는 분도 있다. </p>
<p>하지만 코드스쿼드는 그렇진 않다. 억지로 무언가 시키는 게 거의 없다. 하는 것도 자유. 안 하는 것도 자유다. </p>
<p>그러니 쉽게 말해 ‘하기 나름’이다. 자기가 어떻게 하느냐에 따라 경험이 너무나 달라진다.</p>
<p>주어진 과제를 스스로 해결하고, (비슷한 수준의) 동기들과 배운 것, 삽질한 것을 공유하는 과정이 메인이다. 철저한 문제 기반 학습이다. </p>
<p>최소한의 틀은 주지만, 시간을 어떻게 쓸지, 어떤 방식으로 공부할지.. 다 자율이다.</p>
<p>과정에 강의 시간도 있고, 질문도 충분히 할 수 있다. </p>
<p>하지만 ‘이건 이렇게 하세요.’ ‘이건 몰라도 돼요.’ 이런 명쾌한 답은 절대 오지 않는다. 오히려 <strong>질문을 하면 더 큰 맥락을 알려주시거나, &#39;이런 것도 고민해보세요&#39;라며  또 다른 질문을 안겨서 돌려주신다. 소크라테스 식 문답법이 떠오른다.</strong></p>
<p>흔히 학원 광고를 보면 나오는 문구가 있다. 
‘물고기를 잡아주는 것이 아닌, 물고기 잡는 법을 가르칩니다&#39; 라고.</p>
<p>코드스쿼드는 ‘물고기를 잡는 법’을 가르쳐주지 않는다. 
그냥 <strong>물고기가 있는 야생의 바다에 뗏목을 띄워준다.</strong> 그리고 ‘자, 이제부터 각자 잡아보자. 모르는 거 있으면 서로 도와주고!’ 하는 곳이다.</p>
<p>코드스쿼드의 마스터들이 불친절하다는 게 아니다. 코드스쿼드의 교육 철학이 그렇다. </p>
<p>‘야생에서 물고기 잡는 법을 스스로 익힐 수 있어야 진짜 그게 실력이 된다’ 부트캠프 내내 그런 조언을 정말 많이 듣는다.</p>
<p>내가 다녀본 것은 한 곳 뿐이니까 좋다 나쁘다 하긴 어렵지만, 다행히 나는 그게 잘 맞았다. ‘자율과 책임&#39;을 사랑하는 사람이기에, 그런 철학이 마음에 들어서 갔다. 어느 정도 예상하고 있었다. </p>
<p>하지만 분명한 건, 모든 사람에게 &#39;극도의 자율성&#39;이 잘 맞는 건 아니다. 스스로 모든 걸 결정하고 실행해야하는 상황이 절대 쉽지는 않다. 코드스쿼드를 내년에 지원하는 분이 있다면, 이 점을 꼭 알고 가시라는 말을 하고 싶다.</p>
<hr>
<p>아무튼 CS 10 5주가 지나자 iOS 동기들이랑은 꽤 친해졌다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/dfa25f5a-6a0a-4eae-9c89-3a3d5eb84356/image.PNG" alt=""></p>
<p>(처음에 친해지려고 개더타운에 모여서 게임도 함)</p>
<p>코드스쿼드의 학습 스타일에도 조금씩 적응이 됐다. 무사히 CS10을 마치고 다음 단계로 넘어갈 수 있었다.</p>
<h1 id="5-velog-1위">5. Velog 1위</h1>
<p>깜짝 놀랐다. 신기해서 몇 번이고 새로 고침을 해봤다. 여전히 내 글이 Velog 메인 가장 위에 떠 있었다. </p>
<p>누가 볼 거라고 기대한 글은 아니었는데, 그저 내가 이해하고 싶어서 쓴 글인데. 이게 터질 줄이야? </p>
<p>이 날이 개발 블로그의 재미를 알게 된 날이었던 거 같다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/69f93f68-6d10-4a2e-bc73-f42231893e61/image.PNG" alt=""></p>
<p>내가 개발 블로그를 진지하게 해야겠다고 마음먹은 건 1월쯤이었다. 내가 <strong>커리어 전환하면서 가장 잘한 선택 중 하나라고 생각</strong>한다. </p>
<p>모든 사람이 하기엔 힘들다는 건 알지만, 개인적으로 굉장히 추천한다.</p>
<p>일단 취업 및 커리어에 도움이 된다. 내가 봤던 *<em>모든 면접에서, 개발 블로그 인상깊게 봤다라는 언급을 여러 번 들었다. *</em></p>
<p>(물론 내가 이력서에 블로그를 강조해놔서 그랬겠지만. 하지만 그게 어디인가. 신입이 쓸 경력도 없는데 블로그라도 자랑해야지.)</p>
<p>내가 뭐 대단한 개발자도 아닌데, <strong>출판/기고 문의</strong>도 꽤나 받았다. 지금은 그럴 레벨이 아니라고 생각하지만, 앞으로 커리어 기회로 연결되는 게 진짜 가능하구나 느꼈다.</p>
<h3 id="쓰려다보면-생각이-생긴다">쓰려다보면 생각이 생긴다</h3>
<p>하지만 이것보다 더 중요한 이유는 따로 있다. <strong>내가 글을 쓰면서 배우기 때문</strong>이다.</p>
<p>처음 Velog에서 트렌딩 1위를 한 <a href="https://velog.io/@eddy_song/alan-kay-OOP">‘앨런 케이가 생각하는 객체 지향의 본질&#39;</a>이라는 글이 있다. 이 글을 쓰면서 정말 많이 배웠다.</p>
<p>그전까지는 객체 지향의 여러 용어들이 머릿속에서 자리잡지 못하고, 다 따로 놀았다. 뭔가 쉬운 말을 꼬아놓은 거 같기도 하고, 서로 충돌되는 것 같기도 했다. </p>
<p>일단 글로 써보기로 했다. 도대체 객체 지향을 어떻게 이해해야 하는지, 그냥 내 말로 풀어써보기로 했다.</p>
<p>그러면서 앨런 케이에 대해서 알게 되었다. 그의 인터뷰까지 찾아서 읽었다. 그걸 정리해 글을 쓰면서 그 전까지 들었던 아리송한 말들이 딸깍하고 맞춰지는 ‘아하 모먼트’를 겪었던 게 생각난다.</p>
<blockquote>
<p>“생각이 있어서 쓰는 것이 아니라, 뭐라도 쓰려다보면 생각이 생긴다&quot; </p>
</blockquote>
<p>나는 이 말을 좋아한다. (사실 내가 만든 말이다) </p>
<p>지금 이 회고도 내가 머릿속에서 이 모든 생각을 하고 있었던 게 아니다. 파편적인 생각들을 글이라는 논리적인 형태로 묶고 정리하려고 노력하다보니 나오는 거다. ‘내가 이런 생각을 하고 있었다고?&#39; 싶은 정도로 새로운 말이 나온다.</p>
<h3 id="꼭-글이-아니라-남한테-설명을-해보는-것도-좋다">꼭 글이 아니라, 남한테 설명을 해보는 것도 좋다.</h3>
<p>내 머릿속에선 다 이해된 것 같지만, 다른 사람한테 설명이 잘 나오지 않을 때가 있다. 그만큼 내가 완벽하게 이해하고 있지 못하다는 뜻이다.</p>
<p>기억나는 장면이 하나 있다. 3월쯤이었나. </p>
<p>코드스쿼드에서 처음으로 MVC에 대해서 배우고, 거기에 맞게 역할을 나누고 구조를 짜는 연습을 했다.</p>
<p>나도 어느 정도 이해는 했는데, 완벽하게 알겠다 싶진 않았다. </p>
<p>그 때 다른 동기가 MVC에서 막혀서 괴로워하고 있었다. 왜 다른 사람한테 물어보지 않았냐 하니까 “그러기엔 내가 나 스스로 해결하지 못해서 너무 의존적인 거 같고, 다른 사람들한테 민폐될 거 같아서&quot; 라는 답이 돌아왔다.</p>
<p>점심시간 1시간 반인가를 빼서 개더 타운에서 동기들과 같이 질의응답을 했다. (알고보니 다른 사람들도 똑같은 문제로 고민하고 있었다.) </p>
<p>그 친구를 도와주고 싶었고, 거기에 더해서 나도 더 이해하고 싶었다. 나도 MVC를 잘 안다고 할 수는 없었다. 온라인 화이트보드까지 동원해가면서 최대한 쉽게 MVC를 내가 이해한 방식으로 설명하려고 했다. 오히려 내 지식이 단단해지는 걸 느꼈다.</p>
<p>사람들은 시간 내서 설명해줘서 고맙다고 하는데, <strong>솔직히 제일 도움이 되는 사람은 나였다.</strong> 그 후로도 기회가 있으면 다른 사람들한테 내가 아는 것을 시간 내서 설명하려고 했다. </p>
<p>그건 동기들을 도와주려는 마음도 있지만, 결국 내가 공부가 잘 되기 때문이었다.</p>
<h3 id="아웃풋-중심으로-공부하기">아웃풋 중심으로 공부하기</h3>
<p>누군가 나에게 개발 공부를 잘하려면 어떻게 해야 하냐, 라고 물어본다면 이렇게 답할 거 같다.</p>
<blockquote>
<p>‘아웃풋&#39; 중심으로 공부하기</p>
</blockquote>
<p>흔히 공부라고 하면 책을 읽고, 강의를 듣는 인풋 행위라고 생각한다. 그리고 절반 이상의 시간을 거기에 쓴다. </p>
<p>하지만 나는 인풋보다 아웃풋에 시간을 많이 쏟으려고 노력했다. 서툴더라도 쓰고, 만들어보고, 더올려보고, 설명해보는 아웃풋 방식이 훨씬 더 효과가 좋다고 생각하기 때문이다. (더 알고 싶다면 <a href="https://www.learningman.co/output/">이 글을 참고</a>하자)</p>
<p>아무튼 개발 블로그, 그래서 추천한다. 근데 여기까지 써놓고 보니 뭐 개발 블로그 좋은 거 누가 모르나? 싶다. 사실 진짜 어려운 건 실제 글을 쓰는 일이다.</p>
<p>하지만 개발 블로그를 쓰는 건 굉장히 힘들고 고된 작업이기도 하다. 꾸준히 쓰기 위해서 내가 배운 점은 다음 2가지다. (이거에 대해서는 나중에 다른 글에서 얘기를 해보자.)</p>
<ol>
<li>혼자서는 절대 오래가지 못한다.</li>
<li>가볍게 자주 써야 한다.</li>
</ol>
<h1 id="6-선배에게-도움-구하기">6. 선배에게 도움 구하기</h1>
<blockquote>
<p>안녕하세요, OO! 블로그 글 잘 봤습니다. 주말에 다시 한번 들어가서 보는데 좋다. 요즘 블로그 열심히 쓰시는 거 같아요 ㅎㅎ
혹시..! X월 중에 시간이 되시면 줌으로 커피챗 한번 하는 거 괜찮으실까요?
요즘 배워야 할게 너무 많아서 힘들기도 하고, 취업이라는 목표에 잘 맞춰서 가고 있는지도 고민이 되어서 OO는 어떠셨는지 얘기 나눠보고 싶습니다!</p>
</blockquote>
<blockquote>
<p>OO 안녕하세요. 코드 리뷰하느라 고생 많으셨습니다! 리뷰 열심히 해주셔서 정말 도움이 많이 됐어요!
다름이 아니라 혹시 시간 되시면 줌으로 커피챗 한번 괜찮으실지 물어보려고요 ㅎㅎ
이제 코드스쿼드 수료도 얼마 안 남았고... 문득 지금 제가 하고 있는 노력이, 목표와 잘 방향이 맞춰져있는지도 고민되기도 해서요.
OO는 어떠셨는지, 또 현업에서는 어떤 고민하고 계신지 가볍게 얘기 나눠보고 싶었습니다 :)</p>
</blockquote>
<p>그 때 내가 코드스쿼드 선배들한테 보냈던 DM이다. </p>
<p><strong>코드스쿼드는 학원이 아니라 커뮤니티에 가깝다.</strong> 슬랙에는 모든 기수가 다 들어와있고, 이런 요청을 해도 대부분의 사람들이 친절하게 받아주는 편이다.</p>
<p>부트캠프가 절반쯤 지나가자 정신적으로 힘든 일들이 잦아졌다. 배워 내려가면 갈수록 새로운 배울 것들이 화수분 처럼 등장하고, 부트캠프의 끝이 다가오고 있음을 느끼면서 조급해지기 때문이다. </p>
<p>이럴 때 물어보거나 고민 상담할 사람 없으면 정말 힘들다. 이왕 돈 내고 부트캠프에 온 거, 앞서서 이런 고통을 겪은 선배들과 최대한 많이 얘기를 나눠보고 싶었다.</p>
<p>저런 식으로 DM을 보냈다. 일면식도 없지만 모두들 선뜻 시간을 내주었다. 대부분은 1-3년차의 주니어 개발자들이었다. </p>
<p>물론 코드스쿼드에는 수십 년 내공을 자랑하는 마스터가 있지만, 오히려 나랑 비슷한 환경에서 살짝 앞서 있는 사람과는 말이 잘 통할 때가 많다.</p>
<p>1-3년차 분들은 <strong>훨씬 더 솔직하고 실전적인 얘기</strong>를 많이 해준다. </p>
<p>대기업 취업이 목표라면 그것보단 이걸 하는게 맞다, 이 라이브러리는 꼭 학습해둬야 할 것 같다, 이 회사는 코테 난이도가 어땠다, 지금부터 아예 이력서를 많이 넣어봐야 유리하다, 그런 얘기들. <strong>실제로 취업 전략을 짜는데 꽤 도움이 많이 되었다.</strong></p>
<p>반 20등이 전교 1등한테 설명듣는 거보단 같은 반 10등 친구한테 설명 듣는게 더 와닿는 느낌이랄까?</p>
<p>(이 자리를 빌어 그 때 저랑 커피챗해주신 개발자 선배/지인 분들에게 감사...🙏)</p>
<p>그렇지만 너무 많이 의존하는 것도 좋지는 않다. </p>
<p><strong>나중에는 좀 혼란스럽기도 했다.</strong></p>
<p>개인적인 경험을 기반으로 애기해주는 거니까, 서로 완전히 반대의 말을 하기도 한다. </p>
<p>어떤 순간에는 내 방향을 정해서 나름 가고 있는데, &#39;자기는 이렇게 할 것 같다&#39;면서 얘기하면 괜히 내가 흔들리기도 했다.</p>
<p>그들의 말이 객관적이고 옳으니까 들어야 한다는 태도는 지양하는 게 좋다. 오히려 지금 생각하니 감정적인 도움이 컸다. </p>
<p>‘나만 이런 고민하는 거 아니구나&#39; ‘00에 간 개발자들도 다 비슷하구나&#39; 뭐 이런 것들? </p>
<p>계속 취준만 하다보면 조급함에 시야가 좁아지기 마련이다. 내가 몰랐던 회사나, 취업 전략에 대해서 시야를 넓힌다.. 그렇게 접근하면 좋겠다.</p>
<p>(물론 부트캠프 과정을 하면서 가장 서로 의지가 되는 건 동기다. 하지만 굳이 말 안해도 동기끼리는 소통을 많이 하게 되니까 생략...)</p>
<p>만약 취업/개발 공부 때문에 고민이 많다면, (낯을 가리는 성격이라 하더라도) 꼭 <strong>선배 개발자들에게 컨택을 해보기를 추천</strong>한다. </p>
<p>물론 예의와 성의는 필수. 그들의 시간은 공짜가 아니기에 기프티콘이나 감사 인사 정도는 당연히 챙기자.</p>
<h1 id="7-압도감">7. 압도감</h1>
<blockquote>
<p>아, 해야할 게 너무 많다.</p>
</blockquote>
<p>5월이 되면서, 이 말을 거의 입에 달고 살았다. </p>
<p>아는 것이 하나 쌓일 때마다, (모르는 줄도 몰랐던) 모르는 것이 3개씩 쌓이는 느낌이었다.</p>
<p>‘<a href="https://www.thinkful.com/blog/why-learning-to-code-is-so-damn-hard">왜 개발을 배우는 것은 그렇게 힘든가</a>’라는 유명한 글이 있다. 이 글에서는 프로그래밍 입문자가 거치는 4가지 단계를 설명한다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/d77ef24b-369b-4ea5-ba2a-a36ab17aa018/image.jpeg" alt=""></p>
<p>3단계가 ‘절망의 사막(Desert of Despair)&#39;이다. 이 시기 <strong>딱 내 느낌이 3단계</strong>였다. </p>
<p>그 전에는 뭘 모르는지 몰랐다. 보이는 게 많이 없었다. 하지만 조금씩 지식이 늘어나면서, 내가 뭘 모르는지 알게 된다. </p>
<p><strong>갑자기 공부할 것들이 폭발적으로 늘어나는 듯 보였다. 그에 비해 내 실력은 너무나 작고 더디게 자라는 것처럼 느껴졌다.</strong></p>
<p>이 때는 이동할 때, 쉴 때도 폰으로 뭔가를 계속 찾아봤다. </p>
<p>개발 커리어를 조언하는 유튜브 영상... 미디엄에 올라오는 ‘내가 주니어일 때 알았다면 좋았을 것들&#39; 같은 아티클... ‘앱 개발자가 알아야할 X가지 기술 키워드’…</p>
<p>끊임없이 찾아봤다. 코딩도 하루에 10시간 가까이 하고 있었다. 하지만 코딩을 안 하는 시간에도 항상 코딩에 대한 무언가를 검색하고, 훑어보고, 스크랩하고 있었다.</p>
<p>물론 그런 걸 보면 볼수록, 내가 <strong>뭔가 얻어간다기보다는 그냥 ‘들어본 것&#39;만 많아졌다.</strong> 속으로는 그런 행동이 
도움이 안 된다는 걸 알았지만, 불안하니까 계속 그러고 있더라.</p>
<p><strong>이 시기에 서류 전형도 진짜 많이 떨어졌다.</strong> 경험도 쌓을 겸 이곳 저곳의 채용 공고에 지원했다. 진짜 가을 낙엽처럼 우수수 떨어지더라. 2달간 20개 가량 떨어졌던 거 같다.</p>
<p>스타트업은 신입을 원래 잘 안 뽑으니까. 타이밍이 안 맞았겠지. 아직 이력서가 안 다듬어져서 그럴 거야. </p>
<p>이런 식으로 생각을 해보지만, 불합격 이메일이 올 때마다 조급함이 더해지는 건 어쩔 수가 없었다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/88ee725a-c545-497a-97be-13b24db57ec5/image.png" alt=""></p>
<p>*<em>그렇게 몇 주가 지났다. 자존감이 바닥을 찍는 느낌이 왔다. *</em></p>
<p>난 멘탈에 기복이 크지 않은 성격인데, 이 시기에는 꽤나 힘들었다.</p>
<p>계속 나 스스로를 평가하면서, 내가 정한 기준에 내가 못 미친다는 감정이 심해져갔다. 계속 나를 갉아먹는 느낌이었다. </p>
<p>이 때는 사람들 만나는 것도 스트레스였다. (참고로 나는 외향형이다.) 요즘 뭐하고 있어? 라는 얘기조차 듣기가 싫었다.</p>
<p>그러다가 친한 동생에게 그때 상태를 털어놓았다.</p>
<blockquote>
<p>형 그건 좀... 강박 증상인데?</p>
</blockquote>
<p>그 친구의 말에 띵-한 느낌이 들었다. </p>
<p>그 전까지는 내가 그 ‘감정&#39; 자체였다. 내가 어떻게 느끼고 있는지 잘 인식하지 못했다. </p>
<p>‘나 강박인가?’ 라고 생각해보니 갑자기 제 3자의 시선으로 날 보게 됐다.</p>
<blockquote>
<p>음. 그렇구나. 내가 많이 조급해하고 있구나.</p>
</blockquote>
<p>그 때부터 잠깐 내려놓고 찬찬히 생각해보기 시작했다.</p>
<blockquote>
<p>왜 이런 감정이 일어날까?</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/29a62eab-ae4b-4ac6-aa3a-6cd36a384110/image.jpeg" alt=""></p>
<p>내 생각에 원인 중 하나는 이거였다. </p>
<p><strong>너무 ‘최적 경로&#39;에 대해 생각을 많이 하고 있었다.</strong></p>
<p>나는 뭔가 내 앞에 로드맵을 그리고 싶었다. ‘개발자가 된다&#39; 목표를 향한 최적 경로를 찾고 싶었다.</p>
<p>그 과정을 온전히 컨트롤하고 싶었다. 내가 어디로 잘 못 가지 않는지, 최선의 길로 가고 있는지 끊임없이 물었다.</p>
<p>평소에 내가 그 정도로 컨트롤 프릭(Control freak)은 아니었지만. 개발자로 커리어 전환이 나에게 상당한 리스크를 건 모험이라고 느껴져서 그랬던 거 같다. </p>
<p>&#39;나는 늦게 시작해서 시간이 없다&#39; 
&#39;빨리 끝내고 좋은 결과를 내야한다&#39;
이렇게 보채는 마음이 강했다. </p>
<p>아무리 내가 로드맵을 그리고 싶어한다고 해도, 소프트웨어 개발이라는 거대한 광야는 그런 로드맵이 쉽게 보이는 크기가 아니다. </p>
<p>취업이란 목표를 네비에서 찾는다고 나올리도 없다. </p>
<p>게다가 그 앞에는 너무나 많은 변수가 있다. 항상 불확실성은 있을 수밖에 없다. 이건 팩트다.</p>
<p>그런데도 나는 그 앞에서 나침반과 지도를 들고, <strong>어떻게든 내가 제대로 가고 있다는 걸 끊임없이 확인</strong>하려고 했다. 그러다보니 오히려 발이 꼼짝없이 바닥에 붙어버리곤 했다. </p>
<p><strong>어차피 뭔 길로 가도 마라톤</strong>인 건 분명했는데, 그 사실에 자꾸 <strong>압도되어버렸다.</strong></p>
<p>아예 코딩을 안하고 하루 정도 조용히 쉬면서 이런 생각을 정리했다. 객관적으로 내 정신 상태를 좀 파악한 느낌이 들었다. 조급합이 많이 나아졌다.</p>
<p>그 때부터 <strong>행동 편향을 가지려고 노력</strong>했다. 나는 항상 계획, 전략을 찾는 성향이기 때문이다. 의식적으로 반대 편향을 만들어줄 필요가 있었다.</p>
<p>뭔가 생각이 많아지면서 발이 바닥에 붙는 느낌이 날 대마다, ‘일단 코드 한 줄이라도 치자’ ‘일단 커밋 한개라도 하자&#39;를 계속 되뇌었다. 그렇게 눈앞에 있는 일을 하나 꺼내면 좀 발이 가벼워졌다.</p>
<p>물론 그렇다고 만병통치약 먹은 듯 불안감이 싹 사라졌느냐. 그런 건 당연히 아니었다. </p>
<p>웃긴 건, <strong>만병통치약은 따로 있었다</strong>는 거다. 6월 말에 첫 회사에서 <strong>합격 메일</strong>을 받았다. 그거 받고 나서는 마음이 어찌나 편하던지. 사람 마음이 참...</p>
<blockquote>
<p>그러니까 여러분이 문제가 아니고 그냥 취준이 문제입니다. 대한민국 취준생 모두 화이팅.</p>
</blockquote>
<h1 id="8-토스">8. 토스</h1>
<p>그냥 ‘밑져야 본전&#39;이라는 생각이었다. </p>
<p>신입 채용을 잘 안하는 회사라고 알고 있었다. 게다가 난 이미 첫 회사에 합격한 상태였다. </p>
<p>엄청난 기대는 하지 않았지만, 면접은 한번 꼭 보고 싶었다. <strong>전부터 가장 가고 싶었던 회사였기 때문</strong>이다.</p>
<p>그냥 하는 말이 아니라, 난 오래전부터 토스 서비스의 팬이었다. </p>
<p>금융업을 보면, ‘꼭 이렇게 해야하나?’ 싶은 것들이 참 많다. 조금만 개선하면 될 거 같은데, 왜 이렇게 하지? 싶은 앱이 많다. 그런 게 바뀌지 않는 이유는, 금융업계에는 항상 암묵적인 선들이 있고, 누구도 처음으로 선을 넘는 사람이 되고 싶어하지 않기 때문이다.</p>
<p>하지만 토스 같은 회사들은 더 편리한 서비스를 위해 그 선을 계속 넘는다. 금융감독원은 싫어하겠지만, 난 그런 모습을 좋아하고 공감한다. (내가 핀테크 도메인에 관심이 많은 이유이기도 하다.)</p>
<p>문화도 나랑 잘 맞을 것 같았다. 지인 중에 토스 전/현직자 분들이 꽤 있어 대화를 많이 나눠봤다. 회사가 일하는 방식과 문화도 어느 정도 알고 있었다. </p>
<p>무튼 그런 이유로 지원을 했다. </p>
<h3 id="코딩-테스트">코딩 테스트</h3>
<p>코딩테스트를 봤다. 카카오나 네이버보다는 좀 쉽다고 느껴졌다... 라고 생각했는데 2문제밖에 풀지 못했다. 당연히 떨어졌을 줄 알았다. 근데 합격 연락이 왔다. </p>
<p>코딩 테스트뿐만 아니라 iOS와 Swift에 관한 서술형 및 객관식 문제도 있었다. 아마 그 부분에서 추가 점수를 많이 받은 게 아닌가 싶다.</p>
<h3 id="1차-기술-면접">1차 기술 면접</h3>
<p>1차 기술 면접은 굉장히 뎁스있는 질문으로 이뤄졌다. 인터넷 검색했을 때 나오는 뻔한 질문은 다 스킵한 느낌이었다. (뻔한 질문도 열심히 준비했는데...ㅠ)</p>
<p>질문의 난이도가 굉장히 높았는데, 솔직히 좀 이것까지 알아야 하나? 싶은 디테일한 부분도 물어봤다.</p>
<p>면접 과정에서 &#39;그 지식을 아느냐?&#39; 보다 &#39;면접관과 말이 통하면서 그럴듯한 추론을 하느냐&#39;를 본다는 게 확실히 느껴졌다. </p>
<p>미리 알아서 풀 수 있는 문제가 아닌, 갖고 있는 지식을 활용해서 추론을 해보라는 식의 문제였다. 질문을 편하게 하고 힌트를 요청할 수 있는 분위기였다. </p>
<p>뭘 알고 있는지 체크한 느낌이 아니라, 같이 토론한 느낌이어서 면접 경험이 꽤 좋았다.</p>
<h3 id="2차-문화-면접">2차 문화 면접</h3>
<p>2차 컬쳐 핏 면접도 좋은 경험이었다. </p>
<p>토스에서 추구하는 8가지 가치와 관련된 질문이 많이 나왔다. 아마 본인이 일의 진심인 사람이라고 생각한다면, 어려움 없이 없이 넘어갈 수 있지 않을까 싶다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/266d24ff-e5ec-41e6-96c2-4ae0d63293a7/image.png" alt=""></p>
<p>무엇보다 좋은 건, <strong>결과를 엄청 빨리 알려줬다</strong>는 거다. 공식적으로 결과는 3-5 영업일 후에 알려준다고 되어있지만, 검토가 빨리 끝나면 그냥 바로바로 알려주는 것 같다.</p>
<p>합격 이후 프로세스도 세심하게 설계한 게 느껴진다. (아직 온보딩 프로세스를 다 하진 않았다.)</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/0d1dfc25-fe4d-425d-9618-a0920f189c68/image.png" alt=""></p>
<p>그 중 하나로 합격 축하 꽃, 손글씨(느낌 프린트) 편지가 왔다. (부모님이 좋아하셨다.) </p>
<p>지원자에게 신경을 많이 써준다고 느꼈다. 일반 채용이 마트 쇼핑이라면, 토스 채용은 뭔가 백화점 쇼핑 느낌.</p>
<h1 id="9-성장중입니다">9. 성장중입니다</h1>
<p>몇달 전, iOS 동기 J가 나에게 이런 말을 해주었다. </p>
<p>자기는 프리 과정할 때부터 항상 뒤쳐진다고 느꼈고, 그래서 많이 힘들었다고 한다. </p>
<p>그러던 J가 회고 시간에 &#39;그래도 1달 전을 생각해보니까 그때보단 쫌 나아진 거 같네요.&#39;라고 한 적이 있었다. 그 말에 내가 &#39;성장중입니다🔥&#39;라고 줌에 채팅을 쳤다.</p>
<p>J는 그걸 보고 웃었다. 그날 그 말이 되게 와닿아서 캡처해서 저장을 해뒀다고 한다. 그 캡처를 힘들 때마다 봤다고.</p>
<p>난 별 생각 없이 한 응원일 뿐이었는데, 다른 사람에게는 큰 의미가 있었다니 기분이 묘했다. 오히려 나한테 무척 기억에 남는 말이 되었다. </p>
<blockquote>
<p>성장중입니다🔥</p>
</blockquote>
<p>지금도 개발자가 되기 위해 노력하고 있는 분들에게는, 무슨무슨 취업 팁이라고 조언을 늘어놓는 것보다, 사실 저 말이 더 필요하지 않을까.</p>
<blockquote>
<p>지금은 허우적거리는 것 같아도, 여러분은 분명 성장중입니다!</p>
</blockquote>
<p>P.S. 마지막으로 6개월 동안 길잡이 역할을 해준 JK &amp; 코드스쿼드와, 지금도 열심히 살고 있을 코드스쿼드 동기들에게 고맙다는 말을 하고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로세스들과 바람피는 운영체제]]></title>
            <link>https://velog.io/@eddy_song/process</link>
            <guid>https://velog.io/@eddy_song/process</guid>
            <pubDate>Tue, 30 Aug 2022 11:09:40 GMT</pubDate>
            <description><![CDATA[<p>운영체제를 이해하기 위해 필수적인 개념들을 하나씩 살펴보고 있다. 이전 글에서 &#39;파일&#39; 얘기를 했다. 오늘은 &#39;프로세스&#39; 얘기를 해보자.</p>
<p>프로세스는 많이 들어봤을 것이다. 그치만 여러번 들어도 아리송한 개념이다. 워낙 추상적이기 때문이다. </p>
<p><strong>프로세스 및 관련 키워드를 최대한 쉽게 *<em>설명하려고 노력해보았다. 이 글을 읽고 나면 *</em>프로세스에 대한 감을 잡고, OS를 이해하는 탄탄한 기초를 만들 수 있을 것</strong>이다.</p>
<h1 id="프로세스는-호텔에-체크인한-고객">프로세스는 ‘호텔에 체크인한 고객’</h1>
<p>초기 컴퓨터는 한번에 하나의 프로그램만 실행했다. 한 프로그램이 전체 컴퓨터 시스템을 사용했다. 비유하자면 한 사람이 집 전체를 빌려쓰는 전셋방이었던 셈이다. 세입자 한명이 짐을 빼기 전까지는 다른 세입자가 들어올 수 없었다.</p>
<p>그 후 컴퓨터의 활용도를 높이기 위한 발전이 이뤄졌다. 1970년대 이후부터 거의 모든 컴퓨터 시스템은 <strong>한 번에 여러 개 프로그램을 같이 실행</strong>할 수 있었다. &#39;멀티 프로그래밍&#39;이 가능해졌다.</p>
<p>멀티 프로그래밍 시스템에서는, 컴퓨터의 메모리 안에 여러개의 프로그램이 같이 저장된다. CPU는 각 프로그램의 명령어를 번갈아가면서 실행한다.</p>
<p>컴퓨터가 &#39;전셋방&#39;에서 &#39;호텔&#39;로 진화한 것이다!</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/94a1ea24-4f6e-4daa-8160-e9be280cf83f/image.jpeg" alt=""></p>
<p>전세방일 때는 그냥 자기맘대로 집을 쓰면 됐다.</p>
<p><strong>하지만 호텔이 되자 새로운 문제가 발생했다.</strong> 수많은 사람이 동시에 쓰는 시설이 되었기 때문이다.</p>
<p>예를 들어, 여러 프로그램이 서로 충돌하지 않도록 보호해야했다. 각 프로그램이 필요할 때 효율적으로 하드웨어 자원을 배분해야 했다. 어떤 프로그램이 시설을 사용할 수 있는지 없는지 권한을 설정해야 했다.</p>
<p>다시 말해, <strong>&#39;호텔 관리자&#39;가 필요</strong>해졌다. 호텔 관리자는 많은 일을 한다. 호텔 시설/서비스를 효율적으로 여러 고객에게 전달하기 위해서다. </p>
<p><strong>컴퓨터의 &#39;호텔 관리자&#39;가 바로 운영체제(OS)다.</strong></p>
<p>&#39;호텔 관리자&#39;는 고객이 들어오면 &#39;체크인&#39;을 한다. 방을 배정해준다. 고객 정보를 시스템에 등록한다. 해당 고객에게 ID를 부여한다. (&#39;202호 고객&#39; 같은 식으로) 그래야 관리가 편하기 때문이다.</p>
<p>마찬가지로 <strong>프로그램도 실행하면 &#39;체크인&#39; 과정을 거친다.</strong> 구체적으로 말하면, OS가 메모리를 배정한다. 디스크에 있던 프로그램이 메모리로 불러온다. 시스템 서비스를 사용할 수 있도록 준비시킨다. </p>
<p>&#39;체크인&#39;을 마친 프로그램에 OS는 번호(process id)를 붙인다. 그래야 관리가 편하기 때문이다. </p>
<p>이렇게 <strong>OS가 관리 중인 프로그램, 실행 중인 프로그램을 &#39;프로세스&#39;</strong>라고 부른다.</p>
<blockquote>
<p>&#39;운영체제라는 관리자&#39;가 운영하는, 
&#39;컴퓨터라는 호텔&#39;에, 
&#39;체크인한 고객&#39;이 바로 프로세스다.</p>
</blockquote>
<h1 id="프로그램과-프로세스는-뭐가-다르지">프로그램과 프로세스는 뭐가 다르지?</h1>
<p>&#39;프로그램&#39;과 &#39;프로세스&#39;는 헷갈리기 쉽다. 한번 더 짚고 넘어가자.</p>
<h2 id="소스-코드-➡️-프로그램">소스 코드 ➡️ 프로그램</h2>
<p>다음과 같은 C 코드가 있다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int main()
{
    printf(&quot;hello, world\n&quot;);
    return 0;
}</code></pre>
<p>C 언어를 몰라도 상관없다. &quot;Hello, world&quot;를 출력하고 종료하는 단순한 코드니까.</p>
<blockquote>
<p>이 코드는 &#39;프로그램&#39;일까?</p>
</blockquote>
<p>엄밀히 말해 <strong>이 코드는 &#39;아직&#39; 프로그램이 아니다.</strong> 그저 텍스트가 담긴 &#39;hello.c&#39; 파일일 뿐이다. &#39;hello.c&#39;는 프로그래머가 작성한 소스 코드다. </p>
<p>이 코드가 프로그램이 되려면, &#39;번역&#39;이 필요하다. 컴퓨터가 알아들을 수 있는 언어로. 즉, C 언어 코드를 컴파일해서 기계어 명령으로 바꿔야 한다.</p>
<p>C 컴파일러(gcc)를 사용해서 hello.c를 컴파일한다.</p>
<p>소스 코드는 전처리, 컴파일, 어셈블, 링킹을 거친다. 마지막엔 <strong>운영체제가 실행 가능한 파일 형식</strong>이 된다. </p>
<p>[그림]</p>
<p>이게 <strong>&#39;프로그램&#39; 또는 &#39;바이너리&#39;</strong>다. 컴퓨터가 이해할 수 있도록 0과 1로 번역된 명령어 덩어리다.</p>
<p>소스 코드가 &#39;프로그램&#39;이 되는 과정이었다. 이제 &#39;프로그램&#39;이 &#39;프로세스&#39;가 되는 과정을 보자.</p>
<h2 id="프로그램-➡️-프로세스">프로그램 ➡️ 프로세스</h2>
<p>사용자가 디스크에 있는 &#39;hello.o&#39; (실행 파일)을 실행시킨다. </p>
<p>운영체제는 &#39;가상화된 메모리&#39;를 할당한다. (가상화는 잠시 뒤에 살펴보자.) 운영체제는 디스크에 저장된 프로그램을 가상화된 메모리에 불러온다. </p>
<hr>
<p><strong>메모리 공간은 여러 구역으로 나뉜다.</strong></p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/f908df17-2148-4925-8537-2665ed16b30b/image.png" alt=""></p>
<p>프로그램 (=명령어)가 저장되는 공간은 Text라고 한다.
프로그램이 담고 있는 전역 변수, 정적 변수도 따로 저장한다. Data 영역이라고 한다.</p>
<p>Text나 Data는 실행을 해보지 않아도 어느 정도의 공간이 필요할지 미리 정해져있다. 늘어나거나 줄어들지 않는다. 왜냐하면 프로그램이 실행되는 내내 필요하기 때문이다. 따라서 처음부터 고정된 크기의 구역을 배정한다. </p>
<p><strong>도서관으로 치면, 사용자가 배정된 &#39;고정석&#39;</strong>이라고 할 수 있다.</p>
<p><strong>반면 나머지 구역은 &#39;자유석&#39;이다.</strong> 항상 필요한 데이터가 아니라서, 그때 그때 사용하고 비워주는 공간이다. Heap 구역과 Stack 구역이 여기 해당된다.</p>
<p>Heap과 Stack은 프로그램을 실행하면서 공간이 필요할 때마다 그때그때 메모리를 할당하고, 사용이 끝나면 해제해서 줄어든다. 계속해서 영역의 크기가 변한다.</p>
<p>Heap과 Stack의 차이를 아는 것은 매우 중요하다. 하지만 오늘 주제에서는 벗어나니까 일단 넘어가자.</p>
<hr>
<p>*<em>자, 이제 프로그램을 불러왔다. *</em>필요한 메모리 공간도 할당했다. 프로세서(CPU)가 프로그램을 실행할 준비가 되었다.</p>
<p>*<em>프로그램이 &#39;프로세스&#39;가 된 것이다. *</em></p>
<p>프로세스는 운영체제 입장에서의 &#39;고객/사용자&#39;이라고 했다. 그래서 운영체제는 <strong>실행 중인 프로그램을 관리하기 위해 관련 각종 데이터를 따로 저장</strong>해둔다. (호텔 관리자가 고객 명부를 관리하듯이) </p>
<p>이 데이터를 &#39;프로세스 제어 블록(Process Control Block, PCB)&#39;라고 부른다. 기억해두자.</p>
<h1 id="가상화는-양다리다">가상화는 &#39;양다리&#39;다</h1>
<p>프로세스 얘기를 하다보면, &#39;가상화된 프로세서&#39; &#39;가상화된 메모리&#39; 같은 용어가 등장한다. </p>
<p>교과서를 보면 이렇게 말한다. </p>
<blockquote>
<p>&#39;가상화를 통해 프로세스는 <strong>전체 자원을 혼자 쓰는 듯한 착각</strong>을 지니게 되며, 이는 프로세스라는 개념의 핵심이다.&#39;</p>
</blockquote>
<p>나는 이 말을 꽤 오랫동안 이해하지 못했다. 하지만 원리를 알고보니, 그렇게 어려운 건 아니었다.</p>
<p>쉬운 이해를 위해, 호텔과는 다른 비유를 또 하나 들어보자. </p>
<p><strong>운영체제가 &#39;양다리를 걸치는 바람둥이&#39;</strong>라고 생각해보는 거다.</p>
<h2 id="김운영-씨-이야기">김운영 씨 이야기</h2>
<p>김운영 씨는 엄청난 바람둥이다. </p>
<p>운영 씨는 너무나 매력적이어서 주변에 여자가 끊이지 않는다. 운영 씨는 이걸 잘 알고 있기 때문에 한 명만 사귀고 싶어하지 않는다. (나쁜 놈이다.) </p>
<p>그럼 어떻게 하느냐. 금요일은 A와, 화요일은 B와, 수요일은 C와... 이런 식으로 시간을 나눠서 데이트를 한다. </p>
<p>데이트 장소도 마찬가지다. 겹치지 않도록 각 애인별로 철저하게 공간을 나눈다. A는 이태원에서만 만나고, B는 강남에서만, C는 종로에서만 만나는 식이다.</p>
<blockquote>
<p>그리고 시공간을 분할하는 것보다 더 중요한 게 있다. 무엇일까? </p>
</blockquote>
<p>바로 A, B, C는 <strong>김운영이 다른 사람과도 사귀고 있다는 걸 몰라야 한다</strong>는 점이다. </p>
<p>김운영 씨는 상당히 철저해서 모든 애인에게 <strong>가명</strong>을 쓴다. 심지어 사는 주소도 다 다르게 말한다. </p>
<p>그 결과 김운영 씨는 완전 범죄를 유지하며 여러명의 애인과 양다리를 걸칠 수 있었다. 그 인원 수는 무려 수백명에 달한다. 각각의 애인들은 서로의 존재를 까맣게 모르고 행복한 연애를 했다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/6731f4ef-814b-476e-b0db-050e0992ae5e/image.jpeg" alt=""></p>
<p>실제였다면 &#39;그알&#39;에 나올만한 이런 엄청난 사기가, 가능한 이유는 무엇일까? </p>
<p><strong>김운영씨가 애인과 24시간 붙어있는 것은 아니기 때문</strong>이다. </p>
<p>데이트를 하는 것은 1-2주에 한번 정도였다. 그래서 몸은 하나지만, 스케줄링과 가명을 철저히 해서 양다리를 걸치는 게 가능했던 것이다.</p>
<h2 id="운영체제-이야기">운영체제 이야기</h2>
<p>실제 &#39;운영체제&#39;가 프로세스에게 하드웨어 자원을 분배하는 방식도 이와 같다. </p>
<p>컴퓨터 하나, OS 하나에 프로세스는 여러 개다. 프로세스를 실행하려면 메모리 공간과 CPU가 필요하다. 한 컴퓨터에 있는 한정된 CPU와 한정된 메모리를 가지고, 어떻게 수백개의 프로세스를 돌릴 수 있을까?</p>
<p>당연히 자원을 나눠야 한다. OS는 CPU와 메모리를 쪼개서 각 프로세스에게 나눈다. </p>
<p>CPU는 시간적으로 분할한다. 10초는 A 프로세스가 썼다가, 다음 10초는 B 프로세스가 쓰는 식이다. 실행을 교차시킨다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/73d0c110-c7f3-4298-a53e-e0fd7a81d87d/image.jpeg" alt=""></p>
<p>메모리는 공간적으로 분할한다. 1000번부터 2000번 메모리까지는 A 프로세스가 쓰는 공간. 2000번부터 3000번 메모리까지는 B 프로세스가 쓰는 공간. 이런 식이다. </p>
<p>(물론 가상 메모리는 단순히 공간적으로만 나누는 기법은 아니지만 여기서는 일단 단순하게 설명한다.) </p>
<p>OS의 역할은 여기서 끝나지 않는다. OS는 각 프로세스에게 자원을 공유하고 배분하고 있다는 사실을 <strong>&#39;숨긴다&#39;.</strong> 바람둥이가 양다리를 걸치는 것처럼 말이다.</p>
<p>왜? <strong>사용하는 쪽에서 편리하기 때문</strong>이다. 운영체제는 각 프로세스가 멀티 프로그래밍 상태를 신경쓸 필요가 없도록 단순한 인터페이스를 제공한다.</p>
<p>숨긴다는 게 무슨 말일까? 메모리의 예를 들어보자. </p>
<p>사실 컴퓨터가 가진 메모리는 하나다. 0부터 1만까지 주소가 있는 메모리라고 치자. </p>
<p>0부터 999까지는 A 프로세스 공간이다.
1000부터 1999까지는 B 프로세스 공간이다.</p>
<p>하지만 B 프로세스에게 주소 공간을 1000 ~ 1999라고 알려준다면, *<em>B 프로세스는 &#39;0 ~ 999는 이미 다른 프로세스가 쓰고 있다&#39;는 사실을 알아야 한다. *</em>다른 프로세스의 공간과 자신의 메모리 범위를 항상 신경쓰면서 메모리 조작 요청을 해야할 것이다.</p>
<p>OS는 이런 정보를 숨긴다. B 프로세스가 받은 공간이 1000-1999이든, 4342-5341이든 상관없다. 그냥 0-1000으로 바꿔서 알려준다. (김운영 씨가 가명을 쓰는 것이 떠오르지 않는가?)</p>
<p>그러면 B 프로세스는 다른 프로세스의 메모리 주소에 신경을 쓰지 않아도 된다. &quot;그냥 200번에 &#39;1&#39;을 저장해줘&quot;라고 하면 된다. </p>
<p>운영체제는 &#39;알았어&#39; 하고 대답한다. 
&#39;B 프로세스한테 200번이 실제로 몇 번이었지...?&#39; 하고 찾는다. 
&#39;아 1200이었구나. 1200에 10을 저장하자&#39; </p>
<p>이 부분은 프로세스가 전혀 모르게 이뤄진다.</p>
<p>운영체제는 수백개의 프로세스에게 하드웨어 자원과 서비스를 제공하기 위해서, 복잡한 공유, 스케줄링, 보호 메커니즘을 가지고 있다. 하지만 <strong>각 프로세스는 그걸 몰라도 되도록 정보를 최대한 숨긴다.</strong></p>
<p><strong>이게 바로 OS가 제공하는 &#39;가상화&#39;다.</strong> OS는 프로세스에게 &#39;가상화된 프로세서&#39;와 &#39;가상화된 메모리&#39;를 준다.</p>
<p>&#39;가상화된 자원&#39;이 가능한 이유는, <strong>프로세스가 자원을 항상 사용하는 것은 아니기 때문</strong>이다. 필요할 때가 정해져 있다. 그래서 이런 시스템이 가능하고 효율적이다.</p>
<h1 id="프로세스의-상태">프로세스의 상태</h1>
<p>프로세스는 처음부터 메모리를 할당받는다. 하지만 프로세서는 항상 가질 수 없다. </p>
<p>프로세스는 보통 수백개다. 반면 프로세서(코어)는 전체 컴퓨터에 몇 개 없는 희귀한 몸이다. 각 프로세서는 한번에 하나의 프로세스만 실행할 수 있다.</p>
<p>그래서 특정 시점만 잘라서 확인하면, <strong>수많은 프로세스 중에서 몇 개 정도만 실행 상태</strong>다. <strong>나머지는 모두 멈춰서 대기</strong>한다.</p>
<p>&#39;어떤 프로세스를 대기시키고 어떤 프로세스를 실행시킬 것이냐&#39;. 이걸 결정하는 게 운영체제의 핵심 임무 중 하나다. </p>
<p>운영체제는 스케줄링을 잘 하기 위해 프로세스에 &#39;상태&#39;를 부여해 구분한다.</p>
<p>준비(Ready), 실행(Running), 대기(Waiting)</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/161c593e-8c9f-49fd-9794-d2cea1411a17/image.jpeg" alt=""></p>
<p>먼저, 프로세스가 새로 생겨나면 <strong>준비(Ready)</strong> 상태가 된다.</p>
<p>커널은 준비 상태인 프로세스 중 하나를 골라서 프로세서를 준다.</p>
<p>이 때** 프로세서는 &#39;실행(Running)&#39; 상태**다.</p>
<p>프로세서가 프로세스 안에 있는 프로그램 명령어를 하나씩 실행한다. 그런데 디스크에서 <code>abc.txt</code>를 읽어오라는 명령이 있었다. 메모리가 아닌 보조 저장장치에서 정보를 읽어오는 것은 프로세서가 할 수 없다. </p>
<p>따라서 커널에 파일 입출력을 요청한다. 커널이 파일 입출력 작업을 완료해서 데이터를 넘겨줄 때까지는 다음 명령을 실행할 수가 없다. 입출력 작업은 프로세서보다 훨씬 더 느리다. 따라서 이 동안 프로세서는 다른 프로세스를 실행하는 게 효율적이다.</p>
<p>프로세스는 프로세서를 뺏기고 <strong>대기(Waiting)</strong>하는 상태가 된다. <strong>자고 있는(Sleep) 상태, 멈춘(Block) 상태</strong>라고 하기도 한다. </p>
<p>대기 상태의 프로세스가 파일 입출력이 끝났다는 메시지를 받았다. 하지만 이미 프로세서는 다른 프로세스를 열심히 실행 중이다. 당장 실행을 할 수는 없다. </p>
<p>이 프로세스는 이제 <strong>&#39;준비(Ready)&#39; 상태</strong>로 간다. 실행할 준비가 되었다는 뜻이다.</p>
<p>그러다가 커널이 다시 프로세서를 할당해주면, 실행 상태로 되돌아간다. 아까 <code>abc.txt</code>를 읽어오라는 명령 다음부터 다시 실행하기 시작한다.</p>
<p>프로세서는 매우매우 빠르고, 입출력은 수십배에서 최대 수천만배까지 느리다. 따라서 대부분의 프로세스는 외부 작업을 기다리는 대기 상태에서 시간을 보낸다.</p>
<p>그렇다면 <strong>현재 준비 상태인 프로세스 중, 어떤 프로세스에게 프로세서를 줄 것인가?</strong></p>
<p>이것을 결정하는 알고리즘이 CPU 스케줄링 알고리즘이다. 여기에 대해서는 나중 글에서 더 자세히 알아보겠다.</p>
<h1 id="컨텍스트-스위칭">컨텍스트 스위칭</h1>
<p>자, 가상화, 프로세스 상태, 스케줄링까지 왔다. </p>
<p>정말 가볍게 설명했지만, 그래도 처음 듣는다면 머리가 아플 수 있다. 마지막 하나 용어만 더 알고 가자.</p>
<p>아까 전 프로세스의 상태가 바뀌는 과정을 살펴봤다. 실행 중이던 프로세스는 대기, 혹은 준비 상태로 이동한다. 그리고 나중에 다시 실행 상태가 된다.</p>
<p>실행을 중간에 멈췄다가 다시 실행하려면, 실행을 멈췄던 지점까지의 정보를 알아야 한다. 즉, 맥락(Context)을 불러와야 한다.</p>
<p>이 맥락을 저장해두는 것은 OS의 역할이다. OS는 고객 명부처럼, 프로세스를 관리하는 프로세스 제어 블록(PCB)를 갖고 있다. 여기에 프로세스의 현재 상태를 저장한다.</p>
<p>따라서 실행 중인 프로세스가 바뀌면, 먼저 실행을 멈추는 프로세스의 현재 정보를 저장해둔다. 새롭게 실행할 프로세스의 정보를 불러온다. </p>
<p>마치 게임에서 저장해뒀던 플레이를 불러오는 것처럼.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/84eee957-6d90-459f-8bc7-83368b3b43ef/image.jpeg" alt=""></p>
<p>이걸 &#39;컨텍스트 스위칭(Context Switching)&#39;이라고 한다. 컨텍스트 스위칭은 그 자체로 상당한 시간이 필요하기 때문에, 가급적 적게 일어나는 게 성능에 좋다. </p>
<p>사람도 너무 많은 걸 짧은 시간에 하려다보면, 일이 잘 안되는 경우가 있다. 컨텍스트 스위칭이 너무 자주 일어나기 때문이다. 코딩을 한 줄 하려다 메일이 오고, 메일 답장 한줄 쓰려다 카톡이 오는 상황을 상상해보자. 이렇게 하는 일을 빠르게 바꾸다보면 일 효율이 매우 떨어진다. </p>
<p>운영체제 입장에서도 컨텍스트 스위칭은 최소화하는 게 좋고, 그러기 위해서 또 다양한 기법들이 나오게 된다.</p>
<h1 id="프로세스-id">프로세스 ID</h1>
<p>지금 컴퓨터로 이 글을 보고 있다면, 터미널을 켜고 <code>top</code>를 입력해보자. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/f6692494-89c5-4fa5-a5d2-42dd1b513027/image.png" alt=""></p>
<p>그러면 이런 화면이 뜬다. 우리가 방금 배웠던 것을 확인해볼 수 있다.</p>
<p>내 맥북 에어에는 무려 589개의 프로세스, 3358개의 스레드가 돌아가고 있다. </p>
<p>그런데 589개 중 2개만 실행 상태다. 내 맥북은 코어가 여러개이기 때문에 2개 프로세스를 병렬 실행할 수 있다. 하지만 길게 보면 빠르게 컨텍스트 스위칭을 하면서 &#39;동시적으로&#39; 수백개의 프로세스를 실행하고 있다는 걸 알 수 있다.</p>
<p>또 여기서, pid라는 숫자를 볼 수 있다.</p>
<p>프로세스 ID (pid)는 OS에서 프로세스를 구분하기 위한 id다. 1부터 시작한다.</p>
<p>pid가 1인 프로세스는 항상 정해져있다. <strong>init 프로세스</strong>라고 한다. 컴퓨터가 부팅될 때, 커널은 가장 먼저 init 프로세스를 찾아 실행한다. init 프로세스는 pid 1이 된다.</p>
<p>init 프로세스는 부팅 과정에서 중요한 역할을 한다. 주로 설정을 초기화하고, 필요한 기본 프로그램들을 실행시킨다. 시스템 초기화, 웹 서버, 프린트 서버, ssh 서버 같은 서비스 실행, 로그인 프로그램 실행 등이다. </p>
<p>MacOS의 init 프로세스는 <a href="https://en.wikipedia.org/wiki/Launchd"><code>lanchd</code></a>라는 프로그램이다. 리눅스에서는 <a href="https://en.wikipedia.org/wiki/Systemd"><code>systemd</code></a>가 많이 쓰인다. </p>
<h1 id="프로세스-계층">프로세스 계층</h1>
<p>유닉스 계열의 새로운 프로세스는 fork() 라는 시스템 콜로 만들어진다.</p>
<pre><code>#include &lt;unistd.h&gt;

pid_t fork(void);</code></pre><p><code>create</code>가 아니고 <code>fork</code>다. 프로세스를 만들 때 그냥 새로운 걸 만드는 게 아니다. 생성을 요청한 프로세스를 복사해서 만든다. 커널은 <code>fork()</code>를 호출한 프로세스를 복사해서, 다른 프로세스를 만든다.</p>
<p>이 때 원본 프로세스는 &#39;부모&#39;가 된다. 복사된 프로세스는 &#39;자식&#39;이 된다. </p>
<p>모든 자식 프로세스는 부모 프로세스가 있다. 따라서 프로세스는 <strong>‘트리 계층 구조&#39;</strong>를 만들게 된다. (부모 프로세스 아이디는 <code>ppid</code>라고 한다.)</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/4c7e21ce-4983-4d0a-95a3-c53874d4bd6c/image.png" alt=""></p>
<p>linux 시스템에서는 <code>pstree</code> 를 입력하면 이렇게 생긴 프로세스의 트리를 볼 수 있다.</p>
<p>가장 먼저 실행되는 프로세스는 pid 1인 init 프로세스다. init 프로세스는 root 프로세스다. 모든 프로세스의 부모를 따라가보면 init과 만나게 된다.</p>
<h1 id="사용자-그룹">사용자, 그룹</h1>
<p>프로세스에는 pid 뿐 아니라 사용자 id (user id), 그룹 id (group id)라고 하는 고유한 숫자가 부여된다. </p>
<p>이 사용자/그룹 아이디는 매우 중요하다. 프로세스가 시스템 자원에 접근이 가능한지, <strong>권한을 판단</strong>하기 때문이다.</p>
<p>특정 프로세스가 <code>password.txt</code>라는 파일을 열 수 있는지 없는지를 결정할 때, 파일에 어떤 사용자와 그룹이 허가되어있는지를 보고, 해당 프로세스의 uid와 gid와 맞춰본다.</p>
<p><strong>uid 0번은 root 사용자</strong>다. 루트 사용자는 시스템 내에서 모든 것을 할 수 있는 강력한 권한을 가지고 있다. </p>
<p>(쉘에서 <code>sudo</code> 커맨드를 써본 적이 있겠지? <code>sudo</code>를 사용하면 root 사용자 권한으로 명령을 할 수 있다.)</p>
<p>호텔 관리자의 예를 들자면, 어떤 고객님은 일반 방과 시설에만 접근이 가능하고, 돈을 많이낸 VIP 고객은 별도의 라운지나 룸서비스를 요청할 수 있다. 호텔은 사용자 id라는 별도의 아이디를 부여하고, 고객이 서비스를 요청할 때 먼저 권한이 있는지 확인한다. </p>
<p>그러면 <strong>root는 호텔 오너쯤 되겠다.</strong> 고객인데 모든 일을 할 수 있으니까.</p>
<h1 id="요약-정리">요약 정리</h1>
<ul>
<li>&#39;운영체제라는 관리자&#39;가 운영하는,&#39;컴퓨터라는 호텔&#39;에, &#39;체크인한 고객&#39;이 바로 프로세스다.</li>
<li>소스 코드를 컴파일하면 프로그램이 되고, 프로그램을 커널이 실행하면 프로세스가 된다.</li>
<li>운영체제는 마치 양다리 걸치는 바람둥이처럼, 여러 프로세스에게 자원을 배분하고 공유하지만 그 사실을 프로세스에게는 숨긴다.</li>
<li>운영체제는 프로세서를 스케줄링하기 위해 준비, 실행, 대기 상태로 나눠 프로세스를 관리한다.</li>
<li>프로세서가 실행 중인 프로세스가 바뀌면, 정보를 저장해두고 새로운 정보를 불러오는 &#39;컨텍스트 스위칭&#39;이 일어난다.</li>
<li>프로세스는 ID를 가지고 있으며, fork()를 통해 복사 방식으로 만들어져서 트리 구조를 이룬다.</li>
<li>프로세스는 사용자, 그룹 ID를 가지고 있으며 권한을 결정한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[모든 것이 파일(file)이다]]></title>
            <link>https://velog.io/@eddy_song/file-system</link>
            <guid>https://velog.io/@eddy_song/file-system</guid>
            <pubDate>Wed, 17 Aug 2022 01:58:02 GMT</pubDate>
            <description><![CDATA[<p>파일은 누구나 알고 모든 사람들이 쓰는 용어다. (적어도 데스크탑을 써본 사람이라면) 파일을 열고 읽고 쓰고 닫고 삭제할 줄 안다. </p>
<p>하지만 그 파일이 어떻게 &#39;파일&#39;로 존재할 수 있는지. 컴퓨터는 어떻게 수십만 개의 파일을 관리하는지. 우리가 파일 탐색기에서 본 것말고 또 어떤 파일들이 있는지. 이런 지식은 나도 잘 몰랐다.</p>
<p>이번 글에선 파일에 대해 좀 더 깊이 들어가 본다. </p>
<p>파일은 간단해보이지만, 운영체제의 원리를 이해하기 위한 필수 개념이다.</p>
<h2 id="파일은-도서관에-꽂혀있는-책이다">파일은 도서관에 꽂혀있는 책이다</h2>
<p>파일이란 보조 저장 장치(ex. 디스크)에 정보를 저장하는 단위다. </p>
<p>파일이라는 이름은 종이로 된 서류 관리 시스템에서 왔다. 종이 문서는 하나의 &#39;파일철&#39;로 묶어 책처럼 저장할 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/2622a34a-d60a-4b67-8e12-efd83860696f/image.webp" alt=""></p>
<p>&#39;파일&#39;을 하나의 책이라고 생각해보자.</p>
<p>그리고 파일이 저장되는 디스크 공간은, 수많은 책이 꽂힌 큰 하나의 도서관이라고 생각해보자.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/037e0d2e-5c65-4126-a2d1-80f2d80f667a/image.jpeg" alt=""></p>
<p>이 도서관은 굉장히 많은 정보를 담고 있다. 도서관 정보는 &#39;책&#39;의 형태로 묶여서 저장된다. (아니면 서류철이라고 해도 되고.)</p>
<p>책이 관련된 텍스트를 묶은 것처럼, 디스크에 저장 연관 정보를 묶으면 파일이 된다. </p>
<p>운영체제는 정보를 파일 형태로 쓴 뒤 저장하고, 찾아서 읽는다. </p>
<h2 id="파일에-체계를-잡아주는-파일-시스템">파일에 체계를 잡아주는 파일 시스템</h2>
<p>아직 파일이 들어오지 않은 도서관을 상상해보자. </p>
<p>도서관은 지금 비어있다. 이제부터 끊임없이 새로운 책들이 들어오고 나갈 것이다. </p>
<p>그런데 책을 그냥 마구잡이로 쌓아두거나, 어떤 책이 있는지 기록해두지 않거나, 책을 다루는 어떤 규칙을 만들지 않으면 어떻게 될까? </p>
<p>계속해서 새로운 파일이 들어온다.</p>
<p>도서관은 금방 정신없는 아수라장이 된다. 아무도 원하는 책을 제대로 찾을 수가 없다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/c2c50a88-11ec-4332-8676-96bd49d5fd8c/image.jpeg" alt=""></p>
<p>하지만 실제 도서관은 훨씬 체계적이다. </p>
<p>책에 관리 번호를 붙인다. 주제별로 분류한다. 어떤 책이 있는지 기록한다. 어떤 위치에 꽂을지 결정하는 규칙을 만든다.</p>
<p>이런 체계가 있기 때문에 수많은 책을 저장하고도 편리하게 정보를 꺼내 쓸 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/288ed62d-53c0-4431-abb6-482609602edc/image.jpeg" alt=""></p>
<p>파일도 마찬가지다. 저장공간에 무질서하게 넣어둘 수는 없다. 파일을 관리하는 체계가 필요하다. 이걸 &#39;파일 시스템&#39;이라고 한다.</p>
<p>파일 시스템은 파일 이름과 파일 정보, 저장 공간을 관리하고 파일을 효율적으로 찾을 수 있도록 도와준다.</p>
<p>어떤 컴퓨터든 보조 저장 장치가 필요하다. 그래서 파일 시스템은 운영체제에서 빼놓을 수 없는 부분이다. </p>
<p>우리가 컴퓨터에서 파일을 열고 쓸 때마다, 운영체제는 파일 시스템을 사용한다.</p>
<p>우리가 책이 필요하거나 새로운 책을 보관할 때, 도서관 시스템을 사용하는 것과 마찬가지다. 파일에 읽고 쓸 일이 있을 때마다 운영체제는 파일 시스템을 사용해 디스크에 데이터를 읽고 쓴다. </p>
<p>파일 시스템은 어떤 운영체제든 필수로 포함되어있지만, 종류는 다 다르다. 도서관마다 책을 관리하는 방법이 다 다르듯이, 저장공간도 각자 쓰는 파일 시스템이 다를 수 있다.</p>
<p>대표적으로 윈도우는 FAT(12/16/32, exFAT), NTFS, 리눅스는 ext(2/3/4), 맥OS는 HFS+, APFS 등의 파일 시스템을 사용한다.</p>
<p>파일 시스템이 하는 일을 조금 더 구체적으로 알아보자.</p>
<h2 id="1-파일의-메타데이터-관리">1. 파일의 메타데이터 관리</h2>
<p>도서관 관리 시스템을 생각해보자. 기본적으로, 저장된 책에 대한 정보를 저장하는 시스템이 있다. 책의 이름, 저자, 최근 빌려간 날짜, 반납된 날짜, 대분류/소분류, 서가 위치 등. 이 책 정보가 있어야, 책을 가져갈 수 있는지, 어디에 있는지 등을 알 수 있다.</p>
<p>마찬가지로 파일 시스템의 중요한 역할은, 파일의 메타 데이터 관리다.</p>
<p>파일 메타데이터는 파일에 대한 데이터를 저장한다.</p>
<ul>
<li>파일 크기</li>
<li>만들어진 시각</li>
<li>마지막 접근 시각</li>
<li>변경된 시각</li>
<li>파일 소유자</li>
<li>파일 접근 모드</li>
<li>어떤 블록에 저장되어있는지</li>
</ul>
<p>파일 시스템은 파일의 내용과 파일 메타 데이터를 따로 나눠서 저장한다. </p>
<p>유닉스 계열에서는 이 메타데이터를 저장하는 자료 구조를 i-node라고 부른다. i-node는 파일이 정확히 어떤 위치에 저장돼있는지를 포함한다. </p>
<p>도서관의 책 정보가 책을 대출하고 찾기 위한 정보인 것처럼, i-node는 파일에 접근하기 위한 열쇠가 되는 정보다. </p>
<p>모든 파일은 i-node를 가지고 있다. i-node에는 고유한 정수 번호가 매겨져있다. 이 번호를 가지고 i-node 객체에 접근할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/c7ede9dd-0cbc-4221-9736-9a90658d01b2/image.png" alt=""></p>
<p>(유닉스 계열 운영체제에서 <code>ls -i</code> 명령어를 입력한 결과. 현재 디렉토리 내 파일의 i-node 번호를 볼 수 있다.)</p>
<h2 id="디렉토리와-계층-구조">디렉토리와 계층 구조</h2>
<p>&#39;디렉토리&#39;는 여러 파일을 묶어놓은 단위다. 컴퓨터를 쓰다보면 파일의 개수가 많아진다. 디렉터리로 분류하면 잘 정리된 형태로 파일을 찾을 수 있다. </p>
<p><code>/computer_science/operating_system/file_system/directory.txt</code> 이런 식으로 대분류부터 소분류까지 파일 경로로 표현할 수가 있다. </p>
<p>디렉터리 안에 또 디렉터리를 넣을 수 있고, 하위 디렉터리에 파일을 넣어 구조화하는 방식을 &#39;계층적 파일 시스템&#39;이라고 한다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/7399775f-a04b-4f79-bf2a-3f0925e6afd2/image.png" alt=""></p>
<p>뭐, 사실 너무나 익숙해서 굳이 설명이 필요한가 싶다. 하지만 이것도 유닉스가 만들어지던 당시에는 꽤나 참신한 방법이었다고 한다. 유닉스 이전에는 파일 시스템에 규칙성이 부족했고, 계층적 파일 시스템이 별로 없었다.</p>
<p>우리가 잘 모르고 있는 부분은 디렉터리도 결국 파일이라는 점이다. 디렉터리는 하위 파일의 &#39;링크&#39;를 담고 있는 특수한 형태의 파일이다.</p>
<h3 id="링크">링크</h3>
<p>앞서 파일 시스템은 i-node 번호를 가지고 파일의 메타데이터를 찾고, 그 메타데이터로 파일을 열고 읽고 쓸 수 있다고 했다.</p>
<p>하지만 i-node 번호는 그냥 숫자다. 사람은 숫자를 잘 기억 못한다. 대신 사람은 &#39;파일 이름&#39;으로 파일을 찾는다. </p>
<p>(도서관의 비유에서도 마찬가지다. 도서관에는 책의 일련번호가 매겨져있고, 그걸로 시스템을 관리한다. 하지만 사람은 일련번호가 아닌 이해하기 쉬운 책 이름으로 책을 찾는다.)</p>
<p>그렇다면 특정 파일 이름이 어떤 i-node 번호를 가리키는지 알아야겠지?</p>
<p>이걸 &#39;링크&#39;라고 한다. 링크는 파일 이름과 i-node를 저장한다. 이름만 입력하면 실제 파일을 찾을 수 있게 해준다. </p>
<h3 id="링크를-모아놓은-디렉터리">링크를 모아놓은 디렉터리</h3>
<p>디렉터리도 파일이다. 다만 디렉터리는 &#39;자신에게 속한 파일 링크&#39;를 저장하는 파일이다. 디렉터리 파일엔 다른 내용은 읽거나 쓸 수 없다. 오직 링크를 추가하거나 삭제할 수만 있다.</p>
<p>디렉터리를 열어 내용을 읽으면 링크들이 있고, 이 링크들은 실제 파일을 찾아갈 수 있도록 정보를 저장하는 &#39;포인터&#39; 역할을 한다.</p>
<p>디렉터리 안에 또 다른 디렉터리에 대한 링크가 있을 수 있다. 이렇게 파일 이름과 i-node를 가진 디렉터리가 계속 중첩된다. 이 중첩 구조가 트리를 이룬다.</p>
<p>이 트리 구조가 방금 말했던 &#39;계층적 트리 구조&#39;다. 우리가 잘 알고 있는 &#39;파일 경로&#39;가 여기서 나온다.</p>
<h3 id="경로로-파일을-찾아내는-법">경로로 파일을 찾아내는 법</h3>
<p>사용자는 시스템에 파일 경로를 주고 파일을 찾도록 할 때가 많다. 다음과 같은 경로를 주면서 커널에게 파일을 열어달라고 요청했다고 하자.</p>
<p><code>/home/black/bird.png</code></p>
<p>루트 디렉터리는 보통 이미 커널에서 알고 있다. 루트 디렉터리를 열어본 커널은 <code>home</code>이라는 이름의 파일 링크를 찾는다. <code>home</code>은 디렉터리이면서 파일이기 때문에 i-node를 갖고 있다.  </p>
<p><code>home</code>의 i-node를 가지고 커널은 home의 내용을 읽어낸다. 그 안에는 또 여러 링크가 들어있다. 그 중 <code>black</code>이라는 디렉터리를 찾는다. </p>
<p><code>black</code>이라는 디렉터리를 읽어낸 커널은 <code>bird.png</code>라는 파일을 찾는다. 링크에서 i-node를 알아내고, 최종적으로 <code>bird.png</code>의 내용에 접근한다.</p>
<h3 id="절대-경로와-상대-경로">절대 경로와 상대 경로</h3>
<p>파일 경로에는 &#39;절대 경로&#39;와 &#39;상대 경로&#39;가 있다. </p>
<p>루트 디렉터리에서 시작하는 경로 이름은 누락이 없는 완전한 형태라서 &#39;절대 경로&#39;라고 한다. </p>
<p>반대로 현재 디렉터리에서 본 상대적 위치로 나타내면 상대 경로라고 한다. </p>
<p>디렉터리에는 기본적으로 자기 자신을 뜻하는 <code>.</code>와 부모 디렉터리를 뜻하는 &#39;..&#39; 항목이 있다. </p>
<p>따라서 상대 경로는 흔히 <code>.</code>으로 시작한다. <code>./download/text.txt</code> 이런 식이다.</p>
<p>현재 경로와 상대 경로를 합치면 절대 경로가 된다.</p>
<h2 id="디스크-주소와-블록-매칭">디스크 주소와 블록 매칭</h2>
<p>도서관을 다시 떠올려보자. 책을 직접 꺼내오려면 책이 어디 꽂혀있는지 알아야 한다. 이 때 책의 위치는 어떻게 표현할까?</p>
<p>&#39;3층 5번째 책꽂이로 가서 왼쪽에서 두번째, 위에서 세번째 선반을 보시면, 11번째에 꽂혀 있습니다&#39;</p>
<p>실제 물리적인 위치를 표현한다면 이게 가장 정확할 것이다. 책꽂이는 여러개가 연속되어있고, 위에서부터 몇 개의 층으로 이뤄져있고, 또 그 안에서 순서대로 책이 꽂혀있을 테니까.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/e87b108a-01a8-42e3-8066-ca7773efde90/image.png" alt=""></p>
<p>하지만 저 대사만 봐도 알 수 있듯이 이건 너무 번거롭다. 도서관에서는 별도로 서가 번호를 매긴다. 왼쪽 첫번째 서가부터 차례대로 번호를 매기는 거다. </p>
<p><code>43번 서가에 가면 있습니다.</code> </p>
<p>이제 한 마디로 빠르게 책이 꽂힌 위치를 찾을 수 있다. 이것도 역시 도서관에 &#39;체계&#39;가 있기 때문에 가능한 일이다.</p>
<h3 id="섹터와-블록">섹터와 블록</h3>
<p>마찬가지로 디스크도 물리적인 주소 공간을 나타내는 단위가 있고, 논리적인 단위가 따로 있다. </p>
<p>디스크를 물리적으로 나눠놓은 최소 단위는 &#39;섹터&#39;다. 섹터는 디스크 공간의 한 조각이다. </p>
<p>섹터는 대부분 512 byte 크기다. 512byte보다 더 큰 파일은 여러 섹터에 나눠서 담긴다. </p>
<p>그런데 GB를 넘어가는 큰 파일들은, 천만 개가 넘는 섹터에 나눠서 담아야 한다.</p>
<p>이렇게 많은 섹터를 하나씩 읽어서 파일을 읽고 쓰려면 굉장히 느릴 수밖에 없다.</p>
<p>그래서 파일 시스템은 물리적 섹터를 몇 개씩 묶어서 &#39;블록&#39;이라는 단위와 매칭한다. </p>
<p>덕분에 파일 시스템은 한 블록에 있는 섹터 여러개를 한꺼번에 읽고 쓸 수 있다. 데이터를 더 빠르게 읽고 쓸 수 있다.</p>
<p>블록은 물리적으로 존재하는 주소는 아니지만, 파일 시스템이 어떤 블록에 어떤 물리 주소가 대응되는지 정보를 관리하기 때문에 사용할 수 있다.</p>
<p>커널에서는 &#39;블록&#39; 단위로 파일의 위치를 지정하고 내용을 저장한다. &#39;블록&#39; 단위를 전달받은 파일 시스템은 실제 기기를 읽을 때 물리적 주소인 섹터 단위로 변환해서 접근한다.</p>
<p>(파일 제어 블록, 프로세스 제어 블록 등 커널에서 관리하고 디스크에 저장되는 정보에 &#39;블록&#39;이라는 단어가 들어가는 이유다. 블록 단위로 저장되기 때문.)</p>
<h2 id="디스크-파편화">디스크 파편화</h2>
<p>기존에 저장해둔 파일 os.txt가 있다. 이 파일은 블록 0-4번에 저장했다. 그리고 os.txt에 새로운 내용을 추가했다. 어? 그런데 블록 5번에 이미 다른 파일이 들어 있다. </p>
<p>어떻게 하지? 뭘 어떻게 해. 비어있는 다른 블록에 저장한다. 11번 블록이 비었으니 저기 저장하자. </p>
<p>이번에는 내용을 삭제한다. 프로세스에서 <code>os.txt</code>의 중간 내용을 삭제해서, 블록 3,4번에 있는 데이터를 지웠다. 중간에 빈 블록이 생긴다.</p>
<p>이렇게 파일을 쓰고 지우고 하다보면, 하나의 파일이지만 물리적으로는 이곳 저곳에 흩어져있고, 중간에 비어있는 곳도 생기게 된다.</p>
<p>이걸 &#39;디스크 파편화&#39;라고 한다. 공간을 효율적으로 쓰면 주기적으로 파편화를 정리해줘야 한다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/a0d03ce9-5e2e-4e17-af57-b3eafcfe7958/image.png" alt=""></p>
<p>예전 윈도우즈 운영체제를 써봤다면, &#39;디스크 조각 모음&#39;을 해봤을 것이다. 이 조각 모음이 파편화를 정리해주는 기능이다.</p>
<p>&#39;조각 모음&#39;은 파일 시스템이 하는 중요한 일 중 하나다. 한 쪽으로 관련된 데이터를 모으고, 빈 공간은 없애준다. </p>
<p>다행히 현대 운영체제의 파일 시스템에선 &#39;조각 모음&#39;을 수동으로 할 필요가 없다. 파일 시스템이 알아서 공간을 효율적으로 정리한다. (게다가 SSD에선 조각 모음이 의미가 없다.)</p>
<h2 id="그-외-파일-시스템이-하는-일">그 외 파일 시스템이 하는 일</h2>
<p>그 외에 파일 시스템이 하는 일은 정말 많다.</p>
<p>파일 크기나 이름에 대한 규칙. 
파일에 대한 접근 권한 관리. 
디스크를 용도에 따라 나누는 파티션, 
파일 탐색용 소프트웨어 등등. </p>
<p>하지만 워낙 방대한 내용이니까 일단은 넘어간다. &#39;파일&#39;이 무엇이고, &#39;파일 시스템&#39;이 어떻게 파일을 저장하고 관리하는지 정도에 대한 감만 잡자.</p>
<h2 id="모든-것이-파일이다">모든 것이 파일이다</h2>
<p><strong>유닉스 계열 OS에서 특히 파일은 더 중요한 개념</strong>이다. </p>
<p>책의 챕터 순서만 봐도 알 수 있다. 보통 윈도우즈 계열이나 운영체제 전반을 다루는 책을 보면, 순서가 <code>프로세스(스레드) - 메모리 - 파일</code>이다.</p>
<p>하지만 유닉스/리눅스를 다루는 시스템 프로그래밍 책을 보자. <code>파일 - 프로세스(스레드) - 메모리 순</code>이다. 가장 앞에서 다룬다. 파일이 가장 중요하기 때문이다. </p>
<p>유닉스 시스템이 거의 모든 자원과 서비스를 파일 형태로 표현하고, 파일을 사용하는 방식으로 시스템 자원을 쓴다. 그러니 중요할 수밖에.</p>
<p>언뜻 들으면 이해가 안 갈 수 있다. </p>
<p>다시 도서관의 비유를 떠올려보자.</p>
<p>이번엔 도서관을 보유한 대학교로 스케일을 키워보자. </p>
<p>A 대학교는 책과 DVD 정도 &#39;파일&#39;로 취급해 도서관에서 보관하고 일련번호를 붙여서 관리하는 시스템을 갖고 있다. 여태까지 우리가 말했던 그런 시스템이다.</p>
<p>그런데 U 대학교에서 갑자기 이런 아이디어를 낸 것이다.</p>
<blockquote>
<p>아니, 대학교 안에 있는 모든 장비나 비품도 다 &#39;책&#39;처럼 관리하면 안 되나?</p>
</blockquote>
<p>이 대학교는 의자, 책상, 복사기, 전화기, 컴퓨터 등등 시설 내의 다양한 장비들도 마치 &#39;책(파일)&#39;과 똑같은 시스템을 써서 관리하기 시작한다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/027c89c5-7a9f-4f24-87c6-b45af333b73f/image.jpeg" alt="">
(출처: 바이인터랙티브)</p>
<p>언제 누가 샀고, 현재 누가 사용중이고, 위치가 어디에 있고 등등. 이걸 도서관과 똑같은 시스템에서 관리한다.</p>
<p>그랬더니 두 개의 각각 다른 시스템을 쓸 필요도 없었다. (물론 약간 차이가 있는 부분은 기능을 만들어줘야겠지만) </p>
<p>결과적으로 &#39;한 시스템 사용법만 알면 책을 포함한 모든 자산을 관리할 수 있으니 참 편하더라~&#39; 하는 얘기다.</p>
<p>유닉스가 낸 게 바로 이 아이디어였다. </p>
<blockquote>
<p><a href="https://en.wikipedia.org/wiki/Everything_is_a_file#:~:text=Everything%20is%20a%20file%20describes,bytes%20exposed%20through%20the%20filesystem">&quot;유닉스에서 모든 것은 파일이다 (Everything is a file)&quot;</a></p>
</blockquote>
<p>일반적으로 파일은 &#39;실행 프로그램&#39;이나 &#39;데이터&#39;를 저장한다. </p>
<p>하지만 <strong>유닉스에선 &#39;저장 장치&#39;, &#39;입출력 장치&#39;, &#39;네트워크 통신&#39;도 모두 파일이다.</strong> 즉, 키보드, 마우스, 디스크, 디스플레이, 인터넷 소켓, 파이프... 다 파일이다. </p>
<p>파일의 내용을 읽을 때도 <code>read()</code>로 하고, 사용자가 키보드에서 입력한 글자를 받아올 때도 <code>read()</code>로 한다.</p>
<p>이렇게 하면 뭐가 좋을까? 인터페이스가 통일된다.</p>
<p><strong>파일을 다루는 툴과 인터페이스로 다양한 시스템 자원을 다룰 수 있다.</strong></p>
<p>예전 운영체제에서는 입출력 장치를 사용할 때 실제 장치의 복잡한 세부사항을 알아야 했다. </p>
<p>하지만 유닉스는 이런 부분을 파일로 최대한 추상화하고, 그냥 파일을 저장하고 읽어오는 인터페이스로 장치를 다룰 수 있게 만들었다. </p>
<p>(이런 장치 파일은 일반 파일과 다르게 중간에 또다른 소프트웨어가 있다. &#39;디바이스 드라이버&#39;다. 장치를 조작할 수 있는 단순한 인터페이스를 제공한다.)</p>
<p>*<em>&#39;모든 것이 파일&#39;은 유닉스가 중요시한 철학이었다. 리눅스를 비롯한 유닉스 계열 운영체제도 다 이런 접근법을 물려받았다.
*</em></p>
<h2 id="리눅스의-특수-파일-4가지">리눅스의 특수 파일 4가지</h2>
<p>리눅스에는 3가지 파일 종류가 있다. </p>
<ol>
<li>데이터/프로그램을 담는 일반 파일</li>
<li>파일 링크를 저장하는 디렉터리 파일</li>
<li>특수 파일.</li>
</ol>
<p>이 <strong>특수 파일이 아까 말했던 다양한 시스템 자원을 파일로 표현</strong>한다. </p>
<p>리눅스를 기준으로 특수 파일은 4가지가 있는데, 간단하게 뭐가 있는지 알아보자.</p>
<h3 id="1-블록-디바이스-파일">1. 블록 디바이스 파일</h3>
<p>디바이스 파일은 무엇을 표현하는 파일일까? 당연히 <strong>&#39;장치&#39;를 표현하는 파일</strong>이다. </p>
<p>디바이스 파일은 2개로 나뉜다. &#39;블록 디바이스 파일&#39;과 &#39;캐릭터 디바이스 파일&#39;.</p>
<p>블록 디바이스 파일은 &#39;블록&#39; 단위로 데이터를 입출력할 수 있다. 블록? 어디선가 들어본 단어이지 않은가? 맞다. 파일 시스템이 디스크에서 데이터를 읽고 쓸 때였다.</p>
<p>블록 디바이스는 안의 내용이 배열 형태로, 순차적으로 읽을 필요 없이 랜덤 액세싱이 가능하다. 그리고 읽을 때는 특정한 고정된 크기(블록)으로 읽고 쓴다.</p>
<p><strong>하드 디스크, CD-ROM 같은 저장 장치들이 블록 디바이스 파일</strong>이다. (온갖 파일을 다 저장하는 디스크도 그 자체로 &#39;파일&#39;이라니 신기하지 않은가?)</p>
<h3 id="2-캐릭터-디바이스-파일">2. 캐릭터 디바이스 파일</h3>
<p>블록 디바이스는 배열 형태인 반면, 캐릭터 디바이스 파일은 큐(Queue)다. 데이터가 쌓인 순서대로 앞에서부터 데이터가 쓰고 읽혀진다. *<em>키보드, 마우스, 모니터, 프린터 등이 여기 속한다. *</em></p>
<p>블록보다 훨씬 작은 1바이트 단위로 입출력을 한다.</p>
<p>키보드 입출력이 대표적이다. 키보드에 &#39;q&#39;, &#39;w&#39;, &#39;e&#39;를 입력하면, 커널은 &#39;q&#39;, &#39;w&#39;, &#39;e&#39;를 차례대로 읽어서 각각 애플리케이션에 전달한다.</p>
<h3 id="3-네임드-파이프">3. 네임드 파이프</h3>
<p>파이프는 프로세스 간 데이터를 주고받는 방법이다. (파이프 또한 유닉스의 중요한 혁신 중 하나인데, 길어질 수 있으므로 패스한다.)</p>
<p>파이프는 실제로 디스크에 어떤 것도 저장하지 않는다. 하지만 여러 실행 중인 프로그램이 일반 파일처럼 읽고 쓸 수가 있다. </p>
<p>A 프로세스에서 파이프 파일에 &quot;hello&quot;라고 쓰면, B 프로세스에서 파이프 파일을 읽었을 때 &quot;hello&quot;가 나온다.</p>
<p>데이터가 FIFO(First In First Out) 큐 형식으로 전달되어서 &#39;FIFO&#39;라고 부르기도 한다.</p>
<h3 id="4-소켓">4. 소켓</h3>
<p>소켓도 다른 프로세스와 통신할 수 있는 방법 중 하나다. </p>
<p>소켓은 2가지 종류가 있다. </p>
<p>같은 기기 내의 프로세스가 통신할 때 사용하는 유닉스 도메인 소켓. 
인터넷을 통해 다른 호스트와 통신할 때 쓰는 인터넷 소켓.</p>
<p>인터넷 소켓은 TCP나 UDP에 대한 세부 지식을 몰라도 다른 프로세스와 통신할 수 있게 해주는데, 네트워크와 인터넷을 구성하는 근본적인 메커니즘이기도 하다.</p>
<p>아무튼 이 소켓 또한 리눅스에서는 파일처럼 취급한다.</p>
<h2 id="요약-정리">요약 정리</h2>
<ul>
<li><p>파일은 저장 장치에 정보를 저장하는 단위로, 운영체제는 파일 단위로 정보를 읽고 쓴다.</p>
</li>
<li><p>도서관에 책만 꽂아둔다고 끝이 아니라 체계가 필요하듯이, 파일을 읽고 쓰려면 파일 체계(File system)가 있어야 한다. </p>
</li>
<li><p>파일 시스템은 파일의 메타데이터를 관리한다. 유닉스 계열에서는 i-node로 메타데이터를 표현한다.</p>
</li>
<li><p>파일 시스템은 파일을 디렉토리 계층으로 구조화한다. 디렉토리는 파일의 링크를 저장한 특수한 파일이다. 파일 경로를 통해서 파일을 쉽게 찾을 수 있다. </p>
</li>
<li><p>파일 시스템은 물리 섹터와 논리 블록을 매칭한다. 덕분에 더 빠르게 데이터를 읽고 쓸 수 있다. </p>
</li>
<li><p>파일 시스템은 디스크 파편화를 자동으로 정리한다.</p>
</li>
<li><p>유닉스에서는 모든 것이 파일이다. 대부분의 시스템 자원을 파일 형태로 표현하기 때문이다. 파일을 다루는 인터페이스 하나로 다양한 자원을 다룰 수 있다.</p>
</li>
<li><p>리눅스에는 시스템 자원을 나타내는 특수 파일 4가지가 있다. 블록 디바이스 파일, 캐릭터 디바이스 파일, 네임드 파이프, 소켓이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[운영체제의 역사 그리고 표준이 중요한 이유]]></title>
            <link>https://velog.io/@eddy_song/os-standard</link>
            <guid>https://velog.io/@eddy_song/os-standard</guid>
            <pubDate>Mon, 15 Aug 2022 06:50:15 GMT</pubDate>
            <description><![CDATA[<h2 id="유닉스의-탄생">유닉스의 탄생</h2>
<p>유닉스는 AT&amp;T 벨 연구소의 연구원이었던 켄 톰슨과 데니스 리치가 만들었다. 벨 연구소는 20세기 과학기술에 엄청난 기여를 한 혁신적인 장소다. 일단 벨 연구소 출신으로 노벨과학상 받은 사람만 10명이 넘으니 말 다했다. 트랜지스터부터 우주배경복사까지 수많은 업적을 쌓았다.</p>
<p>이 벨 연구소가 낳은 역작 중 하나가 바로 유닉스다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/c2288cb0-a456-4384-984b-44b2f572f5cc/image.jpeg" alt="">
(유닉스의 창시자, 켄 톰슨과 데니스 리치)</p>
<blockquote>
<p>왜 갑자기 유닉스 얘기를 하냐고? </p>
</blockquote>
<p>바로 <strong>유닉스가 현대 운영체제의 시조새 같은 존재</strong>기 때문이다. 지금 우리가 쓰고 있는 대부분의 운영체제는 (윈도우즈만 제외하고) 유닉스를 뿌리로 하고 있다.</p>
<p>유닉스의 등장 배경을 아주 짧게 알아보자. </p>
<p>1960년대 후반, 벨 연구소에서는 많은 돈을 들여서 &#39;멀틱스&#39;라는 운영체제 개발 프로젝트를 진행했다. 멀틱스는 멀티 프로그래밍, 멀티 유저를 지원하는 혁신적인 운영체제였다. (그렇다. 그 이전 컴퓨터는 프로그램도 동시에 여러개 못 돌렸고, 하나의 컴퓨터에 여러 유저가 접속할 수도 없었다.) </p>
<p>그렇지만 멀틱스 운영체제 개발은 상업적으로 완전히 실패했다. </p>
<p>대신 교훈을 남겼다. 켄 톰슨과 데니스 리치는 멀틱스 개발을 하면서 깨달은 점이 있었다. </p>
<p>멀틱스에서 느꼈던 문제점을 개선하고 싶어서, 버려진 구식 컴퓨터를 이용해 다락방에서 간단한 운영체제를 하나 만들었다. 이게 바로 <strong>유닉스(UNIX)</strong>다. (&#39;멀틱스&#39;의 반대 어원으로 &#39;유닉스&#39;라는 이름이 나왔다고 한다.)</p>
<p>멀틱스의 안 좋은 기억 때문에, 벨 연구소 경영진들은 유닉스 개발에 별로 신경도 안 썼다. 컴퓨터 사달라는데 지원도 안 해줬다. (당시 컴퓨터는 수천-수억원짜리 기계였으므로) </p>
<p>하지만 유닉스는 당시 운영체제의 불편한 점들을 많이 개선했다. 결과적으로는 엄청난 성공을 거뒀다.</p>
<p>이 이야기는 <strong>&lt;유닉스의 탄생&gt;</strong>이라는 책에서 읽은 것이다. 당시 유닉스 개발팀이었던 브라이언 커닝핸이 썼다. 벨 연구소의 천재 개발자들이 유닉스를 만들어가는 이야기를 담고 있다. 컴퓨터 공학 역사에서 굉장히 중요한 스토리다. 한번쯤 읽어보자. 재밌다.</p>
<p><img src="https://image.yes24.com/goods/91213198/XL" alt=""></p>
<p>(브라이언 커닝핸은 그 유명한 C 언어 교재를 쓴 사람이기도 하다. 최근에 번역된 &lt;1일 1로그 100일 완성 IT 지식&gt; 이라는 책도 있다. 글을 참 잘 쓴다.)</p>
<h2 id="전세계로-뻗어나간-유닉스의-다양한-버전">전세계로 뻗어나간 유닉스의 다양한 버전</h2>
<p>벨 연구소는 유닉스가 돈이 될 거라고 생각을 못했다. (나중에 후회하지만) 유닉스를 저렴한 가격에 외부 배포를 했다. </p>
<p>그러자 전세계 개발자들이 유닉스를 보고 &#39;아아니... 이렇게 좋은 게 있다니!&#39;하면서 유닉스 배포판을 가져다가 수정하고 개선하기 시작했다. 유닉스 개발은 벨 연구소를 벗어나 전세계로 뻗어나갔다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/9c7bb830-ba9f-4878-8f2e-5f2f7127905d/image.gif" alt="">
(UNIX의 역사, 출처: wikipedia)</p>
<p>이 그림을 보면 <strong>유닉스가 엄청나게 다양한 버전으로 갈라져나간 것</strong>을 볼 수 있다. 세세히 다 알 필요는 없지만, 크게 2가지 계열이 있었다.</p>
<p><strong>BSD (Berkeley Software Distribution)</strong></p>
<p>하나는 캘리포니아 버클리 대학에서 만들고 배포한 <strong>BSD 계열</strong>이다. BSD는 초기 유닉스를 기반으로 했지만, 자체적으로 코드를 작성하며 계속 발전시켰다.</p>
<p>1985년 스티브 잡스가 만든 NeXT 컴퓨터의 운영체제가 BSD 기반이었다. 이후 잡스가 돌아가면서 NeXT는 MacOS의 기반이 됐다. MacOS는 이후 iOS의 기반이 됐다. 그러니 애플 운영체제도 넓게 봐서 유닉스 계열이다.</p>
<p><strong>System V</strong></p>
<p>또 다른 쪽은 AT&amp;T가 뒤늦게 유닉스 저작권을 가지고 돈을 벌기 위해 만들었던 System V 계열이다. (그림 아래쪽) IBM, 오라클, HP 같은 시스템 공급 업체들이 사용하는 OS의 기반이 되었다.</p>
<h2 id="유닉스-전쟁">유닉스 전쟁</h2>
<p>이 두 진영은 1980년대 후반 이른바 <strong>‘유닉스 전쟁&#39;</strong>을 벌인다. </p>
<p>당시 수많은 업체, 기관이 각자의 유닉스 버전을 가지고 경쟁했다. 제멋대로 갈라져나간 수많은 유닉스 버전들은 인터페이스도 다를 수밖에 없었다. 당연하게도 유닉스 위에서 어플리케이션을 개발하는 사람들 입장에서는 굉장히 불편했다.</p>
<p>표준이 필요한 시점이었다. 당연히 업계는 표준화가 필요하다는 걸 인정했지만, 누가 진짜 유닉스의 표준이 되어야 하는가는 의견이 다를 수밖에 없었다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/aa115a01-3f26-4a3f-94b1-946d6ff2fe71/image.png" alt="">
(System V가 진정한 표준이라고 홍보하는 1988년 신문 광고)</p>
<p>*<em>BSD 계열과 System V 계열이 특히 박터지게 싸웠다. *</em></p>
<p>AT&amp;T는 BSD가 자기들 코드를 사용했다고 하면서 고소를 했고, BSD는 AT&amp;T에서 유래한 코드를 제거하고 새로 작성했기 떄문에 문제가 없다고 받아쳤다. 지루하고 길고 긴 법정 싸움이 이어졌다.</p>
<p>뭐 아무튼 이 이야기까지 중요한 것은 아니고...</p>
<p>결과적으로 중요한 건, <strong>업계에서는 2가지의 핵심 표준이 유닉스 계열 운영체제의 표준으로 자리잡았다</strong>는 것이다.</p>
<p>하나는 <strong>POSIX</strong>이고, 다른 하나는 <strong>SUS</strong>다.</p>
<h2 id="posix와-sus">POSIX와 SUS</h2>
<p><strong>POSIX (Portable Operating System Interface)</strong>는 IEEE가 정의한 운영체제 인터페이스 표준이다. 더 자세히 말하면, 시스템 콜에 대한 C 언어 API 표준이다. </p>
<p>POSIX는 &#39;유닉스 계열&#39;이라고 불리는 운영체제의 기준이다. BSD, Linux, MacOS 등은 유닉스는 아니지만, OSIX를 따르기 때문에 유닉스 계열이라고 부른다.</p>
<p><strong>SUS(Single Unix Standard)</strong>는 유닉스의 상표권을 가진 오픈 그룹이 만든 유닉스 표준이다. SUS는 POSIX를 포함하는 상위 집합이다. </p>
<p>SUS는 &#39;유닉스&#39;라고 불리는 운영체제의 기준이다. SUS와 호환이 되는 운영체제는 ‘유닉스&#39;라고 불릴 수 있다.</p>
<p>앞으로 우리는 <strong>시스템 콜을 배우게 될 텐데, 대부분은 POSIX에서 정의한 시스템 콜</strong>이다. POSIX가 가장 널리 통용되는 표준이고, 핵심 인터페이스를 담고 있기 때문이다.</p>
<h2 id="리눅스">리눅스</h2>
<p>여기서 리눅스 얘기가 빠질 수 없다. </p>
<p>유닉스가 한창 인기인 시절. 유닉스와 호환이 되는 미닉스라는 운영체제가 있었다. </p>
<p>어느날 21살짜리 핀란드 대학생이 취미로 이 미닉스를 가지고 무료 운영체제를 개발하기 시작했다. 사람들한테 &#39;내가 이런 걸 개발하고 있다&#39;고 알리자 관심을 가진 프로그래머들이 모여서 같이 개발에 참여했다.</p>
<p>이 운영체제는 <strong>이 대학생의 이름을 따서 ‘리누스의 유닉스(Linus&#39;s UNIX)’, 리눅스(LINUX)</strong>라고 이름이 붙여진다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/39ac48eb-d9c8-43c6-aa11-fab256e53e23/image.webp" alt=""></p>
<p>리눅스는 그 후로 엄청난 성공을 거두었다. </p>
<p>리눅스는 지구상에서 가장 널리 쓰이는 운영체제다. 수십 억개의 안드로이드폰, 인터넷을 이루는 서버의 거의 대부분, 자동차, TV 등의 임베디드 장비도 거의다 리눅스를 사용한다. 윈도우가 짱 먹은 데스크탑과 iOS의 아이폰을 제외하고는 리눅스가 짱짱맨이라는 뜻이다. </p>
<blockquote>
<p>21살 프로그래머가 재미로 시작해서 커뮤니티를 통해 발전해온 운영체제가 전세계에서 가장 널리 쓰이는 운영체제가 됐다는 사실은 아무리 생각해도 놀랍다. 
자동차 덕후 한명이 집에서 취미로 사람들을 불러서 수제 자동차를 만들기 시작했는데, 30년 뒤에 갑자기 전세계 1등 자동차 브랜드가 됐다고 상상해보라…</p>
</blockquote>
<p>리눅스는 유닉스와는 분명히 다르다. 하지만 POSIX와 SUS를 지키려고 노력하고 유닉스 철학을 많이 영향받은 ‘유닉스 계열 운영체제&#39;다. </p>
<h2 id="c-언어-표준">C 언어 표준</h2>
<p>아, C 언어 표준도 얘기하고 넘어가야 한다. </p>
<p>C 언어는 1980년대부터 거의 대부분의 개발자들이 쓰는 언어가 되었는데, 딱히 정해진 표준이랄 게 없었다. 여러개의 C 버전이 존재했다. </p>
<p>그래서 미국 표준협회인 ANSI에서 C 언어의 국제 표준을 정했다. 이 표준은 C 언어의 기본 문법, 라이브러리, 헤더 파일을 정의한다. </p>
<p>ANSI C 표준의 첫 버전은 89년에 나왔는데 C89라고 불린다. 그 외에 C90, C95, C99를 거쳐 가장 최근에는 C11까지 나왔다. </p>
<h2 id="표준-인터페이스">표준 인터페이스</h2>
<p>&#39;표준&#39;에 대해서 이렇게 길게 얘기한 이유가 있다. 운영체제 개발자들이 절대로 <strong>이 표준 인터페이스를 벗어나지 않으려고 엄청 노력</strong>하기 때문이다. </p>
<blockquote>
<p>&quot;시스템 콜 인터페이스는 돌에 새겨진 글씨와 같다.&quot;
&lt;리눅스 시스템 프로그래밍&gt;, 로버트 러브</p>
</blockquote>
<p>전세계 수많은 개발자들이 이 표준에 맞춰서 개발을 하고 있다. 함부로 인터페이스를 변경하면 엄청난 문제가 될 수 있다. </p>
<p>반대로 말하면 <strong>표준을 잘 따르면 우리가 작성하는 프로그램이 어떤 기기나 환경에서도 제대로 돌아간다</strong>는 것이다. </p>
<p>따라서 시스템 프로그래밍에서 표준은 매우 중요하다.</p>
<p>시스템 프로그래밍을 배운다는 것은 표준 인터페이스를 배운다는 뜻이다. 운영체제마다 내부 구현은 다르겠지만, 표준 인터페이스는 최대한 지킨다.</p>
<p>리눅스도 공식적으로 POSIX나 SUS 인증을 받은 것은 아니지만, 이 인터페이스를 따르지 않으면 버그로 취급한다고 한다.</p>
<p>앞으로 우리가 배울 시스템 콜은 ‘리눅스&#39;와 POSIX 표준을 기준으로 한다. <del>왜냐하면 내가 리눅스 시스템 프로그래밍 책으로 공부했으니까.</del> </p>
<p>리눅스는 가장 널리 쓰이기도 하고, iOS 또한 POSIX를 따르는 유닉스 계열이다.</p>
<h2 id="api와-abi">API와 ABI</h2>
<p>호환성과 표준에 대해 얘기할 때 하나 짚고 넘어가야할 용어가 있다. 바로 API와 ABI다.</p>
<p><strong>API, ABI는 이 시스템 호환성에 매우 큰 영향을 끼친다.</strong> </p>
<p>왜냐? 둘 다 &#39;인터페이스&#39;이기 때문이다.</p>
<h3 id="인터페이스란-접점이다">인터페이스란 &#39;접점&#39;이다.</h3>
<blockquote>
<p>인터페이스란 무엇인가?</p>
</blockquote>
<p><strong>인터페이스는 서로 다른 소프트웨어/하드웨어를 이어주는 &#39;접점&#39;</strong>이다. </p>
<p>이 접점이 들어맞을 때, 서로 다른 소프트웨어나 하드웨어를 쉽게 갈아끼워서 사용할 수 있게 된다. 즉, 호환이 된다.</p>
<p>만약 A 모듈이 B라는 접점에 맞도록 구현되어있다고 하자. 모두 B라는 접점을 가지는 B1, B2, B3가 있다. 얘네들이 실제 모양은 달라도 A는 모두 문제없이 사용할 수 있다. 즉 호환성을 가지게 된다.</p>
<p>마치 다용도 드라이버를 생각하면 된다. 조립식으로 된 드라이버를 본 적이 있을 것이다. 드라이버 손잡이하고 맞으면 언제든지 다양한 모양의 드라이버를 끼워서 사용할 수 있다.</p>
<p><img src="https://sc04.alicdn.com/kf/H86a1d2e68e4044aab0fb5ec3b676603bM.jpg" alt=""></p>
<p><strong>&#39;인터페이스&#39;</strong>는 아마 컴퓨터를 배우면 가장 많이 등장하는 단어중 하나일 것이다. </p>
<p>왜냐하면 컴퓨터 공학의 기본 원리가, <strong>매우 복잡하고 거대한 시스템을 작고 뚜렷한 모듈로 쪼개고, 그 모듈들 간의 접점을 설계하는 일</strong>이기 때문이다. </p>
<p>쉽게 말해, <strong>컴퓨터 공학은 일체형 가구가 아닌 조립식 가구를 지향</strong>한다. 조립식 가구에서 중요한 것은 조립하는 부품들 간의 접점이 잘 맞아들어가는가다.</p>
<p>아무튼 API와 ABI는 둘다 인터페이스다. 어떤 수준의 인터페이스인지만 다르다.</p>
<h3 id="소스-코드-수준의-접점-api">소스 코드 수준의 접점: API</h3>
<p>시스템 수준에서 <strong>API는 소스 코드 수준에서의 인터페이스</strong>를 말한다. </p>
<p>즉, API는 소스 코드와 컴파일러 사이의 &#39;접점&#39;이다. 예를 들어, <code>printf()</code> 라는 함수를 사용했을 때 콘솔에 출력을 할 수 있다는 인터페이스가 대표적이다.</p>
<p>C 라이브러리는 메모리 관리, 문자열 처리 같은 기능을 사용할 수 있는 C 언어 인터페이스 (API)를 제공한다. </p>
<p>대표적인 운영체제 API는 유닉스/리눅스 계열을 위한 POSIX API, 윈도우즈 시스템을 위한 Windows API가 있다.</p>
<p>C 컴파일러는 API를 제대로 사용한 소스 코드를 받아서, 컴파일과 링크를 거친다. 우리가 원하는 바이너리 코드로 바꿔준다.</p>
<h3 id="바이너리-수준의-접점-abi">바이너리 수준의 접점: ABI</h3>
<p><strong>ABI는 바이너리 코드 수준에서의 인터페이스</strong>다. 바이너리와 하드웨어 간의 &#39;접점&#39;이다.</p>
<p>&quot;&#39;aa&#39;라는 레지스터에 1이라는 값을 넣으려면 &#39;010010110&#39;라는 바이너리 코드를 사용한다&quot; 같은 인터페이스가 표적이다. CPU는 여러가지 연산 기능을 사용할 수 있는 바이너리 코드 인터페이스 (ABI)를 제공한다.</p>
<p><img src="https://cdn.kastatic.org/ka-perseus-images/135ea17701cc5f293999fea26bc98f8446ac3a73.svg" alt=""></p>
<p>컴파일러가 소스코드를 컴파일한 명령어 덩어리(프로그램)가, 이 시스템에서 원하는 대로 실행될 수있게 해준다.</p>
<p>만약 x86의 ABI에 맞춰서 컴파일한 코드를, ARM CPU를 가진 기기에서 돌리려고 하면 실행이 되지 않는다. 둘의 ABI가 다르기 때문이다.</p>
<p>즉, ABI는 하드웨어(CPU) 아키텍처와 밀접한 관련이 있다. 각 CPU 아키텍처마다 서로 다른 ABI를 가지고 있고, 이게 호환성에 영향을 미친다.</p>
<p>우리가 맥에서 소프트웨어 실행 파일을 다운로드 받을 때 인텔 맥용 프로그램이 따로 있고, M1 맥용 프로그램이 따로 있는 이유다. 이 둘은 ABI가 다른 CPU를 사용한다.</p>
<p>하지만 대부분의 프로그래머에게는 ABI보다는 API가 훨씬 익숙하다. </p>
<p>사실상 ABI는 크게 신경쓸 일이 없다. API만 잘 맞추면 컴파일러가 알아서 컴퓨터 구조에 맞춰 처리하기 때문이다. </p>
<p>하지만 ABI가 있다는 것은 알아두자.</p>
<h2 id="요약-정리">요약 정리</h2>
<ul>
<li>대부분의 현대 운영체제는 유닉스에서 시작해서 다양한 버전으로 갈라져 나왔다.</li>
<li>유닉스 표준을 두고 유닉스 전쟁이 일어났고, 결과적으로 POSIX와 SUS라는 2개의 표준이 생겼다.</li>
<li>POSIX는 &#39;유닉스 계열&#39;의 기준이고, SUS는 &#39;유닉스&#39;의 기준이다.</li>
<li>시스템 프로그래밍을 배운다는 것은 이 표준 인터페이스를 배운다는 뜻이다.</li>
<li>API는 소스 코드 수준에서의 인터페이스, ABI는 바이너리 수준에서의 인터페이스를 뜻한다. 이 둘은 특정 소프트웨어의 이식성/호환성을 결정한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[시스템 콜은 운영체제의 '프론트 데스크'다]]></title>
            <link>https://velog.io/@eddy_song/system-call</link>
            <guid>https://velog.io/@eddy_song/system-call</guid>
            <pubDate>Sun, 14 Aug 2022 05:31:26 GMT</pubDate>
            <description><![CDATA[<h2 id="컴퓨터를-쓴다--동시에-여러-프로그램이-하드웨어를-사용해-명령어를-실행한다">컴퓨터를 쓴다 = ‘동시에 여러 프로그램’이 ‘하드웨어를 사용’해 ‘명령어를 실행’한다</h2>
<blockquote>
<p>‘컴퓨터를 쓴다’는 건 무엇을 의미할까?</p>
</blockquote>
<p>컴퓨터를 쓰는 목적은 다양하다. 엄청나게 다양하다. </p>
<p>하지만 단순화해본다면, <strong>컴퓨터를 쓴다는 건, 곧 &#39;프로그램을 실행한다&#39;와 같은 말이다.</strong> 컴퓨터 사용자는 프로그램을 실행시켜서 컴퓨터(하드웨어)를 사용한다. (그리고 엄청나게 다양한 프로그램이 있겠지.)</p>
<p>프로그램은 커다란 명령어 덩어리다. 컴퓨터가 알아들을 수 있는 언어로 작성돼있다. </p>
<p>프로그램을 실행하면 프로세서가 명령어를 한 줄씩 처리한다. </p>
<p>1 더하기 1을 계산하거나, 더한 값을 메모리 0x495942 에 저장하거나. 뭐 이런 일이다. </p>
<p>연산, 저장만 있는 건 아니다. 입출력도 있다. </p>
<p>코드에 따라서 실행중인 프로그램은 컴퓨터에 연결된 키보드나 마우스에서 입력을 받아오기도 한다. 그렇게 받아온 입력을 디스크에 있는 파일에 쓰기도 한다. 인터넷을 사용해 디스크에 있는 파일 내용을 다른 컴퓨터로 보내기도 한다. </p>
<p>프로그램은 명령어를 통해서 다양한 하드웨어를 이용한다. 그런데 프로그램이 하드웨어에 직접 접근하면 문제가 생긴다.</p>
<p>만약 프로그램이 하나뿐이라면, 직접 하드웨어에 접근해서 사용해도 별 문제가 없을지 모른다. (엄청 초창기의 컴퓨터는 실제로 그랬다고 한다.) </p>
<p>하지만, <strong>실제로는 컴퓨터에서 하나의 프로그램만 돌아가지 않는다.</strong></p>
<p>컴퓨터는 여러 프로그램을 동시에 실행시킨다. </p>
<p>지금 여러분이 쓰고 있는 컴퓨터에서 실행 중인 프로그램 목록을 확인해보자. 100개는 가뿐히 넘는다. </p>
<p>즉, 이런 다양한 프로그램이 다같이 프로세서, 메모리, 디스크 같은 하드웨어를 사용해야 한다는 뜻이다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/09a464e7-3a09-4d88-8b13-7bec4a159323/image.jpeg" alt=""></p>
<p>하드웨어는 무한하지 않다. 항상 효율적으로 써야 한다. 각각 특성도 다 다르다. 다양한 프로그램들이 자기 마음대로 하드웨어에 접근해서 쓰면 많은 문제가 생길 수밖에. </p>
<p>그래서 <strong>하드웨어를 관리하고, 프로그램이 필요할 때 하드웨어와 관련된 서비스를 제공하는 시스템 관리자</strong>가 필요하다. </p>
<p>이게 바로 <strong>운영체제가 존재하는 이유</strong>다. </p>
<p>운영체제는 여러 프로그램이 ‘컴퓨터 시스템&#39;을 효율적이고, 안전하고, 편리하게 사용할 수 있게 도와주는 소프트웨어다.</p>
<h2 id="운영체제는-호텔-관리자다">운영체제는 ‘호텔 관리자’다</h2>
<p>설명이 조금 딱딱하다. 쉽게 비유해보자. </p>
<p><strong>컴퓨터 시스템은 호텔 같은 거다.</strong> 방, 침대, 화장실, 식당, 주방, 헬스장, 수영장 등 다양한 시설을 갖추고 있다. </p>
<p><strong>실행 중인 프로그램은 호텔에 체크인한 고객</strong>이다. 호텔은 동시에 수백명의 고객이 사용한다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/015c28a2-25c3-4d76-b80a-77dce0813686/image.jpeg" alt=""></p>
<p>여기에 아무런 관리 시스템이 없다고 생각해보자. 호텔에 들어갔는데 프론트에 아무도 없다?</p>
<p>고객이 알아서 방을 정해서 들어가고, 주방에 가서 음식을 꺼내먹고. 세탁실 가서 직접 침대 시트를 가져온다.</p>
<p>갑자기 다른 고객이 내 방에 들어왔다가 ‘어이쿠 사람 있었네요&#39; 하고 나간다. 관리 시스템이 없으니 당연한 일이다.</p>
<p>그야말로 카오스다.</p>
<p>그래서 현실의 호텔에는 관리 시스템이 있다. </p>
<p>호텔 관리 시스템은 사용자가 체크인 가능한 사람인지 확인한다. 효율적으로 방과 침대를 배분한다. 정해진 사람만 출입할 수 있게 보호한다. 체크아웃한 방은 깔끔하게 청소되도록 한다. 제 시간에 사람들이 조식을 먹을 수 있도록 준비한다. 혹시 고객이 방에 필요한 게 있으면 룸서비스로 갖다준다. </p>
<p>호텔 관리 시스템은 &#39;호텔이라는 한정된, 물리적 시설&#39;을 &#39;여러 명의 고객&#39;이 불편없이 안전하고 효율적으로 이용할 수 있도록 한다.</p>
<p>이 ‘관리 시스템’이 바로 운영체제다. (말 그대로 관리(Operating) 시스템(System)이네.) </p>
<p>운영체제는 프로그램들이 문제없이 실행되도록 하기 위해 어마무시하게 많은 일을 한다. </p>
<p>특히 그 중에서도 <strong>가장 중요한 건 자원 배분</strong>이다. 프로세서, 메모리, 디스크 자원은 모든 프로그램들이 필요로 한다. </p>
<blockquote>
<p>운영체제는 <strong>‘가상화&#39;</strong>를 통해 각 프로그램들이 편리하게 이 자원을 사용하도록 하고, <strong>하드웨어를 최대한 효율적으로 사용할 수 있도록 배분</strong>한다. </p>
</blockquote>
<p>갑자기 좀 어려운 단어들이 나왔지만, 걱정할 필요는 없다. 사실 저 한 줄이 앞으로 우리가 주구장창 공부할 내용이라고 봐도 되니까. </p>
<p>지금은 &#39;왜 컴퓨터에 운영체제가 필요하고 어떤 일을 하는지&#39;만 이해하면 된다.</p>
<p>호텔은 다소 단순화시킨 비유다. 하지만 추상적인 컴퓨터 공학을 이해하는 데 있어서 약간의 단순화와 구체화는 필수적이다. </p>
<p>*<em>개념이 잘 와닿지 않을 때 호텔을 하드웨어, 실행 중인 프로그램을 투숙객, 호텔 관리자를 운영체제라고 생각해보자. *</em>개인적으로 운영체제의 개념을 이해하는 데 도움이 많이 된다고 생각한다.</p>
<blockquote>
<p>💡 <strong>‘운영체제’와 ‘커널’</strong>
프로그램에게 하드웨어 자원을 배분하고 관리하는 부분을 ‘커널&#39;이라고 한다. 
우리가 위에서 말한 ‘시스템 관리자’가 커널이다. 좁은 의미로는 커널이 운영체제 그 자체라고 봐도 문제없다.</p>
</blockquote>
<blockquote>
<p>하지만 넓은 의미의 운영체제는 커널뿐 아니라 각종 유틸리티를 포함한다. 반드시 커널의 일부일 필요는 없지만, 보통 운영체제를 깔면 같이 들어있는 프로그램까지도 포함하는 개념이다. 그래픽이나 멀티미디어를 지원한다든지, 사용자의 파일 탐색을 도와주는 프로그램 같은 것들 말이다. </p>
</blockquote>
<blockquote>
<p>우리는 운영체제의 핵심 작동 원리를 배우고 있기 때문에, 운영체제라고 하면 좁은 의미의 운영체제, ‘커널’을 뜻한다. 따라서 이 글에서 운영체제와 커널은 섞여서 나올 것이고, 같은 의미라고 보면 된다.</p>
</blockquote>
<h2 id="시스템-콜은-프론트-데스크다">시스템 콜은 ‘프론트 데스크’다</h2>
<p>실행 중인 프로그램은 운영체제에게 다양한 요청을 할 수 있다.</p>
<blockquote>
<p>‘디스크에 파일 데이터를 써주세요’
‘이 프로그램을 실행시켜주세요’ 
‘이 IP 주소로 메시지를 보내주세요&#39;</p>
</blockquote>
<p>실제로 프로그램이 어떻게 운영체제에게 서비스를 요청할까?</p>
<p>다시 호텔의 비유로 돌아가보자. </p>
<p>우리는 컴퓨터라는 호텔에 묵고 있는 고객, 즉 실행 중인 프로그램이다. 아침 식사를 방으로 배달시키고 싶다. 그렇다고 해서 직접 주방에 가서 요리사한테 ‘아침 좀 배달해주세요~’하지는 않는다. </p>
<p>호텔 서비스를 이용할 때는 일단 무조건 ‘프론트 데스크&#39;에 전화를 한다. </p>
<p>프론트 데스크에서는 해당 전화 요청을 받고, 가능한 요청인지 확인한다. 프론트는 해당 서비스를 해줄 부서 (주방)에 요청을 전달하고, 고객에게 결과물을 갖다준다. </p>
<p><strong>프론트 데스크는 고객과 호텔 서비스의 접점, 즉 ‘인터페이스&#39;다.</strong></p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/c563c50d-e8f1-4197-9083-e619613d3cae/image.jpeg" alt="">
(출처: 그랜드 부다페스트 호텔 스틸 컷)</p>
<p>마찬가지로 <strong>운영체제의 서비스를 이용할 때도, 정해진 접점</strong>이 있다. </p>
<p>이걸 <strong>‘시스템 콜&#39;</strong>이라고 한다. (방에 있는 프로그램이 시스템에 ‘전화&#39;를 한다고 연상해보자.)</p>
<blockquote>
<p>&quot;엄밀히 말해, 시스템 콜이 곧 운영체제다. 시스템 콜이 운영체제의 서비스를 정의하기 때문이다.&quot;
&lt;유닉스의 탄생&gt;, 브라이언 커닝핸</p>
</blockquote>
<p>운영체제의 기능은 운영체제 내부에 구현이 돼있다. 실행 중인 프로그램은 이 기능을 건드릴 수 없다. 다만 요청할 뿐이다. 운영체제에서 미리 정해놓은, ‘시스템 콜&#39;을 통해서.</p>
<blockquote>
<p>&quot;시스템 프로그래밍은 시스템 콜에서 시작해서 시스템 콜로 끝난다.&quot;
&lt;리눅스 시스템 프로그래밍&gt;, 로버트 러브</p>
</blockquote>
<p>시스템 콜을 배우는 건 운영체제를 사용하는 법을 배우는 것이다. 시스템 소프트웨어는 운영체제의 기능을 활용해 애플리케이션 소프트웨어를 지원해주는 소프트웨어다. </p>
<p>그러니** 시스템 프로그래밍은 시스템 콜을 다루는 프로그래밍**이라고 해도 된다.</p>
<p>대표적인 시스템 콜 하나를 보자. </p>
<p><strong><code>read()</code> 함수는 파일을 읽는 시스템 콜</strong>이다. </p>
<p>인자로 파일을 가리키는 파일 디스크립터와, 읽은 데이터가 저장될 버퍼, 읽어들일 바이트 수를 넘겨준다. 함수의 return 값은 읽어들인 데이터의 바이트 개수다.</p>
<pre><code class="language-c">#include &lt;unistd.h&gt;

ssize_t read (int fd, void *buf, size_t len);</code></pre>
<p>프로그램에서 이 <code>read()</code> 함수를 사용한 순간, 커널에 시스템 호출이 전달된다. </p>
<p>그 순간, 실행의 제어권이 ‘사용자 영역’에서 ‘커널 영역&#39;으로 넘어간다. </p>
<p>실행 중이던 프로그램의 컨텍스트는 잠시 정지된다. 커널 영역의 코드를 실행한다. read()와 매칭된 파일을 읽는 기능이 커널 내부에 구현돼있다. 커널 영역에서는 모든 하드웨어에 접근할 수 있다. </p>
<p>커널은 사용자 영역에서 넘겨준 데이터를 사용해 파일 데이터를 읽어온다. 그리고 읽어온 데이터를 버퍼에 저장하고, 바이트 개수를 return한다.  </p>
<p>커널이 제어권을 가지고 있을 때는 커널 모드, 또는 커널 영역이라고 하고, 실행중인 프로그램이 제어권을 갖고 있을 때는 ‘사용자 모드&#39; 또는 ‘사용자 영역&#39;이라고 한다. (커널 입장에서 실행 중인 프로그램은 ‘사용자&#39;이기 때문이다.) </p>
<p>이제 프로그램이 어떻게 운영체제의 서비스를 이용하는지 이해가 되었겠지?</p>
<p>유닉스 계열 운영체제에는 시스템 콜이 수백 개 정도 있다고 한다. 중요한 것을 몇 개 나열해보면 다음과 같다.</p>
<ol>
<li>프로세스 생성, 실행, 종료: fork(), exec(), wait()</li>
<li>파일 읽고 쓰기: open(), read(), write()</li>
<li>장치 관리: brk(), read(), write()</li>
<li>정보 얻기: getpid(), time()</li>
<li>통신: pipe(), bind(), connect()</li>
</ol>
<h2 id="시스템-프로그래밍의-표준어-c">시스템 프로그래밍의 표준어, C</h2>
<p>시스템 프로그래밍을 얘기하기 위해서, <strong>시스템 콜 말고도 반드시 알아야할 것이 바로 C 언어</strong>다.</p>
<p>위에서 설명한 시스템 콜은 모두 C 언어 함수 형태였다. 시스템 콜은 반드시 C 언어로 사용할 필요는 없지만, 거의 대부분 C 언어로 사용된다. </p>
<p>왜? C 언어가 시스템 프로그래밍의 표준 언어이기 때문이다. 대부분 개발 문서가 국제 표준어인 영어로 되어있는 이유와 비슷하다.</p>
<blockquote>
<p>왜 C 언어가 시스템 프로그래밍의 표준어가 되었을까? </p>
</blockquote>
<p>C 언어는 원래 시스템 프로그래밍용으로 태어난 언어다. C 언어는 유닉스(UNIX)라는 운영체제를 프로그래밍하기 위해 만들어졌다.  이후 다시 얘기하겠지만, 유닉스는 윈도우를 제외한 거의 모든 운영체제의 조상이다. </p>
<p>원래 유닉스 운영체제는 저수준 언어인 어셈블리어로 작성됐다. 하지만 어셈블리어는 컴퓨터 아키텍쳐마다 달랐다. 그래서 컴퓨터 구조가 바뀌면 운영체제 코드를 새로 짜야했다.</p>
<p>하지만 C 언어는 (상대적인) 고수준 언어다. C 코드는 아키텍처와 상관없이 사람이 읽기 좋은 형태로 작성했고, C 컴파일러가 컴퓨터 구조에 맞게 컴퓨터가 알아들을 수 있는 바이너리로 변환해주었다. </p>
<p>&lt;유닉스의 탄생&gt; 책을 보면 C 언어로 유닉스를 코딩하자, 유닉스 개발이 탄력을 받았다고 한다. </p>
<p>초기 운영체제는 하나의 프로그램이 다른 컴퓨터에서 실행될 수 있는지, 이식성이 중요한 이슈였다. 그런데 C 컴파일러만 있으면 운영체제를 크게 바꾸지 않고도 여러 컴퓨터에서 사용할 수 있었기 때문이다.</p>
<p>C 언어를 만든 ‘데니스 리치’는 유닉스 운영체제를 만든 사람이다. 유닉스 운영체제를 만들다가 이식성을 높이기 위해 C 언어(컴파일러)를 뚝딱 만들어낸 것이다. 그래서 유닉스와 C 언어는 뗄레야 뗄 수 없는 관계다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/9d7503c6-dc28-4cf0-bc62-782e78dc48b4/image.jpeg" alt=""></p>
<p>C 언어는 &#39;당시 다른 저수준 언어보다&#39; 훨씬 사용하기 편했다. 유닉스의 인기와 함께 계속 퍼져나갔다. </p>
<p>대부분의 웹 브라우저, 거의 모든 언어의 컴파일러, 거의 모든 데이터베이스, 대부분의 운영체제, 텍스트 에디터부터 MS 오피스까지 모두 C로 만들어졌다. 이후 나온 Java, C#, Python, PHP, Javascript 같은 고수준 언어에도 엄청난 영향을 미쳤다.</p>
<p>아무튼 결론은, C 언어는 절대적인 위치를 차지하는 표준어라는 것. 적어도 시스템 수준의 프로그래밍에서는 거의 &#39;영어&#39;급의 표준이다.</p>
<p><strong>‘시스템 프로그래밍 한다’는 곧 C 언어로 프로그래밍한다라는 뜻</strong>이다.</p>
<h2 id="시스템-프로그래밍의-3가지-주춧돌-시스템-콜-c-컴파일러-c-라이브러리">시스템 프로그래밍의 3가지 주춧돌: 시스템 콜, C 컴파일러, C 라이브러리</h2>
<p><strong>시스템 콜</strong> 인터페이스도 대부분 C 언어로 표준화돼있다. 시스템 프로그래밍을 할 때는 C 라이브러리와 C 컴파일러를 사용해서 코딩을 하게 된다.  </p>
<p><strong>C 컴파일러</strong>는 C 언어 소스코드를 컴퓨터에서 실행할 수 있는 바이너리(기계어) 파일로 만드는 소프트웨어다. C 컴파일러 세상에 존재하는 거의 모든 컴퓨터에서 실행 가능하다. </p>
<p><strong>C 라이브러리</strong>는 자주 사용하는 코드를 미리 컴파일해둔 것으로, 흔히 libc(립씨)라고 부른다. 데이터를 조작하고 계산하는 함수들 뿐만 아니라, 시스템 콜을 더 편하게 사용할 수 있도록 만든 함수들도 존재한다. </p>
<p>&lt;리눅스 시스템 프로그래밍&gt;에서는 시스템 프로그래밍의 3가지 주춧돌이 시스템 콜, C 라이브러리, C 컴파일러라고 한다. </p>
<blockquote>
<p>나는 C 언어로 프로그래밍을 해본 적이 한번도 없었다. 시스템 프로그래밍을 배우면서 처음으로 공부하게 됐다. 
확실히 어려웠다. 기존에 배웠던 Swift와 비교해봤을 때 확실히 C 언어는 운영체제와 매우 가깝고, 추상화가 덜 되어있다. 특히 직접 메모리 상태를 생각하고 관리해야하는 부분이 그렇다. 
하지만 Swift도 C 언어의 손자이기 때문에 물려받은 부분도 꽤 있었다. 그 차이를 이해하는 건 재미있는 경험이었다.</p>
</blockquote>
<h2 id="시스템-콜을-쓰기-쉽게-만들어둔-라이브러리-함수">시스템 콜을 쓰기 쉽게 만들어둔 라이브러리 함수</h2>
<p>사용자 영역, 즉 실행 중인 프로그램에서 커널을 사용하는 방법은 몇 가지가 더 있다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/d2500b72-d219-486b-a258-293248cf34e0/image.jpeg" alt=""></p>
<p>그림을 보자. </p>
<p>시스템 콜은 커널을 둘러싸고 있고, 직접 애플리케이션이 시스템 콜을 사용할 수도 있다. </p>
<p>하지만 ‘라이브러리 함수’이나 ‘쉘’을 사용하는 방법도 있다.</p>
<p>먼저 <strong>라이브러리 함수</strong>. 라이브러리란 쉽게 말해 남이 쓴 코드를 내 코드에 가져다 쓰는 것이다. </p>
<p>그 중에서도 ‘시스템 콜’의 기능을 좀 더 편리하게 사용하기 위해서 만들어둔 코드 모음이 있다. 시스템 라이브러리다. </p>
<p>시스템 콜은 아무래도 운영체제에 대해 지식이 필요하거나 명세가 복잡하고, 추가적인 기능이 부족하다. 그렇기 때문에 시스템 콜을 좀 더 쉽게 쓰기 위해서 만들어둔 라이브러리 함수를 만들어둔 것이다.</p>
<p>이전에 나온 <code>read()</code> 시스템 콜을 예로 들어보자. <code>read()</code>는 커널을 직접 호출하는 시스템 콜이다. 하지만 C 표준 라이브러리에서 제공하는 <code>fread()</code>, <code>fgetc()</code>, <code>fgets()</code>라는 함수도 있다. 이 함수들은 내부적으로 <code>read()</code>를 사용하지만 좀 더 편리하게 파일을 읽을 수 있도록 미리 만들어놓은 함수다. </p>
<blockquote>
<p>시스템 호출: 운영체제가 제공하는 좀 더 날것 그대로의 인터페이스. 
C 라이브러리 함수: 편의를 위해 추상화된 층이 씌워진 버전.</p>
</blockquote>
<p><strong>시스템 호출은 곧바로 커널을 호출</strong>하지만, 라이브러리 함수는 C 언어 라이브러리에서 구현하고 있다는 점에서 분명 다르다. </p>
<p>하지만 사용자 입장에서는 크게 다를 건 없다. 커널을 사용하기 위해서 함수를 호출하는 형태는 비슷하다.</p>
<h2 id="명령어-인터페이스를-제공하는-쉘">명령어 인터페이스를 제공하는 쉘</h2>
<p>사용자가 커널을 사용할 수 있는 또 다른 방법은 <strong>쉘</strong>이다.</p>
<p>*<em>쉘은 쉽게 말해, ‘프로그램을 실행하는 프로그램’이다. *</em></p>
<p>개발자라면 터미널을 켜고  <code>ls</code>, <code>cd</code>, <code>rm</code> 같은 명령어를 입력해서 컴퓨터를 조작해본 적이 있을 것이다. 이건 커맨드라인 인터페이스라고 한다. 쉘은 이 커맨드라인 인터페이스를 가능하게 해주는 프로그램이다. </p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/d2803d10-3fae-43ca-9023-87cd61a65e7c/image.png" alt=""></p>
<p>쉘은 사용자가 입력한 명령어를 한 줄씩 읽고 해석한다. 특정한 방식으로 특정한 프로그램을 실행시킨다. </p>
<p>예를 들어, 디렉터리 내 파일을 확인하는 <code>ls</code>라는 명령어가 있다. 유닉스/리눅스에는 ls라는 시스템 소프트웨어가 이미 들어있다. <code>ls</code>는 현재 디렉터리 혹은 특정 디렉터리의 파일 내용을 출력하는 간단한 프로그램이다. </p>
<p>쉘에 <code>ls</code>를 입력하면 쉘이 ls라는 소프트웨어를 실행시킨다. ls라는 소프트웨어는 C 라이브러리 함수나 시스템 콜을 호출해서 파일 정보를 출력한다. 프로그램 실행을 마치면 다시 쉘로 돌아온다.</p>
<p>이런 식으로 명령어를 해석하고 프로그램을 실행해준다. 간단한 작업을 할 때 C 언어로 코딩을 하고 컴파일을 해서 실행시키지 않아도 된다. 직접 파일을 만들거나, 특정 프로그램을 실행하려면 쉘에 명령어만 입력하면 된다.</p>
<p>쉘은 기본으로 제공되지만, 커널에 포함되지 않는 유틸리티 프로그램이다. 얼마든지 다른 쉘을 설치해서 쓸 수 있다. </p>
<p>리눅스나 Mac의 표준 쉘은 bash다. 그 외에 zsh, csh 등 다양한 쉘이 있다.</p>
<p>복잡한 쉘 명령어가 필요하다면, 여러 명령어를 한꺼번에 모으고 조건문, 반복문 등을 사용해 쉘에 입력할 수도 있다. 이런 언어를 쉘 스크립트라고 한다.</p>
<blockquote>
<p>정리하자면, 사용자가 커널을 사용할 수 있는 주요한 방법은 다음과 같다.</p>
</blockquote>
<p>1) 시스템 콜을 호출하는 것 
2) 라이브러리 함수를 호출하는 것 
3) 쉘을 사용하는 것</p>
<p>물론 3가지 모두 <strong>궁극적으로는 시스템 콜을 사용</strong>한다. </p>
<h2 id="요약-정리">요약 정리</h2>
<ul>
<li>컴퓨터를 쓴다는 것은 여러 프로그램을 동시에 실행시킨다는 뜻이다. 각 프로그램들은 명령어에 따라 프로세서, 메모리, 디스크, 키보드 같은 하드웨어 자원을 사용한다.</li>
<li>운영체제는 마치 호텔 관리자처럼, 한정된 하드웨어를 다양한 프로그램이 문제없이 사용할 수 있도록 도와주는 관리 시스템이다.</li>
<li>시스템 콜은 운영체제의 서비스를 이용하는 접점이다. 시스템 콜을 호출하면 제어권이 커널 영역으로 넘어갔다가 사용자 영역으로 돌아온다.</li>
<li>C는 유닉스의 이식성을 높이기 위해 만들어졌으며, 운영체제, 시스템 프로그래밍의 표준어다.</li>
<li>라이브러리 함수는 시스템 콜에 편의 기능을 추가해 언어 차원에서 미리 만들어둔 함수들이다.</li>
<li>쉘은 프로그램을 실행하는 프로그램으로, 명령어 인터페이스를 제공한다.</li>
</ul>
<hr>
<p>시스템 콜은 운영체제마다 구현이 다 다르다. C도 사실 굉장히 많은 버전이 존재한다. </p>
<p>하지만 오늘날 프로그래머들은 그런 차이를 크게 신경 쓰지 않는다. 시스템 콜과 C 언어의 표준이 있기 때문이다. 운영체제와 그 구현은 엄청나게 다양하지만, 대부분이 표준을 따른다. </p>
<p>그래서 <strong>시스템 프로그래밍을 공부한다는 건 이 표준을 배우는 일</strong>이기도 하다. 다음 글에서는 다양한 운영체제의 종류와 표준에 대해서 알아보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[왜 운영체제, 시스템 프로그래밍을 공부해야 하는가]]></title>
            <link>https://velog.io/@eddy_song/system-programming-study</link>
            <guid>https://velog.io/@eddy_song/system-programming-study</guid>
            <pubDate>Tue, 09 Aug 2022 14:06:33 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eddy_song/post/0d83e6d4-e833-4b65-ba8b-43d440ffc64f/image.jpeg" alt=""></p>
<p>첫 출근 날. 업무용 소프트웨어를 이것저것 세팅하고 있었다. 무슨 업무를 하게 될까? 은근 긴장도 되고 설레기도 했다. </p>
<p>그러다 나를 본 CTO님은, 아 오셨군요, 하면서 갑자기 뭔가를 무거운 것을 가져오더니 책상에 쿵 내려놓았다.</p>
<p>두꺼운 책 2권이었다. 둘 다 &#39;시스템 프로그래밍&#39; 책이었다. &#39;시스템 프로그래밍...? 시스템 프로그래밍이 뭐지?&#39; 순간 내 머릿속에 떠오른 생각이었다.</p>
<blockquote>
<p>&#39;자, 이제 이거 스터디를 하시면 돼요.&#39;</p>
</blockquote>
<p>아... 내가 처음 해야할 일은 운영체제, 리눅스 시스템 프로그래밍 공부였다.</p>
<h2 id="시스템-프로그래밍이란-무엇인가">시스템 프로그래밍이란 무엇인가?</h2>
<blockquote>
<p>시스템 프로그래밍이란 무엇일까? 내가 찾아보고 이해한 정의는 이렇다.</p>
</blockquote>
<p><strong>&#39;어플리케이션 소프트웨어&#39;가 아닌 &#39;시스템 소프트웨어&#39;를 프로그래밍</strong>하는 게 시스템 프로그래밍이다. 애플리케이션 프로그래밍의 반대로 시스템 프로그래밍을 이해해보자는 말이다.</p>
<p>우리는 보통 애플리케이션 개발로 프로그래밍에 입문한다. 그래서 애플리케이션이 어떤 건지는 안다.</p>
<p>어플리케이션은 일반 사용자들이 사용할 수 있는 소프트웨어다. 자바, 파이썬, 자바스크립트 같은 고수준 언어를 사용해서 프로그래밍한다. </p>
<p>하지만 여러분은 실제로 이런 애플리케이션을 만들면서, 직접 프로세스를 생성하거나, 디스크에 있는 파일을 열거나, 키보드 장치에서 데이터를 읽는 코드를 쓴 적이 있는가? 아마 없을 것이다.</p>
<p>그렇지만 당연히 소프트웨어는 하드웨어 자원을 사용해야 한다. 그럼 어떻게 된 것이냐? 이 갭은 시스템 소프트웨어가 메꿔준다. </p>
<p>시스템 소프트웨어는 <strong>어플리케이션 소프트웨어가 하드웨어와 저수준 기능을 사용할 수 있도록 도와주는 소프트웨어</strong>다.</p>
<p>보통 커널에서 제공하는 저수준 기능을 활용해서, 다른 소프트웨어에게 좀 더 추상화되고 편리한 기능을 제공한다. </p>
<p>커널이 제공하는 API는 추상화가 많이 되어있지 않은 저수준의 인터페이스다. 직접 사용해서 원하는 프로그램을 만드는 게 상당히 어렵다.</p>
<p>그래서 보통 애플리케이션 프로그래밍에서는 커널을 직접 호출하지 않는다. 대신 컴파일러처럼 시스템 호출을 활용하는 다른 소프트웨어를 사용한다. </p>
<p><strong>시스템 소프트웨어는 자신이 커널을 직접 호출하고 하드웨어 자원을 조작한다.</strong> 다른 프로그램에게는 그 기능을 쉽게 사용할 수 있도록 추상화(단순화)된 인터페이스를 제공한다.</p>
<p>아파치 같은 웹서버, Vim/Emacs 같은 코드 에디터, 커맨드라인 인터페이스를 제공하는 쉘, 각 언어의 컴파일러, 장치 드라이버, mySQL 같은 DB 관리 시스템까지. </p>
<p>이런 것들이 직접 하드웨어와 운영체제를 다루면서, 조금 더 고수준의 어플리케이션에게 기능을 제공하는 시스템 소프트웨어다. (넓은 의미의 시스템 소프트웨어는 운영체제까지 포함한다.)</p>
<h2 id="왜-시스템-프로그래밍을-배워야-하는가">왜 시스템 프로그래밍을 배워야 하는가?</h2>
<blockquote>
<p>프로그램을 실행한다는 건 어떤 의미일까? </p>
</blockquote>
<p>보통 사용자에게는 그냥 &#39;더블 클릭&#39;일 뿐이다. 하지만 실제로 기계 수준까지 내려가면, 그 더블 클릭 하나에 엄청나게 복잡한 동작들이 숨어있다. </p>
<p>하지만 우리는 그 모든 걸 몰라도 프로그램을 실행할 수 있다. </p>
<p>왜냐하면 &#39;추상화&#39;된 시스템을 쓰기 때문이다. 추상화는 컴퓨터 공학의 근본 중의 근본이다. 쉽게 말해 복잡한 기계의 복잡한 작동 원리를 숨기고 단순한 방법으로 사용할 수 있게 만든다는 뜻이다. </p>
<p>시스템을 추상화하면, 세부 사항을 모르고도 시스템을 사용할 수 있다. 컴퓨터 공학은 CPU부터 웹 브라우저까지 &#39;추상화&#39;라는 층을 쌓아서 어려운 일을 쉽게 만든다. </p>
<p>하지만 반대로도 생각해보자. 꼭 좋기만 한 건 아니지 않을까? </p>
<p>추상화된 시스템만 사용하면 우리는 내부의 동작 원리를 알 수 없다. </p>
<p>물론 내부의 동작 원리와 세부적인 구현은 복잡하다. </p>
<p>하지만 <strong>추상화된 경계면 아래를 이해한 프로그래머는 새로운 능력을 갖게 된다.</strong> 상황에 맞게 최적화된 맞춤형 코드를 쓸 수 있고, 추상화된 시스템이 제대로 돌아가지 않을 때 문제를 해결할 수 있다.</p>
<p>&#39;시스템 프로그래밍&#39;은 보통 웹, 앱 개발자들이 잘 건드리지 않는 추상화의 아랫층에 존재한다. </p>
<p>하지만 시스템 프로그래밍을 하려면 하드웨어와 커널이라는 저수준 시스템을 이해해야 한다. 덕분에 시스템 프로그래밍을 이해하면 더 효율적인 프로그래밍을 할 수 있고, 고수준 언어에서 프로그래밍할 때는 도대체 이해할 수 없는 버그들을 해결할 수 있게 된다.</p>
<p>예를 들어 보자. 네트워크 통신을 하는 코드를 작성했. &quot;Too many open files” 이라는 에러가 떴다. 무슨 소리지? 저수준 시스템에 대해 이해하지 못한다면 머리만 아플 것이다.</p>
<p>하지만 만약 시스템 프로그래밍을 배웠다면? </p>
<p>리눅스에서는 통신 인터페이스도 파일의 형태이기 때문에, 네트워크 통신을 할 때 파일을 여는 시스템 콜을 사용한다는 것을 알고 있을 것이다. 리눅스의 프로세스에서 열 수 있는 파일의 최대 갯수는 기본 1024개로 정해져있다는 것도 알고 있을 것이다. </p>
<p>아랫층을 이해한 개발자는 문제를 좀 더 쉽게 해결할 수 있다.</p>
<p>그런 의미에서 많은 개발자들이 실력있는 개발자가 되려면 반드시 갖춰야할 기본기로 &#39;운영체제&#39;와 &#39;컴퓨터 구조&#39;에 대한 이해를 꼽는다. 그리고 시스템 프로그래밍이란 운영체제나 하드웨어(컴퓨터 구조)와 굉장히 밀접한 연관이 있다. 운영체제가 제공하는 서비스를 직접 사용하는 프로그래밍이니까.</p>
<h2 id="소프트웨어-세계의-아랫층으로">소프트웨어 세계의 아랫층으로</h2>
<p>나도 비전공자다. 이번에서야 &#39;시스템 프로그래밍&#39;이 뭔지 제대로 알았다. 물론 운영체제를 공부한 적은 있지만, 소프트웨어 세계의 <strong>복잡하고 심오한 아랫층은 여전히 두려운 장소</strong>다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/03dd9f6f-b779-4f9f-8cdb-a083740fdfdc/image.jpeg" alt=""></p>
<p>하지만 업무로 기본기 공부를 하게 된 이상, 한번 깊이있게 제대로 파보려고 한다. </p>
<p>지금 30% 정도 진도를 나갔다. 내용을 정리하기도 하지만, 결국엔 내 언어로 풀어보면서 설명을 했을 때 가장 잘 이해가 된다고 생각한다. 내가 이해한 운영체제와 시스템 콜의 세계를 시리즈로 포스팅해보려 한다. </p>
<p>주로 읽고 있는 책은 다음과 같다.</p>
<p>📕 <strong>운영체제 10판</strong>, Abraham Silberschatz, Peter Baer Galvin, Greg Gagne 저/박민규 역
📕 <strong>Operating Systems: Three Easy Pieces</strong>, Andrea Arpaci-Dusseau and Remzi Arpaci-Dusseau
📕 <strong>리눅스 시스템 프로그래밍</strong>, Robert Love
📕 <strong>시스템 프로그래밍: 리눅스 &amp; 유닉스</strong>, 이종원</p>
<p>비록 전부 다 상당히 딱딱하고 두꺼운 교과서 책이긴 하지만, 나도 잘 모르는만큼 이 글에서는 엄밀함보다는 직관적이고 쉽고 재미있는 설명에 초점을 맞춘다. </p>
<p>이 시리즈를 읽고 나면 여러분도 딱딱한 교과서를 읽는 것보다는 훨씬 쉽게 전반적인 개념을 잡을 수 있을 것이다.</p>
<p>먼저 시스템 프로그래밍을 이해하기 위한 기본 개념들부터 시작한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[메모리 계층과 캐싱 뽀개기]]></title>
            <link>https://velog.io/@eddy_song/memory-hierarchy</link>
            <guid>https://velog.io/@eddy_song/memory-hierarchy</guid>
            <pubDate>Sat, 16 Jul 2022 06:32:56 GMT</pubDate>
            <description><![CDATA[<p><img src="https://cdn.kbmaeil.com/news/photo/202101/865124_871742_3310.jpg" alt="library"></p>
<p>거대한 도서관을 생각해보자.</p>
<p>이 도서관은 수십만권의 책을 보관하고 있다. 수백년 된 고서부터 신간까지. 이 많은 책은 다 어떤 방식으로 보관하고 있을까?</p>
<blockquote>
<p>뭐... 책꽂이에 꽂아놓겠지.</p>
</blockquote>
<p>쉽게 생각하면 그렇다. 하지만 자세히 들여다보면 더 복잡한 시스템이 있다.</p>
<p>사람들이 <strong>자주 찾는 책이나 신간</strong>은 입구 근처, 눈에 잘 띄는 곳에 배치한다. 책표지가 잘 보이도록 꺼내놓거나 눕혀놓는다.</p>
<p>사람들이 <strong>잘 찾지 않는 책이나 오래된 책</strong>도 있다. 이런 책들은 일반 서가가 아닌 별도 서고에 집어넣는다. 서고는 많은 책을 효율적으로 저장할 수 있는 구조다. 정말 큰 도서관은 보통 사람들이 들어갈 수 없는 서고가 수십개씩 있는 경우도 있다.</p>
<p><img src="https://image.edaily.co.kr/images/Photo/files/NP/S/2016/04/PS16040400349.jpg" alt="서고">
(출처: 이데일리)</p>
<p>디지털 데이터도 마찬가지다. 컴퓨터의 저장 공간도 여러 방식의 층으로 나뉘어있다.</p>
<p>CPU 레지스터는 현재 실행 중인 명령어, 데이터 등을 저장한다. 엄청나게 빨리 데이터를 가져올 수 있다. </p>
<p>그 다음엔 작지만 빠른 캐시 메모리가 있다. 캐시 메모리는 비교적 느린 메인 메모리와 프로세서 사이 중간 다리 역할을 한다.</p>
<p>메인 메모리는 그것보다 더 느린 디스크나 원격 서버의 중간 저장소 역할을 한다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/fdf738a9-e875-4d42-82e0-c34e0f7e0c04/image.png" alt=""></p>
<p>(출처: 컴퓨터 시스템)</p>
<p><strong>모든 컴퓨팅 시스템은 이런 &#39;메모리 계층&#39;을 가진다.</strong> 메모리 계층이 생기는 근본 이유는 2가지다.</p>
<ol>
<li>저장 매체의 가격, 성능 간 트레이드 오프</li>
<li>프로그램이 가지는 지역성(Locality)</li>
</ol>
<p>이 2가지에 대해서는 뒤에 좀 더 자세히 설명하자.</p>
<h1 id="잠깐-우리가-왜-이걸-알아야-하는데">잠깐, 우리가 왜 이걸 알아야 하는데?</h1>
<p>프로그래머가 메모리 계층에 대해 알아야 하는 이유. 프로그램의 성능을 이해하려면 메모리 계층을 알아야 하기 때문이다. </p>
<p>메모리 계층 구조는 프로그램 성능을 좌지우지한다. 프로그램이 사용하는 데이터가 어떤 층에 저장돼있냐, 여기에 따라서 프로그램 성능은 수십배에서 수천만배까지 차이가 난다.</p>
<p>시간이 흐르면서 CPU의 계산 속도와 메모리 접근 속도는 모두 향상되고 있다. </p>
<p>하지만 메모리 접근 속도는 CPU 계산 속도만큼 빠르게 증가하진 않는다. 따라서 <strong>메모리에서 데이터를 &#39;가져오는 시간&#39;은 전체 프로그램 실행 시간을 크게 좌우</strong>한다.</p>
<p><strong>메모리 계층을 잘 알아야 프로그램의 성능을 이해할 수 있다.</strong></p>
<p>이 글을 끝까지 읽고나면 메모리 계층과 캐싱이 무엇인지 알게 될 것이다. 메모리 접근 속도의 원리를 이해하는 개발자가 될 수 있다!</p>
<h1 id="1-저장-매체">1. 저장 매체</h1>
<p>첫번째, 저장 매체 기술.</p>
<p>컴퓨터에는 데이터를 저장하고 유지한 공간이 필요하다. 데이터는 0과 1의 비트로 어딘가에 저장된다. 이 정보를 저장하기 위해 컴퓨터는 다양한 방식을 쓴다.</p>
<p>가장 중요한 3개 카테고리만 알아보자. <strong>RAM, ROM, 디스크</strong>다.</p>
<h2 id="1-ram">1. RAM</h2>
<p><strong>Random Access Memory.</strong></p>
<p>임의 접근(Random Access)은 처음 들으면 무슨 소린지 잘 이해가 안 된다. 랜덤하게 메모리에 접근한다는 뜻은 아니다. 어떤 랜덤한 위치가 주어질 때, 그 위치로 즉시 이동해서 값을 읽을 수 있다는 뜻이다. 덕분에 RAM은 데이터 접근이 빠르다.</p>
<p>반대로 &#39;순차 접근&#39;이 있다. 순차 접근은 어떤 위치가 주어지면, 차례차례 일정한 순서를 거쳐서 해당 위치를 찾아가야 한다.</p>
<p>RAM의 중요한 특징은 &#39;휘발성&#39;이다. <strong>전원이 꺼지면 RAM에 저장된 데이터는 날아간다.</strong></p>
<p>RAM도 2가지 종류가 있다.</p>
<h3 id="static-ram-sram">Static RAM (SRAM)</h3>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Hyundai_RAM_HY6116AP-10.jpg/640px-Hyundai_RAM_HY6116AP-10.jpg" alt="sram">
(wikipedia)</p>
<p><strong>가장 빠르고 비싼 메모리다.</strong> 메모리계의 포르쉐다.</p>
<p>컴퓨터에서는 CPU 내부에 있는 캐시 메모리에 사용된다.</p>
<p>SRAM은 6개의 트랜지스터로 만든 &#39;플립플롭&#39; 회로에 하나의 비트를 저장한다. 트랜지스터가 6개 사용되기 때문에 밀도를 높이거나, 가격을 낮추기가 어렵다.</p>
<p>비싼 대신 빠르고, 안정적이다. SRAM은 &#39;전기가 들어오는&#39; 동안에는 외부 방해에도 끄떡없고, 기록한 비트값이 안정적으로 유지된다. <strong>&#39;Static&#39;</strong> RAM인 이유다.</p>
<p>그렇다면 끄떡있는 녀석도 있겠지? 그게 바로...</p>
<h3 id="dynamic-ram-dram">Dynamic RAM (DRAM)</h3>
<p>흔히 &#39;그 컴퓨터 램 몇 기가야?&#39; 할 때 말하는 바로 그 램이 DRAM이다. 보통 4-32GB 정도 용량이다.</p>
<p>DRAM은 캐시 메모리보다 용량이 더 큰 주 기억 장치 (메인 메모리)에 사용되는 저장 매체다. 컴퓨터의 가장 핵심 부품 중 하나.</p>
<blockquote>
<p>참고로 우리나라 시가총액 1,2위 기업인 삼성전자와 SK하이닉스의 주력 상품이 바로 이 DRAM이다. 전세계 DRAM의 70-80%는 메이드 인 코리아. DRAM은 한국 최대의 수출품이다.</p>
</blockquote>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Pair32mbEDO-DRAMdimms.jpg/220px-Pair32mbEDO-DRAMdimms.jpg" alt="dram">
(wikipedia)</p>
<p>DRAM에 많은 양의 데이터가 들어가는 이유는 뭘까? DRAM은 &#39;캐파시터(Capacitor)&#39;라는 아주 작은 상자에 전자를 담는다. 트랜지스터 1개를 사용해 캐파시터의 뚜껑을 덮고 상태를 유지한다. 캐파시터에 전자가 있으면 1, 아니면 0으로 비트를 표현한다.</p>
<p>캐파시터는 매우 작고, 트랜지스터를 하나만 사용한다. 밀도를 매우 높일 수 있다. 가격도 SRAM보다 저렴하다.</p>
<p>하지만 이 캐파시터의 전자가 시간이 지나면 새어나간다. 시간이 지나면 값이 사라진다. 마치 모래 위에 쓴 글씨처럼. 이게 문제다.</p>
<p>안정적인 SRAM과 다르다고 해서, &#39;<strong>Dynamic</strong> RAM&#39;이라는 이름이 붙었다.</p>
<p>DRAM은 방전되어 내용이 사라지기 전에 충전을 다시 해줘야 한다. DRAM의 전자가 유지되는 시간은 10-100ms 정도다. 0.01초에서 0.1초만 지나면 내용이 사라진다.</p>
<blockquote>
<p>아니, 그런 걸 쓸 수가 있나? </p>
</blockquote>
<p>라는 생각이 들지만, 우리의 시간과 컴퓨터의 시간은 다르기 때문에 괜찮다.
컴퓨터의 클락 사이클은 나노 세컨드다. 계속 충전해가면서 쓰면 된다.</p>
<blockquote>
<p><strong>(중간 요약) SRAM과 DRAM</strong>
빠르고 안정적이지만, 비싸서 조금밖에 못쓰는 게 SRAM.
덜 빠르고 불안정하지만, 싸서 많이 쓸 수 있는 게 DRAM.</p>
</blockquote>
<h2 id="2-rom">2. ROM</h2>
<p>ROM은 RAM과 달리 전원이 꺼져서 내용이 사라지지 않는 메모리다. RAM만큼 데이터를 빠르게 가져올 수는 없다. 하지만 전원이 꺼져도 정보를 저장해주는 믿을 수 있는 친구다.</p>
<p>어떻게 전기가 공급되지 않아도 정보를 저장할 수 있을까? </p>
<p>최초의 &#39;ROM&#39;은 천공 카드라고 한다. 시험 볼 때 쓰던 OMR 카드 같이 생겼다. 여기에 구멍을 뚫어 비트를 표시한다. 물론 손으로 일일이 구멍을 뚫는 건 매우 비효율적이었다.</p>
<p>점점 더 효율적인 ROM들이 등장했다. 프로그래밍이 가능한 PROM, 쓴 데이터를 지울 수 있는 EPROM, 전기로 작동하는 EEPROM 등.</p>
<h3 id="플래시-메모리">플래시 메모리</h3>
<p><img src="https://www.electrorules.com/wp-content/uploads/2022/03/flash-memory.webp" alt="Flash">
(electrorules)</p>
<p>플래시 메모리는 EEPROM의 일종이자 가장 중요한 ROM 기술이다. 1980년대 일본 도시바에서 개발했다.</p>
<p>플래시 메모리는 비휘발성인데도 속도가 빠르고, 내구성이 강하고, 전력도 적게 쓴다.</p>
<p>우리가 사용하는 USB 드라이브, 디지털 카메라, 스마트폰, 노트북, 다 이 플래시 메모리를 사용한다.</p>
<h2 id="3-디스크-드라이브">3. 디스크 드라이브</h2>
<p>윈도우를 써봤다면, &#39;내 컴퓨터&#39; 안에 C 드라이브, D 드라이브를 본적이 있을 거다. 이게 바로 디스크 드라이브다. </p>
<p><img src="https://www.easeus.co.kr/images/partition-manager/windows-10-c-drive-full.png" alt="C-drive"></p>
<p>디스크는 앞에 나온 저장 매체보다 훨씬 느리다. 얼마나 느리냐면... DRAM보다 수십만배 느리다.</p>
<p>대신 디스크는 전원이 꺼져도 데이터가 사라지지 않는다. 무엇보다 엄청나게 많은 용량을 저장할 수 있다.
DRAM은 보통 커야 수십 GB인 반면, 디스크는 수천 GB다.</p>
<p>자주 꺼내기는 힘들지만, 많은 양이 들어가는 창고 느낌이랄까? 그래서 디스크는 컴퓨터에서 &#39;보조 기억 장치&#39; 역할을 한다.</p>
<p>디스크 드라이브에는 전통적인 하드 디스크 드라이브(HDD)와 솔리드 스테이트 드라이브(SSD)가 있다.</p>
<h3 id="하드-디스크-드라이브-hdd">하드 디스크 드라이브 (HDD)</h3>
<blockquote>
<p>LP판을 본 적이 있는가? </p>
</blockquote>
<p><img src="https://cf.shopee.sg/file/5b3587e6ec110cc3aacaf5eb890fcd7d" alt="vinyl"></p>
<p>LP판을 보면 판에 미세한 홈이 파여있다. 이 홈들이 음악 데이터를 저장한다. </p>
<p>턴테이블에 LP를 올리면, 바늘이 홈을 읽어서 음악을 재생한다.</p>
<p><strong>HDD도 같다.</strong> 플래터라고 부르는 원판이 있다. 이 원판에 자성(Magnetic)으로 데이터를 기록하도록 돼있다. </p>
<p>이 원판은 모터로 빠르게 회전한다. 그 위에 헤드라는 녀석이 데이터를 읽고 쓴다.</p>
<p><img src="https://m.media-amazon.com/images/I/81yHZDfM3GL._AC_SL1500_.jpg" alt="HDD"></p>
<p>물리적 속도에 한계가 있다. 데이터가 저장된 위치로 헤드가 이동하는 시간이 필요하다. *<em>접근 속도가 느리다. *</em></p>
<p>반면에 <strong>기록 밀도는 매우 높다</strong>. 많은 양의 데이터가 들어간다. 용량당 가격도 무지 싸다.</p>
<blockquote>
<p>(참고) &#39;하드&#39; 디스크인 이유는, 플로피 디스크라는 (지금은 안 쓰이는) 저장 매체와 구분하기 위해서였다. 플로피 디스크는 구부러지는 &#39;소프트한&#39; 재질이었기 때문.</p>
</blockquote>
<h3 id="솔리드-스테이트-디스크-ssd">솔리드 스테이트 디스크 (SSD)</h3>
<p>SSD는 최근 새롭게 떠오르는 기술이다. 하드 디스크보다 훨씬 더 빠르고, 내구성도 좋다.</p>
<p>SSD가 어떻게 그렇게 빠를 수 있냐? </p>
<p>위에서 말했던 <strong>플래시 메모리를 사용</strong>한다.</p>
<p>기계식 디스크 대신 플래시 메모리 여러개를 담아 디스크로 패키징했다. 보조 기억 장치로 쓰인다는 점은 같지만, HDD와는 사실 구현이 전혀 다르다.</p>
<p>물리적 회전 없이 전자적 방식으로 데이터를 읽고 쓴다. 움직이는 부품이 없으니 소음도 없다. 전력 소모나 내구성도 좋다. 접근 속도도 훨씬 빠르다.</p>
<p>가격 면에서 <strong>아직 하드 디스크보다 비싸다</strong>는 게 유일한 흠이다. 그러나 SSD가격은 빠르게 싸지고 있고, 이 차이는 거의 줄어들고 있다.</p>
<p>휴대성이 중요한 디바이스에서는 완전히 하드 디스크를 대체했다.</p>
<h2 id="4-저장-매체에서-중요한-점">4. 저장 매체에서 중요한 점</h2>
<p>여기까지 주요 저장 매체 기술을 알아봤다.</p>
<p>가장 중요한 시사점 2가지만 꼽아보겠다.
다 안 읽고 스크롤 내렸어도, <strong>이 2가지만 기억</strong>하면 된다.</p>
<h3 id="1-저장-매체의-가격과-성능은-반비례-관계다">1) 저장 매체의 가격과 성능은 반비례 관계다.</h3>
<p><img src="https://i0.wp.com/semiengineering.com/wp-content/uploads/2017/12/fig2.png?fit=529%2C408&ssl=1" alt=""></p>
<p>(semiengineering.com)</p>
<p>&#39;용량당 가격&#39;과 &#39;성능&#39;은 반비례한다. </p>
<p>SRAM - DRAM - SSD - HDD 로 갈 수록, 가격은 싸지고 용량은 늘어나지만, 반대로 접근 속도가 느려진다.</p>
<p>SRAM은 HDD보다 수백만배 빠르다. 용량은 수십만배 적다.</p>
<p>우리는 데이터를 많이 저장하는 것도 필요하고, 빠른 것도 중요하다. 각 저장 매체는 다 명확한 장단점이 존재한다.</p>
<h3 id="2-저장-매체-성능은-프로그램-성능을-결정하는-열쇠다">2) 저장 매체 성능은 프로그램 성능을 결정하는 열쇠다.</h3>
<p><a href="http://www.yes24.com/Product/Goods/31950404">&#39;컴퓨터 시스템&#39;</a> 책을 보면 1985년부터 2015년까지 메모리와 CPU 성능 변화를 비교한 표가 나온다. </p>
<p><strong>&lt;저장 매체 성능 변화&gt;</strong>
<img src="https://velog.velcdn.com/images/eddy_song/post/bdc6e307-52df-4fa0-be2e-01af07473cd9/image.png" alt="">
<img src="https://velog.velcdn.com/images/eddy_song/post/61750aec-d551-48e3-8e9c-d4c552f28eab/image.png" alt=""></p>
<p><strong>&lt;CPU 성능 변화&gt;</strong>
<img src="https://velog.velcdn.com/images/eddy_song/post/2a908b46-0ce4-4bb8-9f8e-e9592d4adb99/image.png" alt=""></p>
<p>30년 전과 비교해볼때, 
SRAM의 접근 속도는 100배 빨라졌다.
DRAM의 접근 속도는 10배 빨라졌다. 
DISK의 접근 속도는 25배 빨라졌다.</p>
<p>하지만 CPU의 실질 속도 (사이클 타임)은 2000배 증가했다.</p>
<p>무어의 법칙이라고 들어본 적이 있겠지? 반도체 칩에 집적할 수 있는 트랜지스터의 숫자가 적어도 매 18개월마다 두 배씩 증가한다는 법칙이다. CPU 속도는 이 법칙에 맞춰 지난 30년간 엄청난 속도로 발전했다.</p>
<p><strong>하지만 메모리의 접근 속도는 그렇게 많이 빨라지지 않았다.</strong></p>
<p>물론 저장 매체의 &#39;가격&#39;은 빠르게 떨어지고 있다. 하지만 속도 측면에서는 메모리-프로세서의 차이가 벌어지고 있다.</p>
<p>따라서 전체 프로그램의 속도를 향상시키기 위해서 &#39;메모리 접근 속도&#39;를 높이는 게 중요하다. 메모리에서 값을 가져와서, CPU가 계산을 하는 게 컴퓨터의 일이다. </p>
<p>&#39;저장 매체의 트레이드 오프&#39;를 고려하면서도 &#39;메모리 접근 속도&#39;를 높이려면 어떻게 해야할까? </p>
<p>다음에 나올 &#39;지역성&#39; 원리가 중요한 이유다.</p>
<h1 id="2-지역성">2. 지역성</h1>
<p>우리는 익숙한 것에 계속 손이 가는 경향이 있다. </p>
<p>옷도 입던 스타일과 비슷한 옷이 편하다. 
음식도 자주 먹던 음식을 많이 찾는다.</p>
<p>프로그램도 데이터를 찾을 때 비슷한 경향이 있다. (물론 프로그램에 취향은 없겠지만)</p>
<p><strong>최근에 찾은 데이터나, 최근에 찾은 데이터 근처의 데이터를 많이 참조한다.</strong></p>
<p>이걸 지역성(Locality)라고 한다.</p>
<p>아주 단순하지만, 프로그램이 보편적으로 가지는 속성이다. 그리고 매우 중요하다. 하드웨어, 소프트웨어의 설계에 어마어마한 영향을 끼치기 때문이다.</p>
<h2 id="시간-지역성">시간 지역성</h2>
<p>최근에 참조된 메모리 위치를 다시 참조할 가능성이 높다. </p>
<p>이 경향을 시간 지역성이라고 한다.</p>
<p>뒤집어 말하면, 동일한 변수를 반복적으로 참조하는 프로그램은 시간 지역성이 있다.</p>
<h2 id="공간-지역성">공간 지역성</h2>
<p>최근에 참조한 메모리 위치 &#39;근처의&#39; 메모리를 다시 참조할 가능성이 높다. </p>
<p>이건 공간적인 개념이라 공간 지역성이라고 한다.</p>
<p>메모리 주소를 차례차례 참조하는 프로그램은 공간 지역성이 있다. 이를 테면 배열의 순회를 돈다든지.</p>
<h2 id="지역성이-있는-코드">지역성이 있는 코드</h2>
<p>컴퓨팅 시스템은 프로그램이 &#39;지역성이 있다&#39;는 가정 하에 최적화를 한다.</p>
<p>하드웨어, 운영체제, 어플리케이션, 웹에 이르기까지 컴퓨팅 시스템의 모든 레벨은 지역성을 활용한다.</p>
<p>최근에 사용한 데이터, 최근에 사용한 위치 근처의 데이터를 빨리 접근할 수 있도록 임시 보관소 (캐시)에 저장해둔다.</p>
<p>지역성이 높은 코드는 캐시를 더 많이 활용한다. 그 결과 실행 속도가 빨라진다.</p>
<p>어떤 코드가 지역성이 있는 코드일까?</p>
<p>같은 변수를 반복적으로 참조하는 코드. 
연속 저장된 데이터를 차례차례 참조하는 코드. (순차 참조)
이런 코드가 지역성이 높다.</p>
<p>순차 참조 패턴을 보이는 코드 중에서도, 참조의 간격이 작을수록 좋은 지역성을 가진 코드다.</p>
<p>예를 들어, 배열의 인덱스를 +1 하는 루프문, +3 씩 도는 루프문이 있다고 하자. +1 루프문이 +3 루프문보다 지역성이 좋다.</p>
<pre><code class="language-javascript">// 1번
for (i = 0; i &lt; columns; i += 1) {
  for (j = 0; j &lt; rows; j += 1) {
    **arr[j][i] ***= 2
  }
}</code></pre>
<pre><code class="language-javascript">// 2번
for (i = 0; i &lt; columns; i += 1) {
  for (j = 0; j &lt; rows; j += 1) {
    **arr[i][j]** *= 2
  }
}</code></pre>
<p>차이를 발견했는가?</p>
<p>아주 조그만 차이 같지만, 1번에서는 j가 행, i가 열이다. 2번에서는 i가 행, j가 열이다.</p>
<p>1번은 [0,0] -&gt; [1,0] -&gt; [2,0] -&gt; [1,1] 순으로 같은 열(column)의 위치부터 참조한다.
2번은 [0,0] -&gt; [0,1] -&gt; [0,2] -&gt; [1,0] 순으로 같은 행(row)를 차례로 참조한다.</p>
<p>배열은 메모리 상에 연속적인 형태로 저장된다. 배열의 인덱스와 메모리 위치를 단순화해본다면 이 순서다.</p>
<blockquote>
<p>(0,0) | (0,1) | (0,2) | (1,0) | (1,1) | (1,2) | (2,0) | (2,1) | (2,2)</p>
</blockquote>
<p>2번 루프는 차례대로 +1 씩 돈다. 1번 루프는 위치상 +3씩 계속 점프한다.</p>
<p>따라서 2번이 더 지역성이 좋은 코드다.</p>
<p>이런 식으로 어떤 코드가 지역성이 있는지 없는지 대략적인 감을 잡을 수 있으면 좋다.
예시를 하나 더 보면서 감을 잡아보자.</p>
<h2 id="퀵-정렬이-빠른-이유">퀵 정렬이 빠른 이유</h2>
<p><a href="https://velog.io/@eddy_song/merge-sort">합병 정렬 (Merge Sort)</a>, <a href="https://velog.io/@eddy_song/heap-sort">힙 정렬 (Heap Sort)</a>, <a href="https://velog.io/@eddy_song/quick-sort">퀵 정렬(Quick Sort)</a>. 빠른 정렬 3총사는 모두 시간 복잡도가 <code>O(N log N)</code>이다. </p>
<p>실제 실행 속도는 퀵 정렬이 가장 빠르다고 알려져있다. &#39;퀵&#39; 정렬인 이유다.</p>
<p>그 이유 중 하나가 바로 &#39;지역성&#39;이다. 퀵 정렬 구현 코드가 힙 정렬이나 머지 정렬보다 지역성이 높기 때문이다.</p>
<p>퀵 정렬은 피벗을 고르고, 파티셔닝하는 과정의 반복이다. 이 과정에서 같은 피벗 위치나, 좁은 범위의 변수를 반복 참조한다. </p>
<p>반면 힙 정렬은 이진 트리에서 부모/자식 노드에 접근하기 위해 계속해서 &#39;곱하기 2&#39; &#39;나누기 2&#39;를 해서 인덱스를 참조한다.</p>
<p>머지 정렬은 아예 새로운 메모리 위치에 배열을 만든다.</p>
<p>따라서 퀵 정렬이 메모리 계층 전반에서 훨씬 더 캐시를 많이 활용한다. 메모리 접근 속도가 줄어드니 성능이 빠르다.</p>
<p>애니메이션으로 보면 이 셋의 차이를 좀 더 직관적으로 이해할 수 있다.</p>
<p><strong>합병 정렬</strong>을 시각화한 애니메이션이다.</p>
<p><img src="https://i.imgur.com/oMbHRV9.gif" alt="merge"></p>
<p><strong>힙 정렬</strong>을 시각화한 애니메이션이다.</p>
<p><img src="https://i.imgur.com/CLGDr3I.gif" alt="heap"></p>
<p><strong>퀵 정렬</strong>을 시각화한 애니메이션이다.
위의 2가지 정렬보다 훨씬 더 고정된, 좁은 범위의 참조가 많이 일어난다.</p>
<p><img src="https://i.imgur.com/GdAe2WF.gif" alt="quick"></p>
<p>(출처: <a href="https://imgur.com/gallery/omL5k">Sorting Algorithm Visualization</a>)</p>
<p>지역성과 캐시의 활용이 얼마나 성능에 영향을 미치는지 실감할 수 있다.</p>
<h1 id="3-메모리-계층과-캐시">3. 메모리 계층과 캐시</h1>
<p>챕터 1과 챕터 2에서 뭘 배웠나?</p>
<p>2가지로 요약해볼 수 있다.</p>
<p><strong>1. 하드웨어의 특성: 저장 매체의 가격-성능 트레이드오프</strong>
-&gt; 빠를수록 비싸다.</p>
<p><strong>2. 소프트웨어의 특성: 프로그램의 지역성</strong>
-&gt; 이미 참조한 위치나 그 근처를 계속 참조한다.</p>
<p>이 2가지 근본 특성이 조합되어, 메모리 계층이 생긴다.</p>
<h2 id="메모리-계층-피라미드">메모리 계층 피라미드</h2>
<p>메모리 계층을 피라미드로 표현한 그림이다.</p>
<p><strong>위로 갈수록 작고 빠르고 비싸다.
아래로 갈수록 크고 느리고 싸다.</strong></p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/f2823fe9-0c64-4466-be01-75b1acee452d/image.png" alt="">
(출처: 컴퓨터 시스템)</p>
<p><strong>* CPU 레지스터</strong>
맨 위에는 레지스터가 있다. 겨우 몇십-몇백 바이트 정도밖에 저장할 수 없다. 프로세서가 즉각 접근할 수 있다. 겨우 1 클락 사이클 밖에 걸리지 않는다. 나노세컨드 (10억분의 1초) 수준에서 가져올 수 있다.</p>
<p><strong>* CPU 캐시</strong>
CPU 안에는 SRAM을 사용한 캐시들이 있다. 이 캐시들도 계층별로 나뉜다. CPU 안에는 L1, 캐시와 L2, L3 캐시가 있다. 각각은 아래 계층의 메모리보다 빠르게 데이터를 가져올 수 있는 캐시로 이뤄진다. 실제 CPU를 보면 캐시가 많은 면적을 차지한다.</p>
<p><img src="https://velog.velcdn.com/images/eddy_song/post/218ef5ff-feaa-43b9-9811-ed55dfd1e33f/image.jpeg" alt=""></p>
<p>*** 메인 메모리 **
DRAM으로 만들어진 메모리가 있다. 데이터를 가져오는 데 수백 클락 사이클 정도가 걸린다.</p>
<p><strong>* 보조 기억 장치 (디스크)</strong>
크기는 매우 크지만, 매우 느린 디스크 저장 공간이 있다.
이 계층에 캐싱을 해두면, 외부 서버에 갔다오지 않고도 데이터를 불러올 수 있다.
메인 메모리 캐시와 다르게 앱을 껐다 켜도 유지가 된다.</p>
<p><strong>* 원격 서버</strong>
같은 기기는 아니지만, 네트워크를 통해 연결된 원격 저장소가 있다. 흔히 HTTP를 통해 데이터를 가져오는 외부 서버다.
대체로 로컬 디바이스보다 훨씬 더 큰 용량이 크다. 대신 네트워크를 거쳐서 가져와야하므로 당연히 훨씬 더 느리다.</p>
<p>원격 서버에서 데이터를 가져오는 애플리케이션은, 대부분 디스크나 메인 메모리에 데이터를 캐싱한다. 원격 웹서버의 데이터를 가져오는 데는 시간이 오래걸리기 때문이다.</p>
<p>예를 들어, 웹 브라우저는 용량이 큰 이미지 등을 브라우저에 캐싱해 놓는다. 이런 캐시 관리 웹 브라우저와 HTTP의 중요한 기능 중 하나다.</p>
<h2 id="캐시-cache">캐시 (Cache)</h2>
<p>여기서 잠깐, 캐시라는 용어에 대해 짚고 넘어가자.</p>
<p>&#39;캐시&#39;란 <strong>더 크고 느린 저장 공간에 있는 데이터를 임시 저장해두는 장소</strong>다.
캐시에 데이터를 저장해두는 것을 캐싱이라고 한다.</p>
<p>캐시는 현대 컴퓨팅 시스템 어디든지 있다. CPU 칩, 분산 파일 시스템, 월드 와이드 웹... 어디를 봐도 캐싱을 사용하지 않는 곳이 없다. 그만큼 중요하다.</p>
<p>사실, 이 캐싱은 우리 일상 생활에서도 정말 흔하다.</p>
<p>신발을 생각해보자. </p>
<p>자주 안 신는 신발은 신발장에 넣어두고, 자주 쓰는 신발은 항상 현관에 나와있다. 왜냐하면 필요할 때 빨리 신을 수 있으니까. <strong>&#39;신발&#39;이 데이터라면 &#39;현관&#39;은 캐시다.</strong></p>
<p><img src="https://img.hani.co.kr/imgdb/resize/2017/0919/150572059449_20170919.JPG" alt=""></p>
<p>(현관도 캐시다. 출처:한겨레)</p>
<p>흔히 CPU에 있는 캐시 메모리든, 웹 브라우저에 저장되는 캐시든 모두 &#39;캐시&#39;라고 퉁쳐서 부른다. 캐시가 특정한 저장 매체를 가리킨다는 느낌이 든다.</p>
<p>하지만 CPU의 캐시 메모리는 &#39;CPU 안에서 캐시 역할을 하는 저장 장치&#39;라는 뜻이다. &#39;캐시&#39; 자체는 특정한 하드웨어를 가리키지 않는다.</p>
<p><strong>캐시는 더 보편적이고 추상적인 &#39;역할&#39;이다.</strong> 캐시라는 이름을 쓰기도 하고 안 쓰기도 하지만, 따져보면 결국 <strong>모든 계층이 캐시 역할</strong>을 한다.</p>
<p><strong>메모리 계층의 본질이 바로 캐싱</strong>이다. 각 레벨의 저장 공간이 다음 레벨의 캐시 역할을 한다.</p>
<p>꼭 저 계층에 표시돼있지 않아도, 우리가 필요하면 얼마든지 중간에 임시 저장소를 만들 수 있다. 그것도 캐시다.</p>
<p>빨라지는 프로세서 속도에 맞춰서, 메모리 속도를 높이기 위해 컴퓨터 공학은 이 메모리 계층을 계속해서 발전시켜야했다. <strong>캐시의 캐시, 그 캐시의 캐시를 만드는 방식</strong>으로. </p>
<p>대부분의 애플리케이션이 자체적으로 캐시를 활용한다. 이 캐시의 성능과 용량을 효과적인 수준으로 유지하기 위해서는 &#39;캐시 관리&#39;를 해야한다. <strong>&#39;캐시 관리&#39;</strong>도 프로그래머가 잘 알아야 하는 주제다.</p>
<hr>
<h2 id="참고-캐싱을-제공하고-돈-버는-회사-cdn">(참고) 캐싱을 제공하고 돈 버는 회사: CDN</h2>
<p>네트워크 상에서 캐싱은 중요하다. 인터넷 사용자들은 점점 더 용량이 큰 이미지, 영상, 게임을 많이 소비하고 있다. 이런 콘텐츠를 빠르고 효율적으로 제공하기 위해 캐싱은 필수다.</p>
<p>콘텐츠 소비자 근처에 캐시 역할을 하는 별도 서버가 필요하다. 거리가 짧으면 그만큼 더 빨리 데이터를 보내줄 수 있기 때문이다. 이런 캐시 서버를 제공하는 서비스를 Content Deilvery Network (CDN)이라고 한다. 잘 알려져있지 않지만 인터넷 인프라의 매우 중요한 축을 담당한다. 전세계 CDN 시장은 10조원이 넘는 크기다.</p>
<p>미국에 있는 유튜브 서버에서 한국에 있는 내 스마트폰으로 영상을 전송한다고 해보자. 이 영상 데이터는 해저 케이블을 타고 태평양을 건너 이런 저런 인프라를 거친다. </p>
<p>하지만 유튜브가 한국인이 자주 찾는 영상을 한국에 있는 서버에 복사해둔다면? 네트워크 사용량도 적고 훨씬 더 빠르게 전송해줄 수 있다. 네트워크 병목이나 원서버의 부하도 줄여준다. 글로벌 서비스를 하는 회사 입장에서는 큰 메리트다. CDN은 전세계에 데이터 센터를 확보하고, 서비스 회사들에게 이런 인프라를 빌려주는 대신 돈을 버는 구조다.</p>
<hr>
<h1 id="4-캐시-관리">4. 캐시 관리</h1>
<p>캐시의 관리는 실제로 캐시를 구현한 각 계층이 담당한다. 관리 방법 또한 구현에 따라서 다르다. 보편적인 몇 개 개념만 살펴보자.</p>
<h2 id="캐시의-성능">캐시의 성능</h2>
<p>만약에 찾는 데이터가 캐시에 있으면, <strong>캐시 히트</strong>다. 캐시에서 바로 데이터를 읽어올 수 있다.
반대로 원하는 데이터가 캐시에 없으면 <strong>캐시 미스</strong>다. 아래 계층으로 넘어가 데이터를 찾아와야 한다.</p>
<p>전체 참조에서 <strong>캐시 히트의 비율을 적중률(Hit Ratio)</strong>라고 한다. (반대는 Miss Ratio.)</p>
<p>캐시의 성능은 주로 &#39;적중률(Hit ratio)&#39;로 표현한다. </p>
<h2 id="캐시-성능과-용량의-트레이드-오프">캐시 성능과 용량의 트레이드 오프</h2>
<p>캐시 용량이 크면 적중률이 올라간다. 캐싱을 해둘 수 있는 데이터가 많아지기 때문이다. </p>
<p>하지만 캐시는 접근 속도가 빠른 대신 용량이 작다고 했다. 어디까지나 임시 저장소이고, 원본 데이터의 일부만 들어간다.</p>
<p>캐시 용량이 다 차면, 필요없는 캐시를 지워준다. </p>
<p>다시 말해 캐시 데이터는 언제든지 삭제될 수 있다. 말 그대로 임시 보관소이기 때문.</p>
<h2 id="캐시-교체-알고리즘">캐시 교체 알고리즘</h2>
<p>그렇다면 캐시 용량이 꽉 찼을 때 어떤 데이터부터 삭제해야할까?</p>
<p>캐시 교체(Cache Replacement) 혹은 캐시 퇴거(Cache eviction)라고 부르며, 이걸 결정하는 알고리즘이 캐시 교체 알고리즘이다.</p>
<p>각 메모리 계층별로 다양한 캐시 교체 알고리즘이 사용된다. 구현과 성능이 다 다르다. </p>
<p>하지만 결국 어떤 데이터를 더 우선순위에 둘 건지를 결정하는 알고리즘이라는 점에서는 다 비슷하다. 대표적인 3가지만 알아보자. </p>
<h3 id="1-fifofirst-in-first-out"><strong>1. FIFO(First in First Out)</strong></h3>
<ul>
<li>가장 먼저 들어간 데이터를 교체.</li>
<li>가장 간단하지만, 지역성을 바탕으로 앞으로 참조될 가능성을 고려하지 않아서 캐시 성능이 떨어진다.</li>
</ul>
<h3 id="2-lfuleast-frequently-used"><strong>2. LFU(Least Frequently Used)</strong></h3>
<ul>
<li>가장 사용 횟수가 적은 데이터를 교체한다.</li>
<li>캐시에 저장을 했는데 &#39;다른 데이터보다 참조하는 횟수가 낮다면, 앞으로도 자주 안 쓰이겠지.&#39; 라고 가정한다.</li>
<li>최근에 저장한 데이터는 참조 횟수가 적기 때문에 교체 가능성이 높은데, 지역성 관점에서는 참조될 가능성이 높기 때문에 이 부분에서는 비효율이 발생할 수 있다.</li>
</ul>
<h3 id="3-lruleast-recently-used"><strong>3. LRU(Least Recently Used)</strong></h3>
<ul>
<li>가장 오랫동안 사용되지 않은 데이터를 교체한다.</li>
<li>LFU와 미묘하게 다르다. 오랫동안 쓰지 않은 데이터가 앞으로도 안 쓰일거라고 가정한다.</li>
<li><strong>시간적 지역성을 가장 잘 반영해서 성능이 높다.</strong></li>
<li>LRU를 구현하기 위해서는 캐시에 저장된 데이터가 사용될 때마다 시간 순서를 기록해야 한다. 여기에 드는 오버헤드가 다른 알고리즘보다 크다.</li>
<li>애플리케이션에서 LRU 캐시를 구현할 때는 Hash Table과 Doubly Linked list를 같이 쓰는데, 코딩 테스트에 자주 나오는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/17680">문제</a>이기도 하다.</li>
</ul>
<h2 id="캐시-무효화">캐시 무효화</h2>
<p>임시 보관소에 있는 복사본을 사용하면, 한가지 더 <strong>골치 아픈 일</strong>이 생긴다. </p>
<p>다른 프로세스나 스레드에서 Disk에 있는 <strong>파일을 수정했는데, 캐시에는 그 수정이 반영이 안된다면 어떨까?</strong> 원본이 바뀌었는데도 캐시 데이터를 여전히 참조해서 일관성 없는 결과를 내놓는다. </p>
<p>즉, 원본 데이터에 변경이 생기면, 느린 저장소에 있는 원본 데이터와 캐시 저장소에 있는 데이터를 일치시켜야한다. </p>
<p>원본 데이터에 변경이 있는 경우 캐시를 무효화해서, 실제 데이터와 일치시키는 메커니즘을 &#39;캐시 무효화&#39;라고 한다. 하위 계층에 데이터가 변경이 있는지 물어보거나, 일정 주기를 기준으로 캐시를 삭제해주는 방법 등이 있다. </p>
<p>흔히 웹브라우저 오류 해결을 하다가, 잘 안 될 때 &#39;캐시 파일을 삭제해보세요~&#39;라는 말을 볼 수 있다. 설정을 변경했는데 캐시에 이전 데이터가 저장되어있으면, 변경된 설정이 반영 안될 수 있기 때문이다.</p>
<h1 id="요약-정리">요약 정리</h1>
<ul>
<li><p>프로그래머는 *<em>프로그램의 성능을 이해하기 위해 *</em>메모리 계층을 알아야 한다.</p>
</li>
<li><p>주요 저장 매체에는 SRAM, DRAM, HDD, SSD 등이 있다. <strong>빠를수록 용량당 가격이 비싸고, 느릴수록 용량당 가격이 싸다.</strong></p>
</li>
<li><p>프로그램은 최근에 참조했거나, 최근에 참조한 데이터 근처에 있는 데이터를 더 많이 참조하는 경향 (지역성)이 있다. </p>
</li>
<li><p><strong>&#39;저장 매체의 트레이드오프&#39;</strong>와 <strong>&#39;프로그램의 지역성&#39;</strong>이라는 근본 특성으로 인해서, 메모리 계층이 생기게 된다. </p>
</li>
<li><p>캐시는 더 크고 느린 저장공간에 있는 데이터를 임시 저장해두는 빠르고 작은 저장공간을 말한다.</p>
</li>
<li><p>메모리 계층에서 위층은 아래층에 대한 캐시 역할을 한다.</p>
</li>
<li><p>캐시의 성능은 적중률(Hit ratio)로 판단할 수 있다. </p>
</li>
<li><p>캐시 용량을 관리하기 위해서는 적절한 교체 알고리즘이 필요하다.</p>
</li>
<li><p>캐시와 원본의 일관성을 유지하기 위해서 캐시 무효화도 필요하다.</p>
</li>
</ul>
<h3 id="참고-문헌">[참고 문헌]</h3>
<ul>
<li>컴퓨터 시스템 3판 / Randal E. Bryan , David R. O&#39;Hallaron</li>
<li>알고리즘, 인생을 계산하다 / 브라이언 크리스천, 톰 그리피스</li>
<li>한 권으로 읽는 컴퓨터 구조와 프로그래밍 / 조너선 스타인하트</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>