<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>mingadinga_1234.log</title>
        <link>https://velog.io/</link>
        <description>딩가딩가 백엔드 개발자</description>
        <lastBuildDate>Sun, 11 Dec 2022 06:40:06 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>mingadinga_1234.log</title>
            <url>https://images.velog.io/images/mingadinga_1234/profile/4343db3d-34bd-445d-8592-91903b39ada4/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. mingadinga_1234.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/mingadinga_1234" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[룰루 밀러, <물고기는 존재하지 않는다>]]></title>
            <link>https://velog.io/@mingadinga_1234/%EB%A3%B0%EB%A3%A8-%EB%B0%80%EB%9F%AC-%EB%AC%BC%EA%B3%A0%EA%B8%B0%EB%8A%94-%EC%A1%B4%EC%9E%AC%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4</link>
            <guid>https://velog.io/@mingadinga_1234/%EB%A3%B0%EB%A3%A8-%EB%B0%80%EB%9F%AC-%EB%AC%BC%EA%B3%A0%EA%B8%B0%EB%8A%94-%EC%A1%B4%EC%9E%AC%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4</guid>
            <pubDate>Sun, 11 Dec 2022 06:40:06 GMT</pubDate>
            <description><![CDATA[<ul>
<li>읽은 기간 : 2022년 12월 8일 ~ 2022년 12월 11일</li>
<li>한줄평 : 생각을 글로 풀어내는 능력이 부럽다</li>
</ul>
<p>인상적인 책이다. 전하고자 하는 메시지가 혁신적이지는 않지만, 자신의 복잡한 생각을 풀어내는 과정을 지켜보는게 흥미로웠다. 무엇보다 &#39;물고기는 존재하지 않는다&#39;라는 메시지를 던지기 위한 빌드업이 좋았다. 물고기를 분류하는데 일생을 바쳤던 데이비드 스타 조던의 조사와 비판과 야사 같은 내용이 책의 2/3를 차지한다. 읽는 내내 &#39;그래서 뭐 어쩌라고.. 고인 능욕이랑 선동을 동시에 하고 있네&#39;라는 생각을 했다. 후반에는 이 인생을 부정하며 본인의 메시지를 부드럽고 효과적으로 전달하여 독자를 설득했으므로 성공적인 시도라고 생각한다. 비록 호불호는 갈리겠지만.</p>
<p>주제 의식에 대한 나의 생각도 풀어봐야지. 나는 &#39;분류&#39;라는 작업을 매우 좋아한다. 복잡하고 앞뒤가 안 맞는 세상을 재단하여 인식하려는 시도라고 생각한다. 복잡한 세상을 이해하는 나름의 방법이다. 그래서 프로그래밍을 공부하면서 코드의 복잡성을 관리하는 객체 지향 패러다임에 끌렸고, 복잡한 세상과 객체를 추상화하려고 노력했다. 이 책을 읽고 나서는 나의 이러한 시도가 지극히 이기적이며 오만한 방법일 수 있겠다고 생각했다. 나 편하자고 기준을 세우고 자체적으로 정의를 내리고 있었던 것은 아닌가? 물론 이 책에서 비판하는 것은 자주적으로 존재하는 자연물의 분류이고, 내가 하는 것은 사람이 만들어낸 객체이지만... 하여튼 편견을 경계해야지. 미움 사봐야 좋을 것 하나 없다.<img src="blob:https://velog.io/5ce66f18-f876-479d-95ca-47a12eb67a1f" alt="업로드중.."></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[김동식, <회색 인간> 시리즈]]></title>
            <link>https://velog.io/@mingadinga_1234/%EA%B9%80%EB%8F%99%EC%8B%9D-%ED%9A%8C%EC%83%89-%EC%9D%B8%EA%B0%84-%EC%8B%9C%EB%A6%AC%EC%A6%88</link>
            <guid>https://velog.io/@mingadinga_1234/%EA%B9%80%EB%8F%99%EC%8B%9D-%ED%9A%8C%EC%83%89-%EC%9D%B8%EA%B0%84-%EC%8B%9C%EB%A6%AC%EC%A6%88</guid>
            <pubDate>Sun, 11 Dec 2022 06:36:45 GMT</pubDate>
            <description><![CDATA[<ul>
<li>읽은 기간 : 2022년 11월 27일 ~ 2022년 11월 30일</li>
<li>한줄평 : 신선한 단편집</li>
</ul>
<p>총 일곱 권의 시리즈. &lt;회색 인간&gt;, &lt;세상에서 가장 약한 요괴&gt;, &lt;13일의 김남우&gt;, &lt;양심 고백&gt;, &lt;정말 미안하지만, 나는 아무렇지도 않았다&gt;, &lt;하나의 인간, 인류의 하나&gt;, &lt;살인자의 정석&gt;. </p>
<p>굉장히 신선한 느낌! SF 소설을 즐기지 않는 이유가 지나친 묘사 때문이었는데, 이 작가는 &#39;만약에&#39;를 먼저 던지고, 주제 의식과 관련된 내용만 제시하는게 마음에 들었다. 이야기에 참여하는 인물의 익명성을 지킨 것도 신선했다. 거대한 옴니버스를 보는 기분. 이야기의 분량이 짧아서 반전이 주는 효과도 극대화된 것 같다.</p>
<p>지금 보니 양이 꽤 많은데 사흘만에 다 읽었다. 단편집을 계속 읽다보니 유튜브 쇼츠 보는 듯한 기분이 들었는데.. 인스턴트 끊자고 책을 읽기 시작한건데 역시 뇌는 익숙한 것에 반응하는구만. 그래도 이 작가 분 단편집 또 나오면 읽어보고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[생택쥐 페리, <야간 비행>]]></title>
            <link>https://velog.io/@mingadinga_1234/%EC%83%9D%ED%83%9D%EC%A5%90-%ED%8E%98%EB%A6%AC-%EC%95%BC%EA%B0%84-%EB%B9%84%ED%96%89</link>
            <guid>https://velog.io/@mingadinga_1234/%EC%83%9D%ED%83%9D%EC%A5%90-%ED%8E%98%EB%A6%AC-%EC%95%BC%EA%B0%84-%EB%B9%84%ED%96%89</guid>
            <pubDate>Fri, 25 Nov 2022 13:10:31 GMT</pubDate>
            <description><![CDATA[<ul>
<li>읽은 기간 : 11월 25일, gdsc 독서 모임</li>
<li>한줄평 : 아름다운 묘사, 입체적인 인간 군상</li>
</ul>
<h2 id="감상">감상</h2>
<p>작품에 나오는 캐릭터가 입체적이어서 흥미로웠고, 책의 주요 사건(야간 비행)이 구체적이면서도 감각적이어서 몰입도 있게 읽었다. 작가가 비행사로 일한 경험이 있어서 그런지 사건의 느낌이 직접적으로 다가왔다. </p>
<p>그외에도 비행 장면의 묘사가 아름다웠다. 되게 은유적인 표현이 많은데 눈 앞에 생생하게 그려졌다.</p>
<p>라비에르 캐릭터가 인상적이었는데, 일하는 태도는 아주 깐깐하고 철두철미하지만 그 밑에는 함께 일하는 사람에 대한 애정이 깔려 있다는 것이 있었다. 역시 사람은 혼자서는 살아갈 수 없다. </p>
<h2 id="🔖-기억에-남는-문장들">🔖 기억에 남는 문장들</h2>
<p>사람들에게 사랑을 받자면, 가엾어 하기만 하면 된다.
나는 거의 가없어 하질 않는다. 어쩌면 그것을 감추고 있는지도 모르지. 그러면서도 나는 우정과 인간의 따사로움으로 둘러쌓여 있기를 정말 좋아한다. 의사는 자기 일을 해가는 동안에 이런 종류의 것을 자주 만난다. 하지만 나는 사건들에 둘러쌓여 봉사하고 있다. 모름지기 나는 나의 사람들을 봉사하는 사람으로 만들어 놓아야 한다. 얼마나 나는 저녁이면 내 사무실에서, 비행교정 문서를 앞에 놓고 이 알 수 없는 법칙들과 씨름하는가. 만약에 내가 되는 대로 내맡겨 둔다면, 번연히 짜여져 있는 업무들을 그대로 진행되게 내맡겨 둔다면 그때엔, 희안한 일이지만 온갖 사고가 생겨난다.</p>
<p>나는 그를 공포에서 건져내주고 싶다. 내가 공격 한 것
은 그가 아니라, 그를 통해서 미지의 것 앞에 인간을 피해 시키는 그 공포를 공격한 것이다. 만약에 내가 그의 말이 귀를 기울이고, 그를 가없이 여기고, 그가 처했던 사건을 진지하게 다뤄준다면, 그는 자기가 어떤 환상의 나라에서 돌아오고 있는 줄로 알 터인데, 바로 환상이라는 것만이 사람에게 공포를 주는 유일한 존재인 것이다.
모름지기 이제는 환상이라는 것이 없어져야 한다. 사람들은 이 침침한 우물 속으로 내려갔다가 다시 솟아 올라와서 나는 아무것도 못 보았노라고 말해야 한다. 모름지기 저 사람은 밤의 맨 깊은 속으로, 그 두께 속으로, 그 희미한 광부의 등불조차 필요 없이 내려가야 한다. 그 등불은 겨우 비행기 날개를 비쳐주는 것이 고작이지만 그 대신 미지의 것을 어깨 넓이만큼 좁게 해 주는 법이다.</p>
<p>그의 고집, 앞만보고 달리는 곰같은 뚝심 때문야. 라고 말했다. 그러나 리비에르는 간단하게, 자기는 그저 올바른 방향에만 힘을 주고 있었기 때문이라고 말했다.
하지만 얼마나 초조했던가, 처음 야간에 비행기를 띄웠 을 때는! 그 시절의 비행기는 날이 밝기 한 시간 전에만 뜨고 해저문지 한 시간 후에는 꼭 착륙해야했다. 리비에르는 자기 경험이 축적되어 확실한 자신이 생겼 다고 판단되었을 때에야 비로소 밤의 깊은 어둠 속으로 감히 비행기를 몰고 들어가게했다. 별로 추종자도 없고 모두에게 부인받는 처지에서, 그는 고독한 투쟁을 해오고 있었던 것이다.</p>
<p>그때 바로 그 순간에, 화비앵의 머리 위에, 태풍의 빈틈 서리로 마치 통발 밑 바닥의 무슨 낚싯밥처럼 몇몇 별들 이 빛났다. 이것이 한낱 함정임을 그는 뚜렷이 헤어렸다. 어떤 구멍 (태풍의 눈) 하나에 별이 세 개 보이고, 그래 그것을 향해서 올라가고, 그러자 곧 다시는 내려올 수가 없고, 그래 거기 머물러 별들을 씹는다. 그러나 빛에 대한 그의 기갈이 워낙 컸기에 그는 타고 올라갔다.</p>
<p>그런데도 아리송한 수 전의 팔들이 그를 놓아주었다. 그 의 온갖 연출을 풀어주고 잠시 꽃들 사이를 혼자 걸어가 게 놓아 두듯이. 너무나 아름답구나 하고 화비앵은 생각했다. 그는 무슨 보물처럼 농밀하게 밀집한 별들 사이를, 다른 것이라 그는 하나도, 정말 완전히 하나도 없고, 오직 자기 화비행과 동료 한 사람만이 살아 어느 세계속을 헤매고 있었다. 거기서 다시는 빠져나올 수 없는 보물실(14초) 속에 갇 힌 저 가공의 도적들과도 같이. 그들은 얼어붙은 돌들 틈에 무한히 행복하지만 죽음의 선고를 받은 사람으로서 헤매고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[조영호, <객체지향의 사실과 오해：역할, 책임, 협력 관점에서 본 객체지향>]]></title>
            <link>https://velog.io/@mingadinga_1234/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4%EF%BC%9A%EC%97%AD%ED%95%A0-%EC%B1%85%EC%9E%84-%ED%98%91%EB%A0%A5-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EB%B3%B8-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</link>
            <guid>https://velog.io/@mingadinga_1234/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4%EF%BC%9A%EC%97%AD%ED%95%A0-%EC%B1%85%EC%9E%84-%ED%98%91%EB%A0%A5-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EB%B3%B8-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</guid>
            <pubDate>Thu, 24 Nov 2022 08:44:50 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/fc4016e9-7cde-4219-9911-daff65d20883/image.jpeg" alt=""></p>
<ul>
<li>읽은 기간 : 2022년 11월 8일 ~ 2022년 11월 24일</li>
<li>한줄평 : 이 책으로 객체지향 세계에 입문했어요
<img src="blob:https://velog.io/c20306e9-2d02-4270-8abd-fffa9640f7fc" alt="업로드중.."></li>
</ul>
<br>

<p>최근 1년간 자바를 많이 사용했다. 객체지향 언어를 사용한다는 것이 객체지향적인 프로그래밍을 하고 있다는 것은 아니라는 말은 많이 들었다. 이 책을 읽고 나서 이 말에 대해 공감할 수 있게 되었다.</p>
<p>나는 자바 공부를 하면서 어떻게 하면 클래스를 잘 설계해서 변경에 취약하지 않은 구조를 만들 수 있는지 고민했다. 클래스의 관점에서 상속, 다형성, 캡슐화 등의 컨셉을 받아들이려고 했다. 코드로는 많이 접해서 익숙해지는 시도를 했으나, 개념적으로는 명쾌한 이해가 어려웠다. 원리를 머리가 받아들이지 못하니 선뜻 코드를 작성할 수 없었다. </p>
<p>이 책을 통해 클래스는 객체를 추상화하기 위한 도구하는 확실한 컨셉을 얻었다. 자바를 사용할 때 클래스를 잘 설계하는 것은 중요하다. 내가 작성한 클래스로부터 객체를 만들어내기 때문이다. 이제는 클래스 설계가 중요한 이유를 객체의 관점에서 보게 되었다. 내가 소프트웨어로 구현하고자 하는 세상을 이루는 것이 객체고, 객체를 분류하기 위한 도구가 클래스이다. 자바는 객체의 분류 도구를 제공하는 것이다.</p>
<p>책에서 반복적으로 설명하는 것이 있다. 바로 협력과 메시지이다. 협력은 우리가 달성하려는 목표이다. 큰 책임을 가진 협력을 달성하기 위해 작은 책임을 가진 여러 객체가 협력에 참여한다. 이때 객체가 다른 객체와 상호작용할 수 있는 유일한 수단은 메시지이다. 객체는 독립적이고 자율적인 책임을 가지기 때문에 다른 객체의 상태를 변화시킬 수 있는 권한이 없다. 이렇게 책을 안 보고도 줄줄 쓰는 것을 보니 책에서 정말 반복을 많이 한 것 같다.</p>
<p>객체가 자율적이어야 시스템 전체의 이해가 쉬워지고 변경도 쉽게 수용한다. 수정으로 인한 파급 효과가 줄어들기 때문이다. 객체는 메시지로 소통한다. 메시지라는 존재 덕분에 객체가 외부와 내부로 철저하게 나뉘어져 변경 사항을 감출 수 있다. 또 같은 메시지를 수신할 수 있다면 협력에 참여하는 객체를 바꿀 수 있다. 같은 책임을 가지면서 더 구체적인 타입을 가지면 이는 서브 클래스이다. </p>
<p>어쨌든 내가 이 책을 읽고 얻은 인사이트는 <strong><em>세상을 객체로 보는 것</em></strong>이다. 나는 요구 사항을 보고 타입부터 설계를 했었다. 이제는 우선 이 협력을 달성하기 위해 어떤 객체가 어떤 책임을 가져야할지부터 고민할 것이다.</p>
<p>마지막 장에 도메인 모델을 만들고, 유스 케이스로 기능을 작성하고, 큰 협력을 객체에게 분배하여 협력 관계를 구성하고, 인터페이스와 내부를 구현하는 과정을 보았다. 책에서는 아주 간단한 예제로 표현을 했는데, 이 방법을 적용하여 설계하는 과정이 궁금해졌다. 왜냐하면 클린 코드 과제할 때 설계로 써먹어보고 싶기 때문이다. 이 책에서 많이 등장했던 &lt;책임 주도 설계&gt;을 볼까 같은 분이 쓰신 &lt;오브젝트&gt;를 볼까 고민했는데, 일단 도서관에서 구할 수 있는 &lt;오브젝트&gt;부터 볼까 한다.</p>
<p>개인적으로 OOP는 정말 매력적인 패러다임인 것 같다. 기능을 구조에 종속시키는 접근 방법이 마음에 든다. 복잡한 세계를 추상화하여 바라보는 것도. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클래스는 개념, 명세, 구현 관점에서 검토한다]]></title>
            <link>https://velog.io/@mingadinga_1234/%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94-%EA%B0%9C%EB%85%90-%EB%AA%85%EC%84%B8-%EA%B5%AC%ED%98%84-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EA%B2%80%ED%86%A0%ED%95%9C%EB%8B%A4</link>
            <guid>https://velog.io/@mingadinga_1234/%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94-%EA%B0%9C%EB%85%90-%EB%AA%85%EC%84%B8-%EA%B5%AC%ED%98%84-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EA%B2%80%ED%86%A0%ED%95%9C%EB%8B%A4</guid>
            <pubDate>Thu, 24 Nov 2022 01:45:59 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 7장</li>
<li>공부 기간 : 2022년 11월 23일 수요일</li>
</ul>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>변경에 유연하게 대응할 수 있는 객체를 작성하는 가장 빠른 방법은 클래스가 개념, 명세, 구현 관점을 명확하게 드러내도록 하는 것이다. 개념은 도메인 모델로부터, 명세는 메시지(안정적인 영역)로부터, 구현은 클래스의 가변적 영역을 드러낸다. </p>
<p>객체지향 시스템을 설계할 때, 도메인 모델을 우선 표현해야 한다. 그리고 객체의 협력 관계를 만들어 인터페이스를 얻는다. 첫 메시지는 기능으로부터 얻고, 객체의 선택은 도메인 모델을 바탕으로 한다. 객체가 수행할 수 없는 책임이 등장하면 그때 다른 객체를 선택한다. 객체 협력 관계가 완성되면 정적 타입으로 분리해 클래스를 작성한다. 인터페이스와 내부 구현을 명확하게 분리한다.</p>
<h1 id="질문">질문</h1>
<ol>
<li>클래스를 설계할 때 고려해야 하는 세 가지 관점은 무엇인가?</li>
<li>도메인 모델은 어떻게 얻을 수 있는가?</li>
<li>객체의 협력 관계를 어떻게 구성할 것인가?</li>
<li>왜 인터페이스와 구현을 명확하게 분리해야 하는가?</li>
</ol>
<h1 id="1-클래스를-설계할-때-고려해야-하는-세-가지-관점은-무엇인가">1. 클래스를 설계할 때 고려해야 하는 세 가지 관점은 무엇인가?</h1>
<p>개념, 명세, 구현이다. 개념은 사용자가 도메인을 바라보는 관점을 반영한다. 명세는 객체의 책임(무엇을)를 바라본다. 구현은 객체가 책임을 수행하는데 필요한 동작 코드(어떻게)를 작성한다. 인터페이스와 구현은 명확하게 분리해야 한다.</p>
<h1 id="2-도메인-모델은-어떻게-얻을-수-있는가">2. 도메인 모델은 어떻게 얻을 수 있는가?</h1>
<p>구현해야 하는 상황을 객체들로 구성해본다. 커피 전문점이라는 도메인은 손님 객체, 메뉴 항목 객체, 메뉴판 객체, 바리스타 객체, 커피 객체로 구성된다. 그리고 객체들 간의 관계를 설정한다. 포함 관계나 연관 관계를 사용할 수 있다. 도메인 모델을 만들면 협력에 필요한 객체의 종류와 책임, 주고받아야 하는 메시지에 대한 대략적인 윤곽을 얻을 수 있다. </p>
<h1 id="3-객체의-협력-관계를-어떻게-구성할-것인가">3. 객체의 협력 관계를 어떻게 구성할 것인가?</h1>
<p>유스케이스에 정리된 시스템의 기능을 도메인 모델을 기반으로 한 객체의 책임으로 분배한다. 협력의 첫 메시지는 시스템의 기능을 책임으로 바꿔 얻을 수 있다. 이 책임을 수행할 객체를 도메인 모델을 바탕으로 선택한다. 커피를 주문하는 최초의 메시지는 손님에게 책임을 분배한다. 손님은 메뉴를 알지 못하므로 메뉴 정보를 얻기 위해 메뉴판 객체에게 메시지를 보낸다. 손님은 커피를 제조하지 못하므로 바리스타 객체에게 메시지를 보낸다. </p>
<h1 id="4-왜-인터페이스와-구현을-명확하게-분리해야-하는가">4. 왜 인터페이스와 구현을 명확하게 분리해야 하는가?</h1>
<p>인터페이스는 클래스의 안정적인 면을 드러내야 한다. 구현은 클래스의 불안정한 면을 드러내야 한다. 인터페이스가 구현 세부 사항을 노출하기 시작하면 아주 작은 변동에도 전체 협력이 요동치는 취약한 설계를 얻을 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[안정적인 구조에 기능을 종속시켜라]]></title>
            <link>https://velog.io/@mingadinga_1234/%EC%95%88%EC%A0%95%EC%A0%81%EC%9D%B8-%EA%B5%AC%EC%A1%B0%EC%97%90-%EA%B8%B0%EB%8A%A5%EC%9D%84-%EC%A2%85%EC%86%8D%EC%8B%9C%EC%BC%9C%EB%9D%BC</link>
            <guid>https://velog.io/@mingadinga_1234/%EC%95%88%EC%A0%95%EC%A0%81%EC%9D%B8-%EA%B5%AC%EC%A1%B0%EC%97%90-%EA%B8%B0%EB%8A%A5%EC%9D%84-%EC%A2%85%EC%86%8D%EC%8B%9C%EC%BC%9C%EB%9D%BC</guid>
            <pubDate>Thu, 24 Nov 2022 01:45:07 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 6장</li>
<li>공부 기간 : 2022년 11월 23일 수요일</li>
</ul>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>설계의 목적은 변화를 수용하는 여지를 남기기 위함이다. 기능이 안정적인 구조를 따라야 변경을 수용할 수 있는 소프트웨어가 된다. 요구사항에 비해 잘 변하지 않는 개념(멘탈 모델)을 표현하는 도메인 모델은 안정적인 구조를 제공한다. 사용자가 도메인에 기대하는 기능은 유스 케이스로 서술한다. 책임 주도 설계는 도메인 모델을 바탕으로 시스템의 책임을 객체에 분배하고, 기능을 바탕으로 책임을 파악한다.</p>
<h1 id="질문">질문</h1>
<ol>
<li>왜 기능이 구조를 따라야 하는가?</li>
<li>기능과 구조의 목표는 무엇인가?</li>
<li>구조는 어떻게 얻을 수 있으며, 이렇게 얻은 구조가 안정적인 이유는 무엇인가?</li>
<li>기능은 어떻게 표현하는가?</li>
<li>책임 주도 설계는 구조와 기능을 어떻게 사용하는가?</li>
<li>연결 완전성과 가역성은 무엇인가?</li>
</ol>
<h1 id="1-왜-기능이-구조를-따라야-하는가">1. 왜 기능이 구조를 따라야 하는가?</h1>
<p>기능은 자주 변경된다. 반면 구조는 기능에 비해 안정적이다. 안정적인 객체 구조는 변경을 수용할 수 있는 유연한 소프트웨어의 기반을 제공한다. 객체 지도는 빠르게 변화하는 기능을 수용할 수 있는 자리를 제공한다.</p>
<h1 id="2-기능과-구조의-목표는-무엇인가">2. 기능과 구조의 목표는 무엇인가?</h1>
<p>기능은 사용자의 목표를 만족시키기 위해 책임을 수행하는 시스템의 행위를 표현한다. 구조는 사용자나 이해 관계자들이 도메인에 관해 생각하는 개념과 개념의 관계를 표현한다.</p>
<h1 id="3-구조는-어떻게-얻을-수-있으며-이렇게-얻은-구조가-안정적인-이유는-무엇인가">3. 구조는 어떻게 얻을 수 있으며, 이렇게 얻은 구조가 안정적인 이유는 무엇인가?</h1>
<p>구조는 도메인 모델을 통해 얻을 수 있다. 도메인 모델은 소프트웨어에 대한 사용자, 설계자의 멘탈 모델을 반영한다. 객체지향은 도메인 모델을 기반으로 객체 구조를 설계하는데, 그 이유는 도메인 모델이 안정적이기 때문이다. 도메인 모델을 구성하는 개념은 비즈니스 정책이 바뀌거나 완전히 개편되지 않는 한 안정적으로 유지된다. 개념은 기능에 비해 변경될 여지가 훨씬 적다. 또 사용자와 설계자가 공유하므로 이해하기 쉬운 시스템을 만든다.</p>
<h1 id="4-기능은-어떻게-표현하는가">4. 기능은 어떻게 표현하는가?</h1>
<p>유스케이스로 표현한다. 유스케이스는 사용자의 목표를 중심으로 시스템의 기능적인 요구사항을 시나리오로 묶어 체계를 만들 수 있다. 이때 유스케이스는 인터페이스와 내부 설계와 관련된 정보를 포함하지 않는다. 사용자 관점에서 시스템의 행위에 초점을 맞춘다.</p>
<pre><code>유스케이스명: 중도 해지 이자액을 계산한다

일차 액터: 예금주

주요 성공 시나리오:
1. 예금주가 정기예금 계좌를 선택한다.
2. 시스템은 정기예금 계좌 정보를 보여준다.
3. 예금주가 금일 기준으로 예금을 해지할 경우 지급받을 수 있는 이자 계산을 요청한다.
4. 시스템은 중도 해지 시 지급받을 수 있는 이자를 계산한 후 결과를 사용자에게 제공한다.

확장.
3a. 사용자는 해지 일자를 다른 일자로 입력할 수 있다.</code></pre><h1 id="5-책임-주도-설계는-구조와-기능을-어떻게-사용하는가">5. 책임 주도 설계는 구조와 기능을 어떻게 사용하는가?</h1>
<p>책임 주도 설계 방법은 시스템의 기능을 역할과 책임을 수행하는 객체들의 협력으로 바라보게 한다. 유스케이스로부터 첫 번째 메세지와 사용자가 달성하려는 목표를, 도메인 모델로부터 기능을 사용할 수 있는 안정적인 구조를 제공받아 객체의 협력 공동체를 구성할 수 있다. 견고한 객체지향 애플리케이션을 개발하기 위해서는 사용자의 관점에서 시스템의 기능을 명시하고, 사용자와 설계자가 공유하는 안정적인 구조를 기반으로 기능을 책임으로 변환해야 한다.</p>
<h1 id="6-연결-완전성과-가역성은-무엇인가">6. 연결 완전성과 가역성은 무엇인가?</h1>
<p>연결 완전성은 도메인 모델링에서 사용한 객체와 개념을 프로그래밍 설계에서의 객체와 클래스로 매끄럽게 변환할 수 있다는 특징이다. 가역성은 연결완전성의 역방향으로, 모델에서 코드로의 매끄러운 흐름을 의미하는 특징이다. 이는 객체지향이 도메인을 모델링하는 기법과 도메인을 프로그래밍하는 기법이 같기 때문이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[메시지에 따라 객체지향을 설계하라]]></title>
            <link>https://velog.io/@mingadinga_1234/%EB%A9%94%EC%8B%9C%EC%A7%80%EC%97%90-%EB%94%B0%EB%9D%BC-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%84-%EC%84%A4%EA%B3%84%ED%95%98%EB%9D%BC</link>
            <guid>https://velog.io/@mingadinga_1234/%EB%A9%94%EC%8B%9C%EC%A7%80%EC%97%90-%EB%94%B0%EB%9D%BC-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%84-%EC%84%A4%EA%B3%84%ED%95%98%EB%9D%BC</guid>
            <pubDate>Thu, 24 Nov 2022 01:43:42 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 5장</li>
<li>공부 기간 : 2022년 11월 22일 화요일</li>
</ul>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>객체지향이 유연한 설계와 재사용성을 높일 수 있는 이유는 협력을 수행하는 방법으로 메시지를 선택하기 때문이다. 메시지는 협력의 문맥에서 객체의 내부와 외부를 구분한다. 따라서 객체는 자율적인 책임을 지니게 된다. 캡슐화, 다형성, 낮은 결합도와 높은 응집도 등의 장점을 자율적인 책임에서 얻을 수 있다. 따라서 객체지향 시스템을 설계할 때는 협력의 문맥에서 메시지(what)을 결정하고 해당 책임을 수행할 객체(who)를 정한다. 객체를 설계할 때도 외부에 오픈할 메시지를 담는 인터페이스와 내부 구현(상태, 행동)을 구분해야 한다.</p>
<h1 id="질문">질문</h1>
<ol>
<li>자율적인 책임은 무엇을 정의하는가?</li>
<li>다형성 지탱하는 것은 무엇인가? </li>
<li>객체지향 설계의 중심은 왜 메시지가 되어야 하는가?</li>
<li>메시지를 먼저 결정하고 메시지에 적합한 객체를 선택하는 방식의 장점은?</li>
<li>공용 인터페이스를 구성하는 것은? </li>
<li>왜 인터페이스와 구현을 분리해야 하는가? </li>
<li>왜 객체는 자율적인 책임을 지녀야 하는가?</li>
</ol>
<h1 id="1-자율적인-책임은-무엇을-정의하는가">1. 자율적인 책임은 무엇을 정의하는가?</h1>
<p>자율적인 책임의 객체가 어떻게 해야 하는가가 아니라 무엇을 해야 하는가를 설명한다. 자율적인 책임은 객체가 협력을 위해 무엇을 해야 하는지 결정하지만 어떻게 해야 하는지는 결정하지 않는다. 책임을 수행할 방법은 객체가 자율적으로 선택한다.</p>
<h1 id="2-다형성-지탱하는-것은-무엇인가">2. 다형성 지탱하는 것은 무엇인가?</h1>
<p>메시지이다. 다형성은 송신자와 수신자 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도를 낮춤으로써 달성된다.</p>
<h1 id="3-객체지향-설계의-중심은-왜-메시지가-되어야-하는가">3. 객체지향 설계의 중심은 왜 메시지가 되어야 하는가?</h1>
<p>협력이라는 문맥에서 개별 객체에 초점을 맞추기 위함이다. 협력 관계 속에서 다른 객체에게 무엇을 제공해야 하고 다른 객체로부터 무엇을 얻어야 하는가라는 관점에서 접근할 때만 훌륭한 책임을 수확할 수 있다. </p>
<h1 id="4-메시지를-먼저-결정하고-메시지에-적합한-객체를-선택하는-방식의-장점은">4. 메시지를 먼저 결정하고 메시지에 적합한 객체를 선택하는 방식의 장점은?</h1>
<p>송신자는 수신자가 어떤 객체인지는 모르지만 자신이 전송한 메시지를 잘 처리할 것이라는 것을 믿고 메시지를 전송한다. 메시지는 어떻게 보다는 무엇을 해야 하는지를 요청한다. 이러한 스타일은 객체를 자율적으로 만들고 캡슐화를 보장하며 결합도를 낮게 유지시킨다. </p>
<h1 id="5-공용-인터페이스를-구성하는-것은">5. 공용 인터페이스를 구성하는 것은?</h1>
<p>공용 인터페이스를 구성하는 것은 객체가 외부로부터 수신할 수 있는 메시지의 목록이다. 책임은 객체가 메시지를 수신했을 때 수행해야 하는 객체의 행동이다.</p>
<h1 id="6-왜-인터페이스와-구현을-분리해야-하는가">6. 왜 인터페이스와 구현을 분리해야 하는가?</h1>
<p>소프트웨어의 변경으로 인한 파급효과을 줄이기 위함이다. 변경해도 무방한 안전 지대를 객체 내부의 구현으로 두고, 변경했을 경우 외부에 영향을 미치는 위험 지대를 구분한다. 객체 외부에 영향을 미치는 변경은 객체의 공용 인터페이스를 수정한다.</p>
<h1 id="7-왜-객체는-자율적인-책임을-지녀야-하는가">7. 왜 객체는 자율적인 책임을 지녀야 하는가?</h1>
<ul>
<li>책임의 추상화 - 자율적인 책임은 세부적인 사항을 무시하고 의도를 드러나는 하나의 문장으로 표현하여 협력을 단순하게 만든다. </li>
<li>캡슐화 - 메시지를 수신하여 책임만 완수할 수 있다면 어떤 방법을 선택할지는 전적으로 객체의 권한이다. 협력의 양상을 외부의 요청과 내부의 수행으로 구분할 수 있다.</li>
<li>낮은 결합도 - 책임이 자율적일수록 변경에 의해 수정되는 범위가 좁아지고 명확해진다. </li>
<li>높은 응집도 - 책임이 자율적일수록 객체의 역할을 이해하기 쉬워진다.</li>
<li>다형성 - 책임이 자율적이면 역할을 대신할 수 있는 객체만 만들어 재사용할 수 있다. 협력이 유연해진다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[역할, 책임, 협력의 관점에서 애플리케이션 설계하기]]></title>
            <link>https://velog.io/@mingadinga_1234/%EC%97%AD%ED%95%A0-%EC%B1%85%EC%9E%84-%ED%98%91%EB%A0%A5%EC%9D%98-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@mingadinga_1234/%EC%97%AD%ED%95%A0-%EC%B1%85%EC%9E%84-%ED%98%91%EB%A0%A5%EC%9D%98-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 24 Nov 2022 01:40:07 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 4장</li>
<li>공부 기간 : 2022년 11월 20일 일요일</li>
</ul>
<h1 id="질문">질문</h1>
<ol>
<li>객체지향 설계의 품질을 결정하는 것은 무엇인가?</li>
<li>협력은 무엇으로 구성되는가?</li>
<li>책임과 메시지의 차이는 무엇인가?</li>
<li>역할을 사용하여 얻을 수 있는 장점은 무엇인가?</li>
<li>책임 주도 설계는 무엇인가?</li>
<li>디자인 패턴은 왜 사용해야 하는가?</li>
<li>테스트 주도 개발과 객체 지향은 어떤 관련이 있는가?</li>
</ol>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>객체지향 설계란 애플리케이션의 기능을 구현하기 위한 협력 관계를 고안하고, 협력에 필요한 역할과 책임을 식별한 후 이를 수행할 수 있는 적절한 객체를 선택하는 과정이다. 핵심은 올바른 책임을 올바른 객체에게 할당하는 것이다.</p>
<p>협력은 요청과 응답으로 이루어지고, 객체는 자신의 책임을 수행하며 다른 객체에게는 메시지를 통해 책임 수행을 요청할 수 있다. 책임의 집합을 추상화하여 역할이라 하며, 동일한 메시지를 이해할 수 있는 객체는 해당 역할을 대체할 수 있다. </p>
<p>책임 주도 설계는 시스템의 책임을 객체의 책임으로 변환하고, 적절한 객체에게 책임을 할당하여 객체들의 협력 공동체를 만든다. 디자인 패턴은 책임 주도 설계의 결과를 코드로 표현하는 템플릿이다. 테스트 주도 개발은 협력이라는 문맥에서 객체의 행동에 대한 기대를 코드로 작성하여 피드백 받을 수 있다.</p>
<h1 id="1-객체지향-설계의-품질을-결정하는-것은-무엇인가">1. 객체지향 설계의 품질을 결정하는 것은 무엇인가?</h1>
<p>객체지향 설계의 전체적인 품질을 결정하는 것은 개별 객체의 품질이 아니라 <strong>여러 객체들이 모여 이루어내는 협력의 품질</strong>이다. 훌륭한 객체지향 설계자는 객체들 간의 요청과 응답 속에서 창발하는 협력에 초점을 맞춰 애플리케이션을 설계한다. 협력이 자리를 잡으면 저절로 객체의 행동이 드러나고 뒤이어 적절한 객체의 상태가 결정된다.</p>
<h1 id="2-협력은-무엇으로-구성되는가">2. 협력은 무엇으로 구성되는가?</h1>
<p>협력은 다수의 요청과 응답으로 구성되며, 전체적으로 협력은 다수의 연쇄적인 요청과 응답의 흐름으로 구성된다. 협력은 어떤 객체의 요청으로 시작된다. 어떤 객체가 특정 요청을 받아들이고 응답하는 이유는 그 요청에 대해 적절한 방식으로 응답하는데 필요한 지식과 행동을 가지고 있기 때문이다. 그리고 <strong>요청과 응답은 협력에 참여하는 객체가 수행할 책임을 정의한다.</strong></p>
<h1 id="3-책임과-메시지의-차이는-무엇인가">3. 책임과 메시지의 차이는 무엇인가?</h1>
<p>책임은 어떤 객체가 다른 객체의 존재 여부와 상관없이 외부에 제공할 수 있는 행위를 나타낸다. 책임은 하는 것과 아는 것으로 파악할 수 있다. 예를 들어 앨리스 이야기에서 모자 장수는 스스로 증인석에 입장해야 하는 책임(하는 것)과 자신이 알고 있는 사실을 증언해야할 책임(자신이 유도할 수 있는 것에 관해 아는 것)을 가진다. 반면 메시지는 송신자와 수신자가 상호 협력하는 문맥을 강조한다. 앨리스 이야기에서 재판 과정에서 왕이 모자 장수에게 증언하라는 요청을 하는 책임을 말한다.</p>
<h1 id="4-역할을-사용하여-얻을-수-있는-장점은-무엇인가">4. 역할을 사용하여 얻을 수 있는 장점은 무엇인가?</h1>
<p>역할은 책임의 집합이다. 역할을 사용하면 재사용 가능하고 유연한 객체지향 설계를 할 수 있다. 앨리스 이야기에서 판사의 역할을 하던 하트 왕이 하트 여왕에게 권한을 위임한다. 이때 판사가 하는 책임을 역할로 추상화하면, 해당 역할을 수행하는 객체는 갈아낄 수 있다. 이때 대체 가능한 객체는 해당 역할의 책임을 메시지로 이해할 수 있어야만 대체 가능하다. 이때 역할과 대체 가능한 객체는 일반화, 특수화 관계를 만족한다. 하트 왕은 판사의 역할 뿐만 아니라 국정을 돌보는 다른 책임도 가지고 있다.</p>
<h1 id="5-책임-주도-설계는-무엇인가">5. 책임 주도 설계는 무엇인가?</h1>
<p>책임-주도 설계는 객체의 역할, 책임, 협력을 고안하기 위한 방법과 절차를 제시한다. 객체의 책임과 상호작용에 집중한다. 책임-주도 설계를 적용한 시스템은 충분히 자율적이면서 우호적으로 협력 가능한 객체로 이루어진 생태계를 구성한다.</p>
<p><strong>객체지향 시스템의 설계 절차</strong></p>
<ol>
<li>시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.</li>
<li>시스템 책임을 더 작은 책임으로 분할한다.</li>
<li>분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.</li>
<li>객체가 책임을 수행하는 중에 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.</li>
<li>해당 객체 또는 역할에게 책임을 할당하여 객체가 협력하게 한다.</li>
</ol>
<h1 id="6-디자인-패턴은-왜-사용해야-하는가">6. 디자인 패턴은 왜 사용해야 하는가?</h1>
<p>디자인 패턴은 책임-주도 설계의 결과를 표현한다. 패턴은 반복적으로 발생하는 문제를 해결할 수 있는 역할, 책임, 협력을 제공하는 설계 방식을 제시한다. 패턴은 해결하려고 하는 문제가 무엇인지 서술하고, 패턴을 사용할 수 있는 상황을 설명한다. 그리고 그 패턴이 특정 상황에서 왜 더 효과적인지에 대한 이유를 설명한다. 특정한 상황에서 설계를 돕기 위해 모방하고 수정할 수 있는 과거의 설계 경험이다. 가장 유명한 패턴 책은 GOF의 디자인 패턴이다.</p>
<h1 id="7-테스트-주도-개발과-객체-지향은-어떤-관련이-있는가">7. 테스트 주도 개발과 객체 지향은 어떤 관련이 있는가?</h1>
<p>테스트 주도 개발은 책임을 수행할 객체 또는 클라이언트가 기대하는 객체의 역할이 메시지를 수신할 때 어떤 결과를 반환하고 그 과정에서 어떤 객체와 협력할 것인지에 대한 기대를 코드의 형태로 작성한다. 테스트 주도 개발이 응집도가 높고 결합도가 낮은 클래스로 구성된 시스템을 개발할 수 있게 하는 최상의 프랙티스이다.</p>
<p>하지만 객체 지향에 대한 경험이 적은 초보자들은 어떤 테스트를 어떤 식으로 작성해야 하는지 결정하는데 큰 어려움을 느낀다. 테스트 주도 개발은 객체지향에 대한 깊이 있는 지식을 요구한다. 테스트를 작성하기 위해 객체의 메서드롤 호출하고 반환값을 검증하는 것은 순간적으로 객체가 수행해야 하는 책임에 관해 생각한 것이다. 역할, 책임, 협력에 집중하고 객체지향의 원칙을 적용하려는 깊이 있는 고민과 노력을 통해서만 테스트 주도 개발의 혜택을 누릴 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[GDSC 코어 세션 - Spring과 OOP]]></title>
            <link>https://velog.io/@mingadinga_1234/GDSC-%EC%BD%94%EC%96%B4-%EC%84%B8%EC%85%98-Spring%EA%B3%BC-OOP</link>
            <guid>https://velog.io/@mingadinga_1234/GDSC-%EC%BD%94%EC%96%B4-%EC%84%B8%EC%85%98-Spring%EA%B3%BC-OOP</guid>
            <pubDate>Fri, 18 Nov 2022 10:12:16 GMT</pubDate>
            <description><![CDATA[<ul>
<li>활동 내용 : GDSC Core Member Session 1</li>
<li>진행 일자 : 2022년 11월 14일 월요일</li>
</ul>
<p>이번주 월요일에 GDSC 코어 멤버 세션으로 Spring과 OOP에 대해서 발표했습니다. 발표 영상을 첨부하고 싶었으나 녹화를 깜빡한 관계로 슬라이드와 대본을 함께 올립니다.</p>
<h2 id="주제-선정-동기">주제 선정 동기</h2>
<p>스프링 입문과 심화 스터디를 진행하면서, 스프링은 객체지향 프레임워크이니 OOP가 무엇인지 알고 계셔야 한다고 언급하며 읽어보면 좋은 링크를 드렸었습니다. 그래도 이왕이면 한번 날을 잡고 OOP 이야기를 하고 싶었고, 저 스스로도 정리가 필요하다고 생각했기 때문에 OOP를 주제로 정했습니다.
<br></p>
<h2 id="목표-설정">목표 설정</h2>
<p>이 발표의 목표는 다음과 같습니다.</p>
<ol>
<li>객체지향이 패러다임이라는 것을 인지하기. 객체지향의 핵심 개념(다형성, 캡슐화 등)이 왜 등장했는지, 객체지향 프로그래밍 언어의 문법이 존재하는지 생각해보도록 유도하기</li>
<li>스프링이 어떻게 객체지향을 적용했는지 알아보기</li>
<li>(본인이) 스프링을 왜 시작했는지, 어떻게 공부했는지 궁금해하시는 분들이 계셔서 나의 경험 공부하기, 일종의 가이드라인 제공하기<br>

</li>
</ol>
<h2 id="내용-구상">내용 구상</h2>
<p>발표 내용은 다음과 같이 구상했습니다.</p>
<ol>
<li>객체지향 패러다임 설명 : 객체는 협력하기 위해 존재하며, 메시지로 협력한다.</li>
<li>스프링에 객체지향이 어떻게 적용됐는지 살펴보기 : DI, IOC, AOP가 어떻게 객체지향을 지키는지</li>
<li>스프링 공부 썰~ 공부하면서 느꼈던 어려움, 더 공부해야 하는 토픽 제공<br>

</li>
</ol>
<h2 id="구체화">구체화</h2>
<p>발표 내용을 구체화할 때 다음 자료를 참고했습니다. 특히 &lt;객.사.오&gt;를 많이 활용했습니다. 또 <a href="https://www.youtube.com/watch?v=Hm0w_9ngDpM&amp;t=406s">제이 님의 aop 설명</a>은 코드를 그대로(...) 가져왔습니다. 좋은 설명 남겨주신 분들께 정말 감사드립니다!</p>
<ul>
<li>객체지향 패러다임 - 조영호 님의 &lt;객체지향의 사실과 오해&gt; 1장, 2장</li>
<li>스프링에 객체지향이 어떻게 적용됐는지 - 유튜브 우테코 영상들</li>
<li>스프링 공부 썰 By Me..</li>
</ul>
<h2 id="반응">반응</h2>
<p>멤버분들이 만족도 폼으로 많은 반응을 주셨습니다. 감사해요💕
멘트를 직접 오픈할 수는 없어서 다음과 같이 요약했습니다.</p>
<ul>
<li>객체 지향의 주요한 개념이 어떤 맥락에서 나왔는지 알 수 있었습니다</li>
<li>단순한 사용법보다 그것이 왜 존재하는지 알 수 있어서 좋았습니다</li>
<li>경험을 들을 수 있어서 좋았습니다. 스터디 진행해주세요 / 웹 공부 커리 알려주세요</li>
</ul>
<p>재밌는게 익명이었는데도 말투가 지문인 분들이 있어서 넘 웃겼습니다 ㅋㅋㅋㅋ
<br></p>
<h2 id="슬라이드와-발표-대본">슬라이드와 발표 대본</h2>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/e4bcefb0-759e-410d-b4f2-a1265a9fd77c/image.png" alt="">안녕하세요, 스프링과 OOP라는 주제로 발표할 코어 멤버 민휘입니다. 스프링 스터디를 운영하면서 객체지향에 대해 여러 번 언급을 했는데, 이번 기회에 설명을 해보겠습니다. 저기 부제 스프링 공부의 어려움을 적어놓은 게 보이시나요? 객체지향 설명도 할거지만 저의 스프링 공부 썰도 같이 풀어볼 예정입니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/8e8d82ab-9f46-4040-bafd-6d3efe2ddd7d/image.png" alt="">이번 발표에서는 이런 얘기를 할겁니다. 객체 지향의 핵심을 짚어볼거구요, 스프링에서 객체 지향이 어떻게 사용되었는지 살펴볼거구요, 웹 개발에 입문하시는 분들을 위해 어떤 공부를 해야하는지도 함께 얘기해보겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/079cb8e5-95c3-40a1-bba7-211451751da6/image.png" alt="">여러분. 요즘에 스프링 인기가 상당합니다. 스프링 공부하는 분들 엄청 늘었어요. 제가 처음에 스프링에 관심을 가지게 된 계기는 소위 네카라쿠배라고 하는 IT 대기업에서 스프링 개발자를 적극적으로 뽑는다는 소식을 듣고 이거 해볼까 관심을 가졌습니다. 실제로 스프링을 사용하는 기업을 보면 규모가 엄청 큰 프로젝트를 개발하는 IT 대기업, 혹은 규모가 점점 커져서 스프링으로 전환하려는 스타트업 기업들이 있습니다. 그런데요, 사실 우리가 단순한 서버 API를 개발할 것이라면 굳이 스프링을 사용할 이유가 없어요. 왜냐하면 동적 언어, js나 파이썬을 사용하는 프레임워크를 써보면 스프링보다 훨씬 효율적이고 빠르게 개발할 수 있습니다. 근데 왜 규모가 커질수록 스프링을 도입하려고 하는걸까요?</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/7f587ba5-2edc-4d1b-991a-833fc245ca08/image.png" alt="">그 이유는 오늘의 주제이기도 한 OOP와 관련이 있습니다. 스프링은요 개발자가 OOP를 지키면서 개발할 수 밖에 없도록 강제를 합니다. 이미 스프링이 웹 개발에 필요한 공통적인 기능들을 다 추상화해놓고 서비스 로직만 개발자가 작성하도록 인터페이스를 제공해요. 우리가 OOP를 지켰을 때 얻을 수 있는 장점은 서비스 로직에 집중할 수 있다는 것입니다. 요구사항 변경에 유연하게 대처를 할 수 있게 되구요. 이러한 장점들이 프로젝트 규모가 커질수록 엄청난 힘을 발휘합니다. 개발자가 로직에만 집중할 수 있게 되니까 성능과 안정성에 신경을 쓸 수 있고요, 복잡도가 증가하는 코드를 효율적으로 관리할 수 있습니다. 결국에는 코드를 깨끗하게 유지하는데 도움이 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/15f2e70f-3b7f-4dc3-a591-06f47323e6e1/image.png" alt="">제가 한번 오프라인이니까 질문을 드리고 싶은데요. 여러분은 객체 지향하면 어떤게 떠오르시나요. 막 던져주세요. (자바, 상속, 김영한(!!!!) 등의 답변이 나왔습니다)</p>
<p>좋습니다. 주로 많은 분들이 떠올리시는 것들이 이런 객체 지향의 핵심 개념. 그런데 여러분. 과연 이런 것들이 객체 지향을 대표할 수 있다고 생각하시나요? 다들 뭔가 조금씩 모자라지 않나요? 맞습니다. 그래서 저와 함께 객체지향이라는 패러다임을 한번 살펴보도록 하겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/685ecae9-bd3d-4c62-83ab-22f14ab63199/image.png" alt="">조영호 님의 객체지향의 사실과 오해 라는 책에서 발췌한 문장을 읽어볼게요. ‘객체 지향 패러다임은 인간이 인지할 수 있는 다양한 객체들이 모여 현실 세계를 이루는 것처럼 <strong>소프트웨어의 세계 역시 인간이 인지할 수 있는 다양한 소프트웨어 객체들이 모여 이뤄져 있다는 믿음에서 출발</strong>한다.’ 객체 지향이 현실 세계의 시뮬레이션을 하기 위해 탄생했다는 설명은 익숙하실 것 같아요. 정말일까요? 정말 소프트웨어 객체가 현실 객체의 모방일까요? 제가 바로 다음 문장을 읽어드릴게요.</p>
<p>‘그러나 현실 세계와 소프트웨어 세계 사이의 유사성은 여기까지일 뿐이다. <strong>객체지향 패러다임의 목적은 현실 세계를 모방하는 것이 아니라 현실 세계를 기반으로 새로운 세계를 창조하는 것이다.</strong> 따라서 소프트웨어 세계에서 살아가는 객체는 현실 세계에 존재하는 객체와는 전혀 다른 모습을 보이는 것이 일반적이다.’ 예를 들어 현실 세계의 전등은 사람의 손길 없이는 스스로 불을 밝힐 수 없지만 SW 세계의 전등은 스스로 전원을 키고 끌 수 있습니다. 전등이 켜져있는지 유무를 나타내는 상태 변수를 두고 메소드로 조작할 수 있겠죠. 그리고 메소드를 자신만 사용할 수 있도록 숨겨서 스스로 전원을 켤 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/d94c54e8-de52-424a-91d1-2a4e3fe37187/image.png" alt="">자 그러면 주인공인 객체가 객체 지향 세계에서 어떤 의미를 가지는지 알아볼게요. 현실의 객체는 여러 개가 모이고 협력해서 공동의 목표를 이룹니다. 예를 들어 커피를 주문하는 상황에서, 손님은 커피를 주문하고, 캐셔는 주문을 받아서 주문표를 작성하고, 바리스타는 커피를 만듭니다. 커피 주문이라는 공동의 목표를 위해 여러 객체는 스스로의 책임을 다합니다. 소프트웨어의 객체는요 애플리케이션의 기능을 구현하기 위해 존재합니다. 이 기능은 엄청 크기 때문에 자신의 책임을 다하는 여러 객체들이 서로 상호작용해서 기능을 하게 됩니다. 커피 주문을 소프트웨어로 구현하면 이런 모습의 객체들이 협력하게 될 것입니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/06b3957b-cad4-4527-84df-52e32201f5f0/image.png" alt="">객체는 어떻게 협력하는지 알아보겠습니다.</p>
<p>현실 세계에서는 의사소통을 합니다. 객체가 사람이 아니라면, 버튼을 누르는 등 어떤 이벤트를 발생시켜 상호작용을 합니다. SW 세계에서의 객체는 메시지를 통해 협력에 참여합니다. 어떤 객체는 메시지를 전송해서 다른 객체에게 책임을 수행할 것을 요청합니다. 메시지는 객체가 무엇을 수행할 지 알려주는데요, 메시지를 처리하기 위해  객체 내부에서는 메소드를 사용합니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/18c2ffd6-d7cd-4a29-9378-9f1a24ac35a8/image.png" alt="">객체들이 이렇게 메시지를 통해 협력에 참여하려면 갖춰야하는 조건이 있습니다. 객체는 충분히 협력적이어야 합니다. 다른 객체의 요청을 듣거나 다른 객체에게 도움을 요청할 수 있어야 합니다. 또 객체는 충분히 자율적이어야 합니다. 자신의 행동을 스스로 결정하고 책임진다는 말입니다. 여기서 생각나는 개념이 있지 않으신가요? 바로 캡슐화인데요. 객체가 자율적이기 위해서 스스로의 책임을 메소드로 구현해서 외부에 오픈하고, 이 메소드는 객체 내부에서만 접근할 수 있는 상태를 관리합니다. 캡슐화가 이러한 자율적인 책임이라는 맥락에서 등장을 합니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/5cf1f929-e7d3-467e-acaf-d5227d2370d5/image.png" alt="">앞에서 봤던 자율적인 책임은 굉장히 중요합니다. 왜냐하면 자율적인 책임이 결국은 협력의 품질을 결정하기 때문입니다. 자율적인 책임을 가지는 객체는 존재 이유가 명확해져요. 이 예제에서 붕어빵 장수는 반죽부터 붓든 팥부터 꺼내든 붕어빵만 만들면 돼요. 또 붕어빵 장수가 저여도 되고 여러분도 되고 교수님이 되도 상관 없어요. 붕어빵을 만드는 역할 하나만 하면 됩니다. 손님은 붕어빵 장수가 어떻게 빵을 만드는지는 상관 없고 빵만 받으면 돼요. 객체 입장에서는 자기가 약속된 책임만 완수할 수 있으면 내부에서 이걸 어떻게 구현하는지는 상관이 없어요. 이걸 우리는 다형성이라고 불러요. 주로 상속이나 인터페이스 같은걸 쓰는데, 다형성을 활용하면 협력하는 그림에서 특정 책임을 가진 객체를 얼마든지 갈아낄 수 있어요. 그렇게 되면 협력이 유연해지고 객체를 재활용할 수 있다는 장점이 생깁니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/357533c7-2fb0-40b7-814d-d7d4061386af/image.png" alt="">제가 마지막으로 강조하고 싶은건 객체 지향은 사상이에요. 사고 방식이에요. 이 사고 방식을 프로그래밍에 적용한게 OOP구요. 여기서는  코드를 정리하는 방식으로 사용이 된거에요. 그러니까 너무 문법만 냅다 공부하지 마시고 이 문법이 존재하는 목적에 대해서 한번 고민해보시면 좋겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/4e0ab86e-c8e5-4771-a543-943cfca44bb1/image.png" alt="">그러면 이제 스프링 이야기로 넘어가보겠습니다. 스프링은요 객체 지향 패러다임 위에 세워진 프레임워크에요. 무슨 말이냐면 개발자들이 객체 지향을 지키면서 프로그래밍할 수 있도록 돕는다는 뜻이에요. 스프링을 공부하다보면 크게 두 영역에서 OOP를 발견할 수 있는데요. 하나는 스프링의 핵심 원리나 MVC 패턴 등 스프링 프레임워크 자체에 대한 공부를 할 때고요, 다른 하나는 우리가 애플리케이션 코드를 짤 때 객체 지향 원칙을 지키면서 클린한 코드를 짜는 부분입니다. 이런거는 SOLID 규칙 같은거 보면서 연습해보면 되는거구요.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/0486394c-6863-46c4-94cb-78c2a1a80263/image.png" alt="">스프링의 핵심 원리인 AOP, DI, IOC에 대해서 훑어볼건데요. 설명이 추상적이어도 그냥 스프링에서 이 개념을 적용한 목적이 객체 지향 때문이라는걸 인지해주시면 좋을 것 같아요.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/09df935b-4c4d-46ea-8f47-9e1382d6fe9c/image.png" alt="">스프링을 사용하면 내가 직접 객체를 생성하거나, 객체 사이의 관계, 앞에서 살펴본 메시징을 주고 받는 그런 관계를 코드로 만들지 않아도 됩니다. 이렇게 어노테이션만 붙이면 스프링이 어딘가에서 객체를 꺼내서 주입해줍니다.  이걸 우리는 Dependency Injection이라고 합니다. 그래서 스프링을 쓰면 개발자는 객체의 책임과 관계를 결정할 수 밖에 없어요. 객체지향적인 프로그래밍을 강제하고 있다고 봐도 되겠죠.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/beae3ade-be4f-46ff-9941-c2d138075f40/image.png" alt="">그리고 DI가 가능한 이유는 바로 스프링이 객체를 직접 관리하기 떄문이에요. 빈(객체)을 생성하고, 의존성을 주입하고 생명주기를 관리해주는 역할을 스프링에서 컨테이너가 해주는데요. 여기서 개발자 대신 스프링 프레임워크가 객체의 제어 권한을 가지고 관리한다고 해서 제어의 역전, IOC 컨테이너라고 부릅니다. 그럼 개발자는 객체 관리에 신경 쓸 필요 없이 서비스 로직에 집중할 수 있게 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/640d139d-c0f1-417e-addb-65b530def351/image.png" alt=""><img src="https://velog.velcdn.com/images/mingadinga_1234/post/fdbcf84b-d49e-4edd-9b14-b39a34173c98/image.png" alt=""><img src="https://velog.velcdn.com/images/mingadinga_1234/post/9f3b8160-f2c7-4d8a-90da-26e1d7c9c9d1/image.png" alt="">마지막으로 AOP 보겠습니다. AOP도 객체 지향처럼 프로그래밍 패러다임인데요. 로직의 핵심 관점과 부가적인 관점을 나누고 관점을 기준으로 모듈화하겠다는 의미입니다. 무슨 소린가 싶죠? 우리가 작성한 애플리케이션 로직이 이미지처럼 생긴게 오백개 정도 있다고 가정할게요. 그리고 성능 분석을 위해 모든 서비스에 실행 시간 측정 기능을 추가하는 상황을 가정해보겠습니다. 모든 메소드에 이렇게 기능을 추가하는 게 가능할까요? 나중에 시간 측정 기능이 아니라 사용자 로그를 찍는 기능이 들어오면, 그때도 메인 로직에 하나씩 기능을 추가해야 할까요? 여기서 AOP를 적용하면, 이런 메인 서비스 로직을 제외한 기능은 부가 기능이 됩니다. 그리고 이 기능은 메인 로직과 구분합니다. 부가 로직을 수행하는 기능을 분리해두고 이 로직을 적용할 메인 로직만 지정하면 쉽게 코드를 리팩터링할 수 있어요. 이것도 역시 객체지향과 깊은 연관이 있는데요 SOLID 원칙 중에 객체는 하나의 책임만을 수행한다는 내용이 있어요. 요 원칙을 잘 지키도록 하는 것이 AOP입니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/9d43caf8-9cb6-45e8-ad7b-fef757e033ac/image.png" alt="">
슬슬 저의 스프링 공부 썰을 얘기해보려고 하는데요. 저는 처음에 스프링을 지금 입문 스터디에서 쓰는 교재로 시작했어요. 그때 당시에는 그렇게 어렵다고 느끼지 않았어요. 왜냐하면 정말 사용법 위주로 공부를 했기 때문에, 스프링이 다 추상화해놓은거 착실하게 갖다 쓴 거기 때문에. 스프링이 왜 어렵다는 거야? 너무 편한데? 라는 생각을 했어요. 미친거죠.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/3c2be083-8eca-467f-a20a-3ed0012ead0e/image.png" alt="">스프링 프레임워크가 어떻게 설계됐는지 공부를 하는데 진짜 너무 너무 어려운거에요.(DI, AOP, DispatcherServlet 등) 내가 뭐가 부족해서 지금 이걸 소화 못하는지 궁금했어요. 커뮤니티 들어가서 보니까, 스프링은 지금까지 자바 웹 개발 역사에서 사용된 기술들을 객체 지향적으로 사용할 수 있도록 추상화해놓은 프레임워크다라는 거에요. 그럼 나는 지금까지 스프링이 무엇을 추상화했는지 전혀 모르는 상태에서 껍데기만 보고 있었구나. 그러니까 이렇게 어렵지. 생각을 했고 그때부터 서블릿, 자바 빈, 하이버네이트 이런 기술들을 개념적으로라도 공부를 하려고 했습니다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/b7a4b597-6a53-4751-a74c-77b994941976/image.png" alt="">제가 지금까지 스프링 프레임워크에 대해서 막 얘기를 했지만 사실 여러분 무슨 프레임워크를 사용하는지는 크게 상관이 있진 않습니다. 특히 저희 같은 주니어 준비생들은요. 중요한거는 내가 개발하는 프로그램이 어떤 프로세스를 가지고 실행되는지 알고 있는 거에요.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/3a8b791f-20a3-4d46-b646-cf38f5254f2d/image.png" alt="">백엔드를 한다고 하면, 쨌든 웹에서 동작하니까 네트워크 알아야하고, 데이터 관리해야하니 DB 알아야 하고, 애플리케이션 코드 쓰려면 언어 알아야 되고요. 내가 작성한 코드의 품질을 관리하고 싶으면 테스트 코드 써야하고, 좀더 객체지향적으로 애플리케이션을 관리하고 싶으면 디자인 패턴이나 도메인 알아야 합니다. 또 프레임워크 쓴다고 하면 그것도 공부를 해야할겁니다. 스프링 쓴다고하면 자바 웹개발 기술부터 훑어야겠죠. 공부할게 어마어마하게 많습니다. 하나만 알기에도 벅찬데요. 이래서 개발자는 끝도없이 공부한다고 하나봐요. 겁이 나네요.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/45ccdc3e-46bb-41f2-bc60-169304b82866/image.png" alt="">자 발표 내용을 세 줄로 정리해보겠습니다.</p>
<p>첫째. OOP는 패러다임이다. 둘째. 스프링 공부는 방대하다. 셋째. 그러니 여러분 우리 같이 열심히 공부합시다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/649fc82f-6548-4c8d-9fc9-6c7d392a1bab/image.png" alt="">마지막에 홍보를 좀 하자면. 저도 바빠서 스프링 심화 스터디 참여를 거의 못하고 있어요. 너무 아쉬워서, 입문 스터디 참여하신 분들 대상으로 토비 스프링 방학 때 진행해볼까 생각중이구요. 또 요즘에 이펙티브 자바나 DDD 혹은 디자인 패턴에 관심 많은데 저와 함께 공부하고 싶으신 분들 대환영입니다. 연락 주세요. 네 이상으로 발표 마치겠습니다. 감사합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체는 행동으로 추상화한다]]></title>
            <link>https://velog.io/@mingadinga_1234/%EA%B0%9D%EC%B2%B4%EB%8A%94-%ED%96%89%EB%8F%99%EC%9C%BC%EB%A1%9C-%EC%B6%94%EC%83%81%ED%99%94%ED%95%9C%EB%8B%A4</link>
            <guid>https://velog.io/@mingadinga_1234/%EA%B0%9D%EC%B2%B4%EB%8A%94-%ED%96%89%EB%8F%99%EC%9C%BC%EB%A1%9C-%EC%B6%94%EC%83%81%ED%99%94%ED%95%9C%EB%8B%A4</guid>
            <pubDate>Fri, 18 Nov 2022 05:59:15 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 3장</li>
<li>공부 기간 : 2022년 11월 16일 수요일<br>


</li>
</ul>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>추상화는 현실의 복잡성을 극복하기 위한 인지 수단이다. 객체를 개념에 따라 분류하여 일반화하고 단순화할 수 있다. 소프트웨어에서 개념은 타입이며, 타입을 결정하는 것은 객체의 행동이다. 행동은 다형성, 캡슐화, 상속을 설명한다. 타입은 객체의 동적인 상태 변화를 정적으로 추상화하며, 클래스는 타입을 구현하는 수단이다.
<br></p>
<h1 id="질문">질문</h1>
<ol>
<li>추상화는 무엇이고 그 목적은 무엇인가?</li>
<li>개념에 의한 분류는 추상화를 어떻게 적용하는가?</li>
<li>소프트웨어에서 객체 분류의 기준인 개념은 무엇인가?</li>
<li>타입을 결정하는 것은 무엇인가?</li>
<li>다형적인 객체는 왜 동일한 타입인가?</li>
<li>객체를 행동에 따라 분류하려면 객체는 어떤 모습이어야 하는가?</li>
<li>슈퍼타입과 서브타입을 결정하는 것은 무엇인가?</li>
<li>타입은 객체의 무엇을 추상화하는가?</li>
<li>클래스는 무엇을 구현하는가?<br>


</li>
</ol>
<h1 id="1-추상화는-무엇이고-그-목적은-무엇인가">1. 추상화는 무엇이고 그 목적은 무엇인가?</h1>
<p>추상화는 불필요한 부분을 무시함으로써 현실에 존재하는 복잡성을 극복하는 인지 수단이다. 훌륭한 추상화는 목적에 부합하는 것이어야 한다.(객체지향에서는 협력 양상 이해가 목적) 추상화는 일반화와 단순화로 이루어진다. 일반화는 구체적인 사물들 간의 공통점은 취하고 차이점은 버리는 것이고, 단순화는 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거하는 것이다.
<br></p>
<h1 id="2-개념에-의한-분류는-추상화를-어떻게-적용하는가">2. 개념에 의한 분류는 추상화를 어떻게 적용하는가?</h1>
<p>일반화와 단순화를 적용한다. 정원사, 병사, 신하, 왕자와 공주, 왕과 왕비, 하트 잭, 하트 왕, 하트 영왕을 트럼프라는 개념으로 묶은 것은 개별 객체 간의 차이점은 무시하고 공통점을 취한 결과이다. 트럼프에 속하는 객체들의 공통점 중에서도 우리가 중요하다고 생각하는 특징은 몸이 납작하고 두 손과 두 발이 네모난 몸 모서리에 달려 있다는 것 뿐이다. 그 외의 사항은 앨리스의 이야기를 풀어나가는데 어떤 도움도 되지 않기 때문에 세부 사항을 제거했다고 볼 수 있다.
<br></p>
<h1 id="3-소프트웨어에서-객체의-타입을-결정하는-것은-무엇인가">3. 소프트웨어에서 객체의 타입을 결정하는 것은 무엇인가?</h1>
<p>여기서 타입은 개념과 동일하다. 
객체가 어떤 타입에 속하는지 결정하는 것은 객체가 수행하는 행동이다. 어떤 객체들이 동일한 행동을 수행할 수 있다면 그 객체들은 동일한 타입으로 분류될 수 있다. 예를 들어 데이터 타입에서 +, - 등의 산술 연산자를 적용할 수 있는 타입은 숫자형 타입이다.
<br></p>
<h1 id="4-다형적인-객체는-왜-동일한-타입인가">4. 다형적인 객체는 왜 동일한 타입인가?</h1>
<p>같은 타입에 속하는 객체는 행동만 동일하다면 서로 다른 데이터를 가질 수 있다. 여기서 동일한 행동이란 동일한 책임을 의미하며, 동일한 책임이란 동일한 메시지 수신을 의미한다. 따라서 동일한 타입에 속한 객체는 내부의 데이터 표현 방식이 다르더라도 동일한 메시지를 수신하고 이를 처리할 수 있다.</p>
<p>다만 내부의 표현 방식이 다르기 때문에 동일한 메시지를 처리하는 방식은 서로 다를 수밖에 없다. 이것은 다형성에 의미를 부여한다. 다형성이란 동일한 요청에 대해 서로 다른 방식으로 응답할 수 있는 능력을 뜻한다. 동일한 메시지를 서로 다른 방식으로 처리하기 위해서는 객체들은 동일한 메시지를 수신할 수 있어야 하기 때문에 결과적으로 다형적인 객체들은 동일한 타입(또는 타입 계층)에 속한다.
<br></p>
<h1 id="5-객체를-행동에-따라-분류하려면-객체는-어떤-모습이어야-하는가">5. 객체를 행동에 따라 분류하려면 객체는 어떤 모습이어야 하는가?</h1>
<p>객체는 분명한 책임을 가지는 행동만을 외부에 노출해야 한다. 데이터의 내부 표현 방식과 무관하게 행동만이 고려 대상이라는 사실은 외부에 데이터를 감춰야 한다는 것을 의미한다. 따라서 훌륭한 객체 지향 설계는 외부에 행동만을 제공하고 데이터는 행동 뒤로 감춰야 한다. 데이터가 캡슐의 벽을 뚫고 객체의 인터페이스를 오염시키는 순간 객체의 분류 체계는 급격히 위험에 노출되고 결과적으로 유연하지 못한 설계를 낳는다.
<br></p>
<h1 id="6-슈퍼타입과-서브타입을-결정하는-것은-무엇인가">6. 슈퍼타입과 서브타입을 결정하는 것은 무엇인가?</h1>
<p>타입 행위의 호환성이다. 일반적인 타입은 특수한 타입에 비해 더 적은 수의 행동을 가지며 특수한 타입은 일반적인 타입에 비해 더 많은 행동을 가진다. 특수한 타입은 일반적인 타입이 할 수 있는 모든 행동을 동일하게 수행할 수 있어야 한다. </p>
<p>슈퍼타입과 서브타입으로 타입을 나누는 것은 일반화를 적용한 것이다. 트럼프라는 슈퍼 타입은 납작 엎드릴 수 있고 뒤집어질 수 있다. 트럼프 인간이라는 서브 타입은 걸을 수 있다는 특징을 추가적으로 가지고 있다. 앨리스는 트럼프 인간 무리를 보았을 때, 기껏해야 트럼프에 불과하다고 생각했다. 앨리스는 트럼프 인간의 특수한 능력은 제거하고 종이 조각처럼 쉽게 뒤집어지는 트럼프의 특성에 집중하여 상황을 단순하게 만들었다.
 <br> </p>
<h1 id="7-타입은-객체의-무엇을-추상화하는가">7. 타입은 객체의 무엇을 추상화하는가?</h1>
<p>타입은 시간에 따른 객체의 상태 변경이라는 복잡성을 제거하고 철저하게 정적인 관점에서 객체의 모습을 묘사한다. 일반적으로 이런 모델을 타입 모델(정적 모델)이라고 한다. 앨리스의 키는 특정 행동을 할 때 값이 변한다. 이때 중요한 것은 값이 변한다는 가능성이지 그런 행동을 할 때 키가 어떤 값을 가지는지 중요하지 않다.
<br></p>
<h1 id="8-클래스는-무엇을-구현하는가">8. 클래스는 무엇을 구현하는가?</h1>
<p>클래스는 객체지향 프로그래밍 언어에서 정적인 모델을 구현한다. 타입은 객체를 분류하기 위해 사용되는 개념이고, 클래스는 타입을 구현할 수 있는 여러 구현 매커니즘 중 하나이다. 클래스는 타입의 구현 외에도 코드를 재사용하는 용도로도 사용되기 때문에 클래스와 타입을 동일시하는 것은 많은 오해와 혼란을 불러 일으킨다. 
<br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체는 협력하기 위해 존재한다]]></title>
            <link>https://velog.io/@mingadinga_1234/%EA%B0%9D%EC%B2%B4%EB%8A%94-%ED%98%91%EB%A0%A5%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EC%A1%B4%EC%9E%AC%ED%95%9C%EB%8B%A4</link>
            <guid>https://velog.io/@mingadinga_1234/%EA%B0%9D%EC%B2%B4%EB%8A%94-%ED%98%91%EB%A0%A5%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EC%A1%B4%EC%9E%AC%ED%95%9C%EB%8B%A4</guid>
            <pubDate>Fri, 18 Nov 2022 05:58:03 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 2장</li>
<li>공부 기간 : 2022년 11월 15일 화요일<br>

</li>
</ul>
<h1 id="질문">질문</h1>
<ol>
<li>객체는 무엇인가?</li>
<li>객체는 무엇으로 구성되며, 각 구성 요소는 왜 필요한가?</li>
<li>객체는 어떻게 협력에 참여하는가?</li>
<li>객체를 왜 캡슐화하는가?</li>
<li>객체 설계에 있어 중요한 것은 무엇인가?</li>
<li>왜 객체 지향은 현실 세계의 모방이 아닌가?<br>

</li>
</ol>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>객체는 협력하기 위해 존재한다. 자율적인 책임을 가진 객체가 협력에 참여할 수 있는 유일한 방법은 행동이다. 객체지향 설계에서는 어떤 책임과 이를 수행할 행동이 필요한지 정의한 후 상태를 결정해야 한다.
<br></p>
<h1 id="1-객체는-무엇인가">1. 객체는 무엇인가?</h1>
<p>객체란 식별 가능한 개체 또는 사물이다. 객체는 자동차처럼 만질 수 있는 구체적인 사물일 수도 있고, 시간처럼 추상적인 개념일 수도 있다. 예를 들어 앨리스(사람), 음료(사물)
<br></p>
<h1 id="2-객체는-무엇으로-구성되며-각-구성-요소는-왜-필요한가">2. 객체는 무엇으로 구성되며, 각 구성 요소는 왜 필요한가?</h1>
<p>객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가진다. 소프트웨어 안에서 객체는 저장된 상태와 실행 가능한 코드를 통해 구현된다. </p>
<ul>
<li><p><code>상태</code> : 행동의 결과는 객체에게 과거에 어떤 행동이 일어났느냐에 의존한다. 자판기에 충분한 금액을 투입하기 전에는 원하는 음료를 선택할 수 없다. 모든 과거의 이력을 저장하는 대신 상태를 기록해 효율적으로 행동의 결과를 예측할 수 있다. 상태에는 단순 값과 다른 객체를 참조하는 링크가 있다.</p>
</li>
<li><p><code>행동</code> : 행동의 결과는 상태에 영향을 받으며, 객체의 행동은 상태를 변경시킨다. 객체는 자율적인 책임을 가지므로 자신의 상태는 자신만이 직접 변경할 수 있으며 다른 객체와 협력을 참여할 때 다른 객체의 상태 변화를 간접적으로 요청할 수 있다. 이 두 가지 효과를 행동이 담당한다.</p>
</li>
<li><p><code>식별자</code> : 객체의 상태와 같은 단순한 값은 동등성을 비교할 수 있다. 반면 객체는 모든 상태 값이 같더라도 다른 객체이다. (일란성 쌍둥이 처럼) 객체는 동일성 비교를 위한 식별자를 가진다.</p>
<br>

</li>
</ul>
<h1 id="3-객체는-어떻게-협력에-참여하는가">3. 객체는 어떻게 협력에 참여하는가?</h1>
<p>객체의 행동은 객체가 협력에 참여하는 유일한 방법이다. 객체지향 세계에서 모든 객체는 자신의 상태를 스스로 관리하는 자율적인 존재이다. 따라서 다른 객체의 상태 변화를 요청하려면, 메시지를 전송해서 다른 객체의 행동이 스스로 동작하도록 만들어야 한다. 객체의 행동을 유발한 것은 외부로부터 전달된 메시지지만 객체의 상태를 변경할지 여부는 객체 스스로 결정한다. 사실 객체에게 메시지를 전달하는 외부의 객체는 메시지를 수신하는 객체의 상태가 변경된다는 사실조차 알지 못한다. 
<br></p>
<h1 id="4-객체를-왜-캡슐화하는가">4. 객체를 왜 캡슐화하는가?</h1>
<p>상태를 외부에 노출시키지 않고 행동을 경계로 캡슐화하는 것은 결과적으로 객체의 자율성을 높인다. 자율적인 객체는 스스로 판단하고 스스로 결정하므로 객체의 자율성이 높아질 수록 객체의 지능도 높아진다. 협력에 참여하는 객체들의 지능이 높아질수록 협력은 유연하고 간결해진다.
<br></p>
<h1 id="5-객체-설계에-있어-중요한-것은-무엇인가">5. 객체 설계에 있어 중요한 것은 무엇인가?</h1>
<p>협력에 참여하는 훌륭한 객체 시민을 양성하기 위한 가장 중요한 덕목은 상태가 아니라 <code>행동</code>에 초점을 맞추는 것이다. 객체는 다른 객체와 협력하기 위해 존재한다. 객체의 행동은 객체가 협력에 참여하는 유일한 방법이다. 따라서 객체가 적합한지 결정하는 것은 그 객체의 상태가 아니라 행동이다. </p>
<p>객체지향 설계는 애플리케이션에 필요한 협력을 생각하고 협력에 참여하는 데 필요한 행동을 생각한 후 행동을 수행할 객체를 선택하는 방식으로 수행된다. 행동을 결정한 후에야 행동에 필요한 정보가 무엇인지를 고려하게 되며 이 과정에서 필요한 상태가 결정된다. 따라서 행동의 결정하고 그 후에 행동에 적절한 상태를 선택하게 된다. </p>
<p>결국 어떤 책임이 필요한가를 결정하는 과정이 전체 설계를 주도해야 한다. RDD(Responsibility Driven Design)는 협력이라는 문맥 안에서 객체의 행동을 생각하도록 도움으로써 응집도 높고 재사용 가능한 객체를 만들 수 있게 한다.
<br></p>
<h1 id="6-왜-객체-지향은-현실-세계의-모방이-아닌가">6. 왜 객체 지향은 현실 세계의 모방이 아닌가?</h1>
<p>현실 속에서는 수동적인 존재가 소프트웨어 객체로 구현될 때는 능동적으로 변한다. 전화기는 스스로 통화 버튼을 누를 수 없으며 계좌는 스스로 금액을 이체할 수 없다. 현실의 객체보다 더 많은 일을 할 수 있는 소프트웨어 객체의 특징을 의인화라고 한다.</p>
<p>그럼에도 현실 세계의 모방이라는 도시 전설이 생겨난 것은 현실 객체의 의미 일부가 소프트웨어 객체로 전달되기 때문이다. 이러한 은유 과계에 있는 실제 객체의 이름을 소프트웨어 객체의 이름으로 사용하면 표현적 차이를 줄여 소프트웨어의 구조를 쉽게 예측할 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[전통적인 관점의 객체지향]]></title>
            <link>https://velog.io/@mingadinga_1234/%EC%A0%84%ED%86%B5%EC%A0%81%EC%9D%B8-%EA%B4%80%EC%A0%90%EC%9D%98-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</link>
            <guid>https://velog.io/@mingadinga_1234/%EC%A0%84%ED%86%B5%EC%A0%81%EC%9D%B8-%EA%B4%80%EC%A0%90%EC%9D%98-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</guid>
            <pubDate>Fri, 18 Nov 2022 05:56:46 GMT</pubDate>
            <description><![CDATA[<ul>
<li>공부 내용 : 객체지향의 사실과 오해 1장</li>
<li>공부 기간 : 2022년 11월 8일 화요일<br>
# 질문
</li>
</ul>
<ol>
<li>객체 지향이 실세계의 모방이라는 설명은 왜 비현실적인가? 그럼에도 사용하는 이유는 무엇인가?</li>
<li>객체 지향 애플리케이션의 윤곽을 결정하는 것은 무엇인가?</li>
<li>협력에 참여하기 위해 객체는 어떤 조건을 만족해야 하는가?</li>
<li>객체 지향에서 객체는 어떻게 협력하는가?<br>

</li>
</ol>
<h1 id="기억하고-싶은-것">기억하고 싶은 것</h1>
<p>객체지향 애플리케이션의 공동 목표는 애플리케이션 기능이며, 작은 역할을 가진 객체들이 각자의 책임을 다하여 협력해서 목표를 이룬다. 객체는 협력적이어야 하며 동시에 자율적이어야 한다. 객체는 메시지를 통해 다른 객체에게 책임을 수행할 것을 요청한다. 
<br></p>
<h1 id="1-객체-지향이-실세계의-모방이라는-설명은-왜-비현실적인가-그럼에도-사용하는-이유는-무엇인가">1. 객체 지향이 실세계의 모방이라는 설명은 왜 비현실적인가? 그럼에도 사용하는 이유는 무엇인가?</h1>
<p>현실의 객체에 직접적으로 대응되는 소프트웨어 객체의 유사성은 거의 없다. 그럼에도 이 비유는 객체지향 설계의 핵심 사상인 연결완전성을 설명하는데 적합하다. </p>
<ul>
<li>캡슐화, 자율성 : 객체를 스스로 생각하고 스스로 결정하는 현실 세계의 생명체에 비유</li>
<li>메시지, 협력 : 현실 세계의 사람들이 암묵적인 약속과 명시적인 계약을 기반으로 협력하여 목표를 달성하는 과정<br>

</li>
</ul>
<h1 id="2-객체-지향-애플리케이션의-윤곽을-결정하는-것은-무엇인가">2. 객체 지향 애플리케이션의 윤곽을 결정하는 것은 무엇인가?</h1>
<p>역할, 책임, 협력이다. 객체 지향 애플리케이션의 공동의 목표는 기능이다. 애플리케이션의 기능은 더 작은 책임으로 분할되고 책임은 적절한 역할을 수행할 수 있는 객체에 의해 수행된다. 객체는 자신의 책임을 수행하는 도중에 다른 객체에게 도움을 요청하기도 한다. 결론적으로 시스템은 연쇄적인 요청과 응답의 흐름으로 구성된 협력으로 구현된다.
<br></p>
<h1 id="3-협력에-참여하기-위해-객체는-어떤-조건을-만족해야-하는가">3. 협력에 참여하기 위해 객체는 어떤 조건을 만족해야 하는가?</h1>
<p>객체는 충분히 협력적이어야 한다. 객체는 다른 객체의 요청을 수신할 수 있고 다른 객체에게 도움을 요청할 수 있을 정도로 열려있어야 한다. </p>
<p>객체는 충분히 자율적이어야 한다. 외부가 아닌 자신이 스스로 자신의 상태를 결정할 수 있어야 한다. 다른 객체의 요청에 응할지 여부는 객체가 스스로 결정한다. 요청에 응해 책임을 수행할 때도 다른 객체의 명령에 복종하는 것이 아니라 요청이 응답할 뿐이다.
<br></p>
<h1 id="4-객체-지향에서-객체는-어떻게-협력하는가">4. 객체 지향에서 객체는 어떻게 협력하는가?</h1>
<p>객체는 다른 객체와 협력하기 위해 메시지를 전송한다. 메시지의 수신자는 요청에 응할 것인지를 판단하고 자신만의 방법에 따라 메시지를 처리하는데, 이처럼 객체가 수신된 메시지를 처리하는 방법을 메서드라고 부른다. 메시지를 수신한 객체는 실행 시간에 메서드를 선택할 수 있다. 커피 주문에서 바리스타는 커피 머신을 이용해 커피를 제조할 수도 있고, 커피머신을 사용하지 않고 수작업으로 커피를 제조할 수도 있다. 이렇게 외부의 요청을 표현하는 메시지와 요청을 처리하는 구체적인 방법인 메서드를 분리하는 것은 객체의 자율성을 높이는 핵심 메커니즘이다.</p>
<br>]]></description>
        </item>
        <item>
            <title><![CDATA[성공하는 스터디를 만드는 10가지 방법]]></title>
            <link>https://velog.io/@mingadinga_1234/%EC%84%B1%EA%B3%B5%ED%95%98%EB%8A%94-%EC%8A%A4%ED%84%B0%EB%94%94%EB%A5%BC-%EB%A7%8C%EB%93%9C%EB%8A%94-10%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@mingadinga_1234/%EC%84%B1%EA%B3%B5%ED%95%98%EB%8A%94-%EC%8A%A4%ED%84%B0%EB%94%94%EB%A5%BC-%EB%A7%8C%EB%93%9C%EB%8A%94-10%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 16 Nov 2022 06:00:11 GMT</pubDate>
            <description><![CDATA[<p><a href="https://youtu.be/N-aZME9Vwlw"><img src="https://img.youtube.com/vi/N-aZME9Vwlw/0.jpg" alt=""></a></p>
<ul>
<li>연설자 분 블로그 : <a href="https://hannut91.github.io/blogs/dynamodb/install">https://hannut91.github.io/blogs/dynamodb/install</a></li>
<li>스터디 팀 블로그 : <a href="https://codesoom.github.io/wiki/api-design/">https://codesoom.github.io/wiki/api-design/</a>
<br><br></li>
</ul>
<p>인프런 다시보기를 보던 중에 스터디와 관련된 세미나를 보았다. 마침 gdsc 스프링 입문 스터디를 거의 마무리 지은 상태여서 앞으로 다른 스터디를 어떻게 준비 혹은 참여해야할지 고민이 많았는데, 이 영상을 보고 좋은 팁을 얻었다. 핵심은 입력(책, 자료, 강의 영상)에 의존하기 보다 <strong><em>인출(코드, 정리한 글) 등의 아웃풋을 남기는 공부 방식이 효과적</em></strong>이라는 점이다.</p>
<h2 id="내가-적용해보고-싶은-팁">내가 적용해보고 싶은 팁</h2>
<ol>
<li>내용 질문과 핵심 질문 만들기</li>
<li>완전한 문장으로 답하기</li>
<li>스터디 활동 전에 짧은 리뷰를 통해 흐름 잡기</li>
<li>다 같이 스터디의 목표 설정하기</li>
<li>소규모 그룹으로 활동하고, 활동 내용 통합하기</li>
</ol>
<h2 id="🍉-코멘트">🍉 코멘트</h2>
<p>스터디 활동에 대한 기록을 남길 때 질문-답변 형식을 사용하면 더 흐름성 있는 공부를 할 수 있을 것 같다. 다음 스터디는 팀원들이 적극적으로 참여할 수 있도록 공동의 목표를 설정하고 템플릿을 제공하면 효과적인 공부를 할 수 있을 것 같다. 또 질문 답변으로 정리하는 방식은 평소에 그냥 책을 읽고 정리할 때 사용해도 좋을 것 같다. 지금 한창 객체 지향의 사실과 오해를 읽고 있는데, 질문으로 정리해서 블로그에 올려봐야겠다!
<br>
<br></p>
<p>⬇️ 영상을 보고 정리한 팁</p>
<h2 id="공부에-인출output이-필요한-이유">공부에 인출(output)이 필요한 이유</h2>
<p>내가 무엇을 이해하는지, 무엇을 할 수 있는지 피드백을 받을 수 있다.</p>
<h2 id="인출-위주의-스터디-시도">인출 위주의 스터디 시도</h2>
<ol>
<li><p>질문 만들기
배운 개념을 질문으로 다시 표현하기(다소 지엽적). 스터디에 적용하면, 멤버가 질문 하나씩 만들어서 랜덤으로 답변하기</p>
<ol start="2">
<li>핵심 질문에 답하기
무엇, 왜, 어떻게에 집중. 코드도 작성</li>
</ol>
</li>
<li><p>강의식 전달하기
 스터디 리드의 역량, 흐름 파악하면 난이도 줄더라</p>
</li>
<li><p>짧은 리뷰
흐름 파악의 중요성. 10분 정도 흐름에 대해 잡기</p>
<ol start="5">
<li>책 같이 살펴보기
스터디 첫날. 이 책에서 말하는 바가 무엇이고, 이 책을 읽고 나면 무엇을 할 수 있어야하는지 목표 설정 
🍉 : 주로 책의 들어가기나 서론 부분 읽어봐야지.</li>
</ol>
</li>
<li><p>그룹 작게 나누기
 3-4명 활동(질문에 답하기, 답변에 대해 토론하기, 코멘트하기), 모여서 다시 공유 -&gt; 더 많은 인출 시도</p>
</li>
<li><p>과제 
 기술적으로 어려운 책 : 인출을 많이 시도
 경험해보지 않은 기술의 책 : 코드 따라치기, 연습문제 풀기, 확장하기 -&gt; 과정을 에세이로 정리하기</p>
</li>
<li><p>빈칸 채우기 퀴즈
 암기 효과, 뒤로 갈수록 어려워지는 문제 방지</p>
</li>
<li><p>완전한 문장으로 만들기
 인출의 형식은 완전한 문장으로. 질문에 대한 답변, 책 보지 않고. 그럼 내꺼가 된거임</p>
</li>
<li><p>끝나고 같이 서평 작성
시간 안에 내용을 쏟아내고, 정리하기</p>
</li>
</ol>
<h2 id="더-시도해볼-것">더 시도해볼 것</h2>
<ul>
<li>실습 늘리기</li>
<li>빈칸 채우기 + 플래시 카드</li>
<li>리더가 필요 없는 자발적인 스터디</li>
<li>학습하는 방법도 공부(질문 만들기 학습법)</li>
<li>다른 회사 개발팀과 스터디 : 내가 모르는 분야 도움!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[첫 해커톤 후기]]></title>
            <link>https://velog.io/@mingadinga_1234/%EC%B2%AB-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@mingadinga_1234/%EC%B2%AB-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Mon, 29 Aug 2022 06:42:56 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/d7879b70-56a4-4c47-8663-6bcb60eda874/image.png" alt=""></p>
<p>8월 27일부터 28일까지 진행된 교내 해커톤에 참여했다. 제로존 프로젝트를 같이 진행했던 프론트 친구들과 jpa 스터디에서 만난 백엔드 파트 언니와 함께 했다. </p>
<p>결과부터 미리 말하자면, 아쉽게도 배포를 못했다! 서버 배포가 늦어진 탓에 프론트가 데이터를 받아서 뿌려주는 일이 매우 빠듯했고, apk 배포 후의 앱에서는 서버에 네트워크 연결이 안돼서 결국 데모 영상을 못 찍었다. 이틀 간 정말 열심히 개발했는데 막판에 문제가 생겨 제출을 못한게 너무 아쉽지만.. 이렇게 몰입해서 무언가를 해본게 오랜만이어서 그런지 정말 재밌었다. 그리고 젊을 때 아니면 정말 못할 것 같다. 하하하</p>
<h3 id="첫-해커톤에-참여한-나에게-해주고-싶은-말">첫 해커톤에 참여한 나에게 해주고 싶은 말</h3>
<ol>
<li>기획은 제발 작게..!!!!!!</li>
<li>CI 붙여라</li>
<li>테스트 코드 써라</li>
</ol>
<h3 id="개발-과정-주저리">개발 과정 주저리</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/c327673a-2404-49d6-881c-842af1c2c0e8/image.png" alt=""></p>
<p>해커톤은 토요일 아침 9시부터 다음날 일요일 밤 10시까지 진행되었다. 나는 서버를 맡았고, 가장 익숙한 자바/스프링으로 개발했다. 해커톤 하루 전날 회원가입, 로그인, 마이페이지 회원 조회 및 수정 등의 간단한 api가 있는 서버를 만들어서 aws ec2에 배포했고, aws maria db를 연결해 테이블을 만들어두었다. 회원가입 및 로그인은 배포가 완료된 상태로 대회를 시작했다. 이때까지는 별 생각 없었다. </p>
<p>주제가 발표되고 나서, 무난한 주제인 밥약 매칭 앱을 만들기로 했다. 기획으로 당근 마켓을 벤치마킹했기 때문에 우리도 채팅 기능을 넣으려고 했는데, 이틀 안에 다른 기능을 비롯해 채팅까지 구현하기엔 시간이 부족할 것 같아 센드 버드라는 외부 api를 연결해보자는 의견이 있었다. 하지만 구현 방법을 보니 프론트 쪽에서 작업을 해줘야하는게 많았고.. 프론트는 화면 구성만으로도 이미 할게 차고 넘쳤기 때문에 채팅은 빼는 것으로 결론이 나왔다. 이때 시간이 오후 한시였다. 하하</p>
<p>Erd, uml, api 설계를 마쳤다. 시간은 오후 세시. 이땐 기능이 그렇게 어렵지 않아서 빠르게 구현할 수 있을 거라고 생각했다. </p>
<p>언니가 기존 회원 관련 로직을 먼저 수정한 후 테스트했고, 나는 후기 관련 기능과 글 작성 기능을 먼저 만들었다. 후기 관련 기능에서 평점 계산으로 평균 쿼리를 사용해야했는데, jpa로 통계 쿼리를 써보는건 처음이라 좀 헤맸다. 자꾸 npe가 떠서 짜증 났지만, 알고보니 검색 조건에 맞는 로우가 없으면 평균을 낼 수 없어 null을 반환하는 것이었다. 반환 타입을 Optional로 수정하고 로직을 완성했다. 이때가 새벽 4시였고, 백엔드 개발 상황 공유 후 기절하고 말았다. 나는 밤 새는걸 잘 못한다.</p>
<p>다음날 아침, 손에 모기 물린 것을 발견. 너무 너무 간지럽고 손이 왕창 부었다. 으흑흑 모기 독에 알레르기가 있어서 무지 따가웠지만 마감이 다가오니 참고 했다. 나는 글 작성과 밥약 생성을 연결했다. Enum을 받아오는 과정에서 에러가 나서 좀 해맸다. 분명 하라는 대로 고쳤는데 왜 파싱을 못하는거야..! 인텔리제이 자체에서 다시 빌드했더나 잘 됐다. </p>
<p>밥약 신청 및 허락, 거절, 밥약 상태 관리는 언니가 맡았는데 여기도 enum 때문에 엄청 헤맸다. 흑흑 왜 변경을 했는데 감지를 못하니..! 왜인지는 모르겠지만 첫 테스트는 반영되는데 시간이 오래 걸리다가 시간이 좀 지나니 바로 바로 반영됐다. 트랜잭션 때문일까..? 지금도 잘 모르겠다. 잘만 되는데 왜 그땐 안됐을까. </p>
<p>오후 3시가 넘었는데 아직도 서버 개발이 완료되지 않았다. 프론트는 배포를 오매불망 기다리는데.. 으아악 그래서 미완성인 상태로 풀 받아서 ec2에 배포를 했다. 테이블 생성해서 배포 서버에 기능이 동작하도록 만든 후 프론트는 연결을 시작했다. 지금 생각해보면 기능을 다 만든 후에 배포해야지는 어리석은 생각이었다. 아직 마이크로 서비스를 공부해보진 않았지만.. 기능을 작게 쪼개서 바로 배포하는 방식으로 개발했어야 시간을 단축할 수 있다. 이 부분은 아직도 후회하고 있다. 프론트가 너무 시간에 쫓겨 연결을 하는 바람에 배포까지 가지 못했던 것 같다. </p>
<p>그리고 개발 시간이 너무 길어졌던 요인 중 하나는 테스트 때문이었던 것 같다. 우리는 테스트 코드를 잘 짜는데 자신이 없어서, 그냥 포스트맨만으로 api 테스트만 하려고 했다. 처음엔 문제가 없었다. 하지만 기능이 추가되면서, 새로 추가한 기능을 테스트하기 위해 선행해야 하는 테스트가 늘어나면서 시간이 오래 걸리기 시작했다. 테스트 코드 작성의 업보빔을 맞은 것이다... 나중에는 테스트하다가 울렁거렸다. 테스트의 지옥을 맛본 것이다. 언니랑 테스트 코드 열심히 연습하기로 했다. </p>
<p>아무튼 서버 쪽도 계속 개발해서 푸시를 했고 프론트도 미친듯이 서버 연동을 했다. 이때는 정말 모두가 초집중 상태여서 시간이 엄청 빨리 갔던 것 같다. 서버 개발이 완료돼서 안심하고 기획서 작성을 하던 와중에.. 500이 떴다는 프론트의 알림.. 오마이갓.. 포스트맨으로 ec2Server에 연결해서 보니 우리가 만들지 않았던 테이블에 insert 쿼리가 날아가고 있었다. 대체 이 테이블의 정체는 뭐지...? 이 오류를 제출 한 시간 남은 상태에 만나서 거의 멘탈이 붕괴된 채로 엔티티를 살펴보았다. 언니가 작업한 부분에서 연관관계 설정이 논리적으로 맞지 않아 새 테이블이 만들어졌고, fk를 가지고 있어 글이 한개 이상 추가되지 않았다. 그러나 우리는 이미 이틀 간 두시간 잔 상태였고 어디를 어떻게 고쳐야할지 머리가 돌아가지 않았다. 모기 물린 곳이 너무 따갑고 몸이 아팠다😢 일단 글 하나까지는 작성이 되니 이 상태로 데모 영상 찍자고 했으나! apk를 받았더니 서버로 요청이 안감! 10시 마감! 끝~~ 이렇게 됐다 푸항항항 ^3^)))</p>
<h3 id="후기">후기</h3>
<p>결과는 아쉽지만 그래도 정말 재밌었다. 배포 과정 개선의 필요성을 알게 되었고, CI/CD를 더 연습해야한다는 인사이트도 얻었다. 그리고 팀원들과 돈독하게 개발도 했고, 맛있는 것도 먹었다. 새벽 3시에 교정에서 별도 보고 남산 타워도 봤다. 별 보면서 코딩했다 하하. 다시 하겠냐고 물으면 다신 하고 싶지 않지만, 이틀이란 시간을 아주 알차게 쓴 것 같아서 재밌었다. 그리고 2학기에 백엔드 같이 한 언니랑 jpa 기능 개선과 채팅 서버 구현을 토이 프로젝트로 하기로 했다. 건설적인 이벤트였다. 함께 고생한 팀원들에게 감사를 전한다. 후기 끝!</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/ff01312e-d57b-404b-93b8-3fe4a45dbc25/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/f7e9a472-7897-4bea-b5e2-b79082bd523e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Google Solution Challenge Top 50 선정]]></title>
            <link>https://velog.io/@mingadinga_1234/Google-Solution-Challenge-Top-50-%EC%84%A0%EC%A0%95</link>
            <guid>https://velog.io/@mingadinga_1234/Google-Solution-Challenge-Top-50-%EC%84%A0%EC%A0%95</guid>
            <pubDate>Fri, 13 May 2022 03:39:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/2c6d8c22-9c2a-4bfd-abdc-d04ce355ab6a/image.png" alt="">
세상에나......
정말 될거라고는 생각 안했는데 덜컥 붙어버렸다.
너무 좋은데 너무 좋은데!!!! 1차 솔루션 제출할 때 뒷일 생각 안하고 개선 사항들을 마구마구 넣었던 기억이 떠오르면서 매우 불안해지기 시작했다. 5월에 안그래도 벌려놓은 일이 많은데..! (클린코드 스터디, JPA 스터디, 20일에 마감인 공모전 1차 제안서, SQLD 자격증까지) 그래서 SQLD 자격증 시험은 취소했다. 이건 방학 때 해도 되는거니까..</p>
<p>그리고 1차 때 GCP에 프로젝트를 배포하고, 프론트 연동을 클라우드에 올린 서버로 요청이 가도록 했었다. 그런데 내가 JPA를 정말 개떡같이 사용했는지 딱 2주 운영했는데 15만원이 청구되었다. 한달 예상 비용은 35만원이었다. 이런 미친!!!! 게다가 실제 애플리케이션은 배포하지 않았기 때문에 프론트 개발자들이 보내는 요청만 받아서 처리했는데 이 정도 비용이 나온거라면.. 이건 꼭 해결해야만 한다.</p>
<p>1차 결과가 나오고 오늘 오전에 회의를 했다. 금요일 아침 9시에 학교에서^^ 우리가 1차 때 냈던 제안서의 개선 사항을 바탕으로 개선할 사항들과 구현할 기능들을 추리고 우선 순위를 지정했다. 만약 머신러닝 쪽에서 비디오를 자동으로 만들어주는 모델의 화질 문제를 개선할 수 있다면, 사용자가 연습하길 원하는 단어나 문장을 입력하면 단어와 문장 연습 페이지를 자동으로 만들어주는 기능을 넣으려고 한다. 이게 되면 진짜 진짜 대박일 것 같다!! 그리고 데이터를 확장할건데, 청각 장애인 교육 전문가분께 자문을 구해서 추가할 데이터들을 정하려고 한다. 이것도 개발 이외의 분야인데.. 솔직히 좀 부담스럽다. 이것까지 해야겠지 아무래도? 응응</p>
<p>그래도 일단 최선을 다하기로 했다. 가장 시급한 성능 개선을 우선으로 하고, 비디오 모델이 긍정적으로 검토된다면 저 기능을 메인으로 구현한다. 그리고 데이터를 얻기 위해 사방팔방 뛰어다닌다. 그리고 UI가 바뀌면 api 요청사항이 늘어날 수도 있어서 신경 써야 한다. 엄청엄청 바쁜데.. 바빠서 행복해요 ^^ 감사한 줄 알자.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/5e07bbad-b1fe-44c5-a7b2-d4c20eb78dde/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Basic Cache Theory]]></title>
            <link>https://velog.io/@mingadinga_1234/Basic-Cache-Theory</link>
            <guid>https://velog.io/@mingadinga_1234/Basic-Cache-Theory</guid>
            <pubDate>Fri, 06 May 2022 09:36:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 포스팅은 숙명여자대학교 김윤진 교수님의 컴퓨터 구조론 특강을 바탕으로 작성되었습니다. </p>
</blockquote>
<p>이 포스팅에서 다루는 내용</p>
<ul>
<li>캐시는 무엇이고 왜 필요한가?</li>
<li>캐시에는 어떤 데이터가 저장되는가?</li>
<li>캐시는 어떤 연산을 하는가?</li>
</ul>
<p><strong>내용 요약</strong>
캐시는 CPU와 메모리의 속도 차이를 완화하기 위한 중간 버퍼이다. 캐시에는 자주 접근하는 데이터를 메모리에서 복사해서 가져온다. CPU는 캐시에 먼저 접근해 해당 데이터가 있으면 빠른 캐시에서 가져올 수 있고, 느린 메모리에 접근하는 경우를 줄일 수 있기 때문에 속도 측면에서 CPU의 낭비를 줄인다. 캐시는 CPU 사이에 read, write 연산을 한다. 멀티 코어에서는 CPU가 메모리에 직접 접근하는 경우도 있다.</p>
<p><strong>이거 왜 배워야됨?</strong>
캐시의 사용자는 캐시의 구성을 이해하고 있어야 한다. 최근 10nm 미만 Fab의 등장으로 캐시의 구성에 큰 변화가 있는데, 이를 이해하기 위해 앞에서 배운 VLSI, 캐시 크기, 구성, 배치를 알고 있어야 한다. 또한 캐시의 구성이 CPU의 전력 소모량을 결정하기 때문에, 성능 밸런스의 이해하려면 캐시를 공부해야 한다.</p>
<h2 id="캐시는-무엇이고-왜-필요한가">캐시는 무엇이고 왜 필요한가?</h2>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/d725fa94-6120-4682-9501-a7e38c3eda2c/image.png" alt=""></p>
<p>캐시란?</p>
<ul>
<li>캐시는 CPU Core와 Main Memory 사이의 중간 버퍼이다.</li>
<li>캐시는 CPU Core와 같은 칩에 들어있을 수도 있고, 아닐 수도 있는데 요즘에는 대부분 같은 칩에 있다.</li>
<li>Main Memory에는 DRAM이 사용되고, Cache에는 SRAM이 사용된다.</li>
</ul>
<p>왜 CPU는 캐시가 필요한가?
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/1c1b2379-05b4-43c9-b00e-e59e34d61782/image.png" alt=""></p>
<ul>
<li>CPU Core에 들어가는 Clock은 점점 빨라지는데 Memory의 발전은 더뎌서, CPU가 메모리에 접근할 때 Memory의 속도가 느려서 코어의 빠른 Clock이 낭비된다.</li>
<li>이 delay를 메꾸기 위해 중간 버퍼인 캐시를 사용한다.</li>
<li>캐시를 사용하여 CPU가 Main Memory에 접근할 때 대기하는 시간을 줄인다.</li>
</ul>
<p><strong>참고1 : 캐시에 어떤 메모리를 사용하는가?</strong></p>
<ul>
<li>SRAM을 사용한다.</li>
<li>캐시에 사용되는 메모리는 Main Memory로 사용되는 DRAM보다 빨라야 한다.</li>
<li>Speed : SRAM(1-10 Cycle) &lt; DRAM(100-200 Cycle)</li>
<li>Capa : SRAM(24KB-12MB) &lt; DRAM(512MB-64GB)</li>
</ul>
<p><strong>참고2 : 왜 캐시를 사용하면 CPU의 대기 시간이 줄어드는가?</strong></p>
<ul>
<li>캐시 메모리에는 자주 사용되는 데이터의 복사본들이 저장된다. 그래서 CPU에서 자주 사용하는 데이터는 빠른 SRAM에서 가져온다.</li>
<li>느린 Main Memory에 접근해야 하는 경우는 덜 자주 사용되는 데이터를 가져올 때이다.</li>
</ul>
<h2 id="캐시에는-어떤-데이터가-저장되는가">캐시에는 어떤 데이터가 저장되는가?</h2>
<ul>
<li>앞에서 <strong>가장 자주 사용되는 데이터</strong>를 메모리에서 복사해 캐시에 저장한다고 했다. 그렇다면 가장 자주 사용되는 데이터가 무엇인지 어떻게 알 수 있을까?</li>
<li>실제로 어떤 데이터가 자주 사용될지는 실행 전에는 알 수 없다. 그래서 우리는 <strong>인접성 원칙(The principle of locality)</strong>을 사용하여 캐시에 저장될 데이터를 정한다.</li>
</ul>
<h3 id="the-principle-of-locality">The principle of locality</h3>
<p><strong>Temporal Locality</strong></p>
<ul>
<li>프로그램이 어떤 메모리 주소에 접근하면, 나중에 똑같은 메모리 주소에 접근할 가능성이 높다.</li>
<li>프로그램은 순차적으로 실행되기 때문이다.</li>
<li>예를 들어, loop에서 일련의 명령어와 데이터 변수에 다시 접근할 확률은 매우 높다.</li>
</ul>
<p><strong>Spatial Locality</strong></p>
<ul>
<li>프로그램이 어떤 메모리 주소에 접근하면, 그 메모리와 인접한 다른 메모리에 접근할 확률이 높다.</li>
<li>예를 들어, 배열이나 객체(구조체) 등이 있다.</li>
</ul>
<h3 id="캐시에-데이터를-저장하는게-무슨-의미가-있나요">캐시에 데이터를 저장하는게 무슨 의미가 있나요?</h3>
<ul>
<li>Spatial Locality와 Temporal Locality를 기반으로 캐시에 데이터를 저장한다. 처음 데이터를 읽어올 때는 메모리와 캐시에 둘다 데이터를 가져와야 하기 때문에 오버헤드가 발생한다. 하지만 나중에 접근하는 데이터가 캐시에 이미 있다면 느린 메모리까지 접근하지 않아도 되기 때문에 이후에 속도가 매우 빨라진다.</li>
<li>Gambling : 캐시에 읽어온 데이터는 나중에 사용되지 않을 수도 있다. 다만 우리는 캐시에서 데이터를 읽어올 때의 속도 이점을 생각하여 데이터를 캐시에 옮겨놓는 것이다. 다행히도 인접성 원칙을 따르기 때문에 나중에 데이터가 다시 읽힐 확률은 아주 높다.<ul>
<li>실제로 캐시 성능을 평가할 때 따지는 hit rate는 대부분 95%를 넘는다. 즉 대부분의 메모리 접근은 캐시에 의해 이루어지는 것을 알 수 있다.</li>
</ul>
</li>
</ul>
<h2 id="캐시는-어떤-연산을-하는가">캐시는 어떤 연산을 하는가?</h2>
<ul>
<li>basic : hit, miss</li>
<li>read : read hit, read miss</li>
<li>write : write hit(write back, write through), write miss(write allocate, no write allocate)</li>
<li>cache memory space allocation</li>
</ul>
<h3 id="cache-hit">Cache Hit</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/7898be47-e855-4bc2-aea3-45fc6826e94f/image.png" alt=""></p>
<ul>
<li>CPU가 요청하는 데이터가 캐시 블록에서 발견되는 경우</li>
<li>데이터는 이미 Locality 원칙을 기반으로 캐시에 옮겨진 상태이다</li>
</ul>
<h3 id="cache-miss">Cache Miss</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/8daa6c6d-b09c-4cbe-9649-cb619634c7b0/image.png" alt=""></p>
<ul>
<li>CPU가 캐시에 데이터를 요청했는데 캐시가 그 데이터를 가지고 있지 않은 경우</li>
<li>이럴 때는 메모리에 접근해서 데이터를 복사해 캐시에 넣는 작업이 필요하다.</li>
</ul>
<p>우리가 해야하는 작업</p>
<ol>
<li>CPU Core를 멈춘다</li>
<li>메인 메모리에 데이터를 요청한다</li>
<li>데이터를 복사해서 캐시에 넣는다</li>
<li>다시 캐시에 데이터를 요청한다(cache hit)</li>
</ol>
<h4 id="cache의-성능-평가-척도">Cache의 성능 평가 척도</h4>
<ul>
<li>Hit Rate (높을수록 좋아)<ul>
<li>캐시 메모리에 의해 관리되는 메모리 접근 비율<ul>
<li>대개 95%가 넘는다. 대부분의 데이터 접근은 캐시에 의해 이루어지기 때문에 데이터 접근할 때 속도가 매우 빨라진다.</li>
</ul>
</li>
</ul>
</li>
<li>Miss Rate (낮을수록 좋아)<ul>
<li>메인 메모리에 접근하는 메모리 접근 비율</li>
<li>1-Hit Rate</li>
<li>Cache Miss가 발생한 경우</li>
<li>멀티 코어 상황에서 Data Consistency를 위해 메모리에 직접 접근하는 경우</li>
</ul>
</li>
</ul>
<p>이제 캐시의 읽기, 쓰기 연산에서의 Hit과 Miss도 알아보자.</p>
<h3 id="read-hit">Read Hit</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/8568c0af-f734-44fd-bbd0-7810a3bc0c42/image.png" alt=""></p>
<ul>
<li>CPU Core에서 Cache에 데이터 요청을 했고 그 데이터가 캐시에 존재한다. 그 데이터를 읽어 CPU Core에 전달한다.</li>
<li>이때 CPU Core와 캐시는 보통 같은 칩 안에 들어있다. 칩 밖보다 빠른 Clock이 들어가며 CPU Core와 캐시는 클락의 속도가 다를 수도 있다.</li>
</ul>
<h3 id="read-miss">Read Miss</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/566157b8-7c0b-498e-b5bb-21b1f0e3d6a6/image.png" alt=""></p>
<ul>
<li>CPU Core에서 Cache에 데이터 요청을 했고 그 데이터가 캐시에 존재하지 않는다.</li>
</ul>
<ol>
<li>CPU Core를 중지한다.</li>
<li>Core에서 Memory에 접근하여 데이터를 요청한다.</li>
<li>Memory에서 데이터를 읽어 캐시에 데이터를 전달하고 저장한다.</li>
<li>캐시에서 Core에 데이터를 전달한다.</li>
</ol>
<h3 id="write-hit---write-back">Write Hit - write back</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/d2961383-b1b5-4768-b321-3dc69d163744/image.png" alt=""></p>
<ul>
<li>CPU Core가 캐시의 데이터를 수정한다.</li>
<li>캐시 데이터는 메인 메모리 데이터의 복사본이기 때문에 수정된 데이터가 메인 메모리에도 반영되어야 한다.</li>
<li>이때 메모리에 반영하는 타이밍은 miss가 발생하여 캐시의 수정된 데이터가 새로운 데이터로 교체될 때이다. 느린 메모리에 접근하는 횟수를 한번으로 줄여 속도의 이점을 가져갈 수 있다.</li>
<li>다만 이 방식은 멀티 코어에서 Data Consistency 문제를 일으킨다. 코어 하나당 캐시가 하나씩 있으며, 메모리를 공유하는 상황에서, 어떤 캐시에서 데이터가 수정되어도 메모리에는 바로 반영이 되지 않는다. 이때 다른 코어의 캐시가 수정이 반영되지 않은 데이터로 연산을 하면 데이터 무결성이 깨진다. 그래서 캐시와 메모리 둘다 업데이트하는 Write Through 연산이 있다.</li>
</ul>
<h3 id="write-hit---write-through">Write Hit - write through</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/0eecc1a9-266d-46be-b933-7501dc96feae/image.png" alt=""></p>
<ul>
<li>캐시와 메모리 둘다 수정된 데이터를 반영한다.</li>
<li>멀티 코어 환경에서 데이터 무결성 문제가 발생하지 않음!</li>
<li>물론 CPU가 캐시와 메모리에 둘다 요청하기 때문에 오버헤드는 발생한다.</li>
</ul>
<h3 id="write-miss---write-allocate">Write Miss - Write allocate</h3>
<ul>
<li>CPU Core가 Cache에 데이터를 쓰려고 요청했는데, 그 요청한 주소에 해당하는 데이터 공간이 캐시에 할당되지 않은 상태.</li>
<li>캐시에 새로운 공간을 할당하기 때문에, 다른 데이터가 out되는 것을 감수해야 한다. 만약 새로 읽어오는 데이터가 다시 사용될 것 같지 않다면 캐시에 쓰지 않고 메모리에만 write하는 방법도 있다.</li>
</ul>
<ol>
<li>CPU Core를 멈춘다</li>
<li>Cache가 메모리에서 데이터를 read</li>
<li>읽어온 데이터를 Cache에 write</li>
</ol>
<h3 id="write-miss---no-write-allocate">Write Miss - No Write allocate</h3>
<ul>
<li>CPU Core가 Cache에 데이터를 쓰려고 요청했는데, 그 요청한 주소에 해당하는 데이터 공간이 캐시에 할당되지 않은 상태</li>
<li>새로운 데이터가 다시 사용될 것 같지 않다면 캐시에 공간을 할당하지 않고 바로 메모리에 데이터를 쓴다.</li>
<li>캐시에 공간을 할당하면 다른 데이터가 나가야 하는데, 새로운 데이터를 저장할 가치가 없어보이면 메모리에만 바로 쓰는 것이 낫다.</li>
</ul>
<h3 id="cache-memory-space-allocation">Cache memory space allocation</h3>
<p>Miss가 발생하는 경우, 메모리에서 데이터를 읽어와 캐시에 공간을 할당하는 경우를 말한다.
메모리에 접근해야 하므로 응답 시간은 길어진다.</p>
<ul>
<li>Write Allocate Miss</li>
<li>Read Miss</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Memory Classification]]></title>
            <link>https://velog.io/@mingadinga_1234/Memory-Classification</link>
            <guid>https://velog.io/@mingadinga_1234/Memory-Classification</guid>
            <pubDate>Fri, 06 May 2022 07:50:51 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 포스팅은 숙명여자대학교 김윤진 교수님의 컴퓨터 구조론 특강을 바탕으로 작성되었습니다. </p>
</blockquote>
<p>이 포스팅에서 다루는 내용</p>
<ul>
<li>CSE 입장에서 필요한 메모리 분류 체계</li>
<li>컴퓨터 시스템에서 메모리와 CPU의 관계</li>
</ul>
<p>우리는 메모리 설계자가 아니다. 메모리 설계의 지식을 빠삭하게 알 필요 없다. 우리는 컴퓨터 사이언스 엔지니어이고, 우리가 메모리를 볼 때 가장 눈 여겨 보아야 할 것은 <strong>CPU와 그 메모리가 어떤 관계를 맺는지</strong>이다. </p>
<h2 id="메모리-분류-기준">메모리 분류 기준</h2>
<ol>
<li>Main/local memory : CPU와 직접 연결되는 메모리 (RAM)<ol>
<li>Byte-level read &amp; write</li>
<li>Fast read &amp; write operation</li>
</ol>
</li>
<li>Secondary memory : CPU와 연결되기에는 느리므로 부가적인 메모리로 사용 (NAND Flash Memory)<ol>
<li>Nonvolidate, 비휘발성</li>
<li>Both readable &amp; writable, 속도 무관</li>
<li>Large capacity, 최소 GB 단위</li>
</ol>
</li>
</ol>
<p>Main, local 메모리는 CPU와 직접 연결되는 메모리로, 메모리 계층 구조의 상위를 차지하는 메모리들이다. 이 메모리를 만족하는 메모리 장치는 Byte-level read &amp; write와 Fast read &amp; write operation가 가능해야 한다. Byte-level read &amp; write가 왜 기준이 되냐면 CPU는 byte를 단위로 세세한 연산을 하기 때문이다. 따라서 CPU와 연결되는 메모리 장치들은 바이트 단위의 입출력이 가능해야 한다. 프로그램에 사용되는 자료형의 최소 크기가 1 byte이다. 1 byte 단위로 access를 못하면, 우리가 작성한 코드를 자료형 단위로 처리할 수 없기 때문에 바이트 단위의 입출력을 꼭 만족해야 한다. 빠른 입출력은 말할 것도 없다. </p>
<p>두 조건을 만족하지 못하는 장치들은 Main, Local 메모리로 사용할 수 없다. 하지만 비휘발성, 동시 입출력, 최소 GB 단위를 저장할 수 있다는 조건을 갖춘다면 Secondary Memory로 사용될 수 있다. 디스크나 보조 기억 장치가 그 예이다. </p>
<p>이러한 분류 기준은 메모리 기술의 발전에 따라 얼마든지 바뀔 수 있다. 이전에 사용되던 메모리인 ROM과 NOR Flash Memory는 메모리 기술의 발전에 적응하지 못하여 도태된 기술들이다. 지금 사용하고 있는 RAM이나 NAND Flash Memory도 더 나은 메모리가 개발된다면 얼마든지 바뀔 수 있다. 메모리를 볼 때 기억할 것은 해당 메모리 장치가 CPU와 어떤 관계를 맺는지이다.</p>
<h2 id="컴퓨터-시스템에서-메모리와-cpu의-관계">컴퓨터 시스템에서 메모리와 CPU의 관계</h2>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/4727c078-0f81-4c0c-896f-c8b1ae6f366b/image.png" alt="">
CPU는 GPP라고 부르기도 한다. CPU를 다루는 곳들이 많다보니 동의어도 많음. General Purpose Processor이라는 뜻인데 왜 General Purpose인지는 CPU를 다룰 때 이야기하도록 한다. (말투 넘 싸가지 없는듯..) </p>
<p>GPP와 직접 메모리 접근을 하는 메모리는 Main Memory와 Local Memory이다. 아까 위에서 살펴본 기준처럼 Byte Level이고 빠른 입출력이 가능하다. 여기에 Random Access라는게 하나 더 붙었는데, Random Access는 임의 접근이라는 뜻으로 순차 접근과 반대되는 개념이다. 그러니까 순차 접근은 처음부터 끝까지 하나씩 검사해서 탐색하는 방법이고, 임의 접근은 해당 데이터가 저장된 주소값을 찍어서 한번에 접근하는 방식이다. Random Access Memory의 Random도 그 뜻이다. RAM의 이름에 대해서는 잠시 후에.. </p>
<p>Secondary Memory는 GP에서 직접 접근하지 않는다. (당연함. 개느림) Secondary Memory도 위의 세 조건을 모두 만족했기 때문에 사용될 수 있는 것이다. 저 조건 마저 만족하지 않는다면 그대로 도태된다. 디스크에서 메인 메모리로 올라오는 부분은 운영체제에서 배우고 있다. 가상 메모리 관리 ... 어렵다 ... </p>
<h4 id="참고--ram-이름의-뜻">참고 : RAM 이름의 뜻</h4>
<p>Random Access Memory다. 이름을 보면 직관적으로 임의 접근이 가능한 메모리구나 라는 생각이 든다. 그럼 다른 메모리들은 임의 접근이 안되나? 아니다 요즘 나오는 메모리들 다 임의 접근 가능하다. RAM이 처음 개발되었을 당시에는 유일하게 임의 접근이 가능했고 유일하게 읽기 쓰기가 둘다 가능했다. 당시에는 임의 접근이 가능한 유일한 메모리라는 뜻에서 RAM이라는 이름이 붙었지만, 오늘날 RAM은 아까 살펴본 기준처럼 <strong>Byte-level 접근이 가능하고 Fast RW가 가능하여 Main, Local memory에 적합한 메모리다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Multi Bit Memory Storage, Register File vs SRAM vs DRAM]]></title>
            <link>https://velog.io/@mingadinga_1234/Multi-Bit-Memory-Storage-Register-File-vs-SRAM-vs-DRAM</link>
            <guid>https://velog.io/@mingadinga_1234/Multi-Bit-Memory-Storage-Register-File-vs-SRAM-vs-DRAM</guid>
            <pubDate>Fri, 06 May 2022 05:20:50 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 포스팅은 숙명여자대학교 김윤진 교수님의 컴퓨터 구조론 특강을 바탕으로 작성되었습니다. </p>
</blockquote>
<p>이 포스팅에서 설명할 내용</p>
<ul>
<li>Basic Multi Bit Memory Storage : Register</li>
<li>Register File</li>
<li>Register File vs SRAM vs DRAM</li>
</ul>
<h2 id="basic-multi-bit-memory-storage--register">Basic Multi Bit Memory Storage : Register</h2>
<p>전 포스팅에서 1bit를 저장하는 최종 컴포넌트 D Flip Flop을 알아보았다. 이제 Multi Bit를 저장할 수 있는 컴포넌트이자, Flip Flop을 여러개 연결하여 만든 기본 멀티 비트 스토리지인 레지스터에 대해 알아보자.</p>
<p><strong>Basic Register</strong>
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/40afede7-614b-4ac9-9d21-b99f30fcfdf9/image.png" alt=""></p>
<p>위 그림은 Flip Flop을 4개 연결하여 4bit를 저장하는 4bit register이다. 이 Flip Flop들은 같은 Clock Signal을 공유한다. 기본 Register는 매 Clock마다 값을 load한다. 오버헤드를 유발할 수 있으므로 특정 Cycle에만 값을 load할 수 있도록 해야 한다.</p>
<p><strong>Register with Parallel Load</strong>
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/7edbfc3f-4e5f-4833-b5a2-0359edb601ac/image.png" alt=""></p>
<p>한 묶음의 데이터를 특정 사이클동안 유지하고 싶을 때 Load input 값을 사용한다. 4bit basic register의 각 Flip Flop 앞에 2x1 MUX를 붙였다. 2x1 MUX로 0 또는 1 값을 선택할 수 있는데, 이 값이 load이다. load가 0이면 값을 유지하고, load가 1이면 새로운 값이 저장되도록 한다.</p>
<h2 id="register-file">Register File</h2>
<p>앞에서 본 Basic Register는 여러 bit로 이루어진 하나의 word를 저장한다. Register File은 여러 word를 저장하는 스토리지이다. 특정 word를 읽거나 쓸 수 있다. MxN Register File은 M개의 word를 가지며, 하나의 word는 n개의 bit를 가진다. 
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/9a80dbd0-ecff-4b42-aade-cddcfee63cf9/image.png" alt=""></p>
<ul>
<li>4x32 register file의 input : data, addr, w_en과 r_en<ul>
<li><strong>값의 read, write가 동시에 가능하다.</strong> 이는 register만의 특징이다.</li>
<li>read는 async이고 write는 sync이다.</li>
</ul>
</li>
<li>Write part<ul>
<li>write data는 와이어를 통해 모든 register와 연결된다.</li>
<li>write decoder를 사용하여 i0, i1중 가능한 조합을 선택한다.</li>
<li>load 값이 1이 되어야만 새로운 값이 저장된다.</li>
<li>Buffer : wire을 통해 write data가 연결되는데, 만약 연결된 component의 수가 늘어난다면 물리 회로의 한계로 값이 약해져 타이밍이 맞지 않는 현상이 발생한다. 버퍼는 신호를 증폭시켜준다.</li>
</ul>
</li>
<li>Read part<ul>
<li>read decorder를 사용하여 읽어올 데이터와 연결된 register를 선택한다.</li>
<li>register로부터 값을 읽을 때, Tri-state buffer이 사용된다.</li>
<li>그 이유는 register 여러개와 하나의 와이어가 연결된 상황에서, 혹시라도 두개 이상의 값이 동시에 들어오면 쇼트가 일어나 회로가 타버리기 때문이다.</li>
<li>Tri 버퍼는 값이 동시에 들어가지 않도록 하는 역할이다. d0가 1이 되면 reg0에 저장된 값이 와이어를 타고 나온다. 그외의 d는 0이 되어, 전기적으로 연결되지 않은 상태인 Z 값이다.</li>
<li>참고로 위 회로는 reg가 4개뿐이기 때문에 버퍼 대신 4x1 MUX로 대체해도 된다. 그런데 회로의 복잡도가 늘어나면 MUX 내부도 복잡해져서 비용이 많이 들고 지연이 생긴다.</li>
</ul>
</li>
</ul>
<p><strong>Register File의 Sync Write와 Async Read</strong>
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/0c71a774-305e-469a-8fe8-b94adf8f851a/image.png" alt=""></p>
<ul>
<li>Write :  W_en이 1이면 Clock의 타이밍에 해당 주소에 값을 쓴다.</li>
<li>Read : R_en이 1이면 바로 해당 주소에 접근해 값을 읽는다. Clock 타이밍과 무관하다.</li>
</ul>
<h2 id="register-file-vs-sram-vs-dram">Register File vs SRAM vs DRAM</h2>
<p>사실 이 내용은 다음 챕터의 메모리 분류 체계를 먼저 살펴본 후, 현재 사용되는 메모리인 SRAM과 DRAM을 Register File과 비교해보는 내용이다. 근데 나는 이미 전체 내용을 다 아는 상황이니까 그냥 메모리 비교를 먼저 다루도록 하겠다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/4b26c7fb-93e7-4835-bf5b-abe2eec63fcf/image.png" alt=""></p>
<p>메모리를 배울 때 이러한 특징 비교는 많이 봤을 것이다. 메모리의 분류의 상위 계층으로 올라갈수록 속도가 빠르고 가격이 비싸고 집적도는 낮다(고전력). 그런데.. 왜 그럴까?! 왜 이런 특징을 가져야 할까? 이 부분은 메모리 계층 구조와 CPU의 구조를 보면 알 수 있는데, 간단하게만 언급하자면 CPU의 연산 부분을 중심으로, 가장 빠른 Register File이 있고 CPU 칩 밖에 Main Memory가 있고, 그 중간 버퍼로 사용되는 Cache가 있다. 데이터의 병목 현상과 메모리 접근 속도를 끌어 올리기 위해 이러한 구조를 취하고 있다. 이러한 메모리 구조에서는 각 메모리가 CPU의 원활한 연산을 위해 갖추어야 하는 특징이 있다. 가장 대표적인 것이 속도와 집적도이다. 연산 부분과 가까이 위치할수록 속도가 빨라야 한다. 같은 칩 안에 위치하면 추가 공정이 필요 없으니 집적도가 높으면 좋다. 각 메모리 계층에서 조건에 맞는 메모리들을 찾다보니 Cache에는 SRAM, Main Memory에는 DRAM이 (현재 메모리 시장에서) 가장 적합하다고 채택된 것이다. </p>
<p>그렇다면 SRAM과 DRAM, Register File은 어떻게 동작하길래 이러한 조건을 갖추는 걸까? 메모리들의 구조를 뜯어보자.</p>
<h3 id="register-file-vs-ram">Register File vs RAM</h3>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/5437a7bf-9979-4421-bbc0-c6ff255f3efb/image.png" alt=""></p>
<p>가장 핵심적인 차이</p>
<ol>
<li>동시 Read &amp; Write : Register File은 가능, RAM은 불가능</li>
<li>1bit storage : Register File은 Flip Flop, RAM은 Trangister</li>
</ol>
<h4 id="register-file-1">Register File</h4>
<ul>
<li><strong>CPU와 가장 근접한 메모리이다</strong>. (CPU 내부에 위치함)</li>
<li>Read와 Write가 동시에 가능하기 때문에 매우 빠르다.<ul>
<li>Read, Write port가 따로 존재하기 때문에 Async Read와 Sync Write가 가능하다.</li>
</ul>
</li>
<li>하지만 게이트를 직접 사용하기 때문에, 메모리 크기가 늘어나면 내부의 복잡도가 증가하고(Decoder, Buffer Logic) 지연 시간이 생긴다. 전력을 더 많이 먹고, 집적이 잘 안되고 크기가 커지기 때문에 메모리 크기를 늘리면 매우 비효율적이다. 주로 <strong>100 words 미만</strong>이다.</li>
<li>따라서 오늘날의 컴퓨터 시스템은 Register만을 사용하여 모든 것을 유지할 수 없고 RAM이나 2차 메모리를 사용한다.</li>
</ul>
<h4 id="ram">RAM</h4>
<ul>
<li><strong>DRAM은 main memory로 사용되어 CPU와 직접 데이터를 주고 받는다. SRAM은 cache로 사용된다.</strong></li>
<li>Read와 Write가 가능하지만 동시에 일어나지 않기 때문에, Register file보다 속도는 느리다. 하지만 CPU와 교류 가능할 정도의 속도는 맞춘다.<ul>
<li>Register File과 달리 Read, Write 포트를 하나만 사용하기 때문에 동시에 RW를 할 수 없다.</li>
</ul>
</li>
<li>Register file보다 속도도 느리고 동시에 RW도 안되지만, 1 bit를 저장하는 소자가 Register file의 FF보다 훨씬 작기 때문에 집적도가 향상되었다. 그래서 대용량의 메모리를 저장할 수 있다. 주로 <strong>512 or 1024개의 word</strong>를 저장한다.
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/5777efd2-6572-419e-9e47-78b723fd8fb2/image.png" alt=""></li>
</ul>
<h3 id="sram-vs-dram">SRAM vs DRAM</h3>
<p><strong>RAM의 구조</strong>
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/50306cbe-be25-4035-8162-d5afb8b98f31/image.png" alt=""></p>
<ul>
<li><strong>W 포트와 R 포트가 따로 존재하지 않아서 Dec Logic이 하나만 존재한다.</strong><ul>
<li>add와 rw 모드를 가짐. rw, en은 Clock에 맞추어 움직이므로 Sync RW을 한다.</li>
<li>rw은 cell을 write할지 read할지 결정한다. 1이면 write, 0이면 read이다.</li>
</ul>
</li>
<li>1 bit를 저장하는 Component는 FF이 아니라, Gate으로만 이루어진 <strong>FF보다 훨씬 집적도가 높고 작은 소자이다.</strong> 그 소자의 종류에 따라 SRAM과 DRAM으로 분류한다.</li>
</ul>
<h4 id="sram">SRAM</h4>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/ec0f96cc-1529-4ccd-b979-0b56559fe722/image.png" alt=""></p>
<ul>
<li>6개의 trangistor를 사용하여 1 bit를 저장한다.</li>
<li>참고로 D FF는 38개의 trangistor를 사용한다.<ul>
<li>2*D Latch(18) + invertor(2) = 38</li>
<li>D Latch : AND 2개, NOR 2개, NOT 1개 = 4*4+2 = 18</li>
</ul>
</li>
<li>Write<ul>
<li>word enable = 0 : data가 invertor를 맴돈다</li>
<li>word enacle = 1 : data가 invertor에 진입하여 loop한다. 값이 여기에 갇히면서 저장됨</li>
</ul>
</li>
<li>Read<ul>
<li>이건 모스의 물리 신호를 알아야 하는데</li>
<li>Don’t care! 더 중요한건 SRAM의 타이밍이다.</li>
</ul>
</li>
</ul>
<h4 id="dram">DRAM</h4>
<p><img src="blob:https://velog.io/288ac0a3-f150-48f1-82d2-a35ac2505b3d" alt="업로드중.."></p>
<ul>
<li>1 transistor로 구성된다. Register File에 비해 1/38배, SRAM에 비해 1/6배 작다.</li>
<li>write<ul>
<li>word enable이 1일 때, capacitor에 전류가 흐른다.</li>
</ul>
</li>
<li>read<ul>
<li>word enable이 0일 때, d 값을 읽는다.</li>
</ul>
</li>
<li>문제<ul>
<li>capacitor이 매번 약해져서 refresh를 해주어야 한다.</li>
<li>dynamic의 뜻 : refresh 필요</li>
</ul>
</li>
</ul>
<h3 id="결론">결론</h3>
<p>어휴 내용이 많다. 결론은 속도 빠른 순으로 RF, SRAM, DRAM이고 높은 집적도 순으로는 DRAM, SRAM, RF이다. 속도 측에서는 RF가 동시에 Read Write가 가능하기 때문에 RAM보다 훨씬 빠르고, 집적도 면에서는 트랜지스터 하나를 사용하는 DRAM이 가장 높다. 이 트랜지스터는 CMOS라고 불리는 반도체 소자인데, 다다음 포스팅에서 살펴볼 것이다. 다음에 살펴볼 내용은 메모리 분류 체계이다. SRAM, DRAM이 현재 컴퓨터 시스템에서 어떤 메모리로 사용되는지 알아본다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1bit memory storage]]></title>
            <link>https://velog.io/@mingadinga_1234/1bit-memory-storage</link>
            <guid>https://velog.io/@mingadinga_1234/1bit-memory-storage</guid>
            <pubDate>Fri, 06 May 2022 01:31:28 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 포스팅은 숙명여자대학교 김윤진 교수님의 컴퓨터 구조론 특강을 바탕으로 작성되었습니다. 교수님께서 주신 인사이트를 제 언어로 정리한 포스팅입니다. 일부 강의 자료의 <a href="https://present5.com/digital-design-chapter-3-sequential-logic-design/">원본</a>을 구글링 하다가 찾아서 그냥 올립니다 ^^</p>
</blockquote>
<p>이 포스팅에서 설명하고자 하는 것</p>
<ul>
<li>1bit를 저장하는 메모리 채택의 변화 (추상적임)</li>
<li>Flip-flop의 동작 원리를 Latch와 Clock을 도입하여 설명하려고 합니다</li>
</ul>
<h3 id="storage">Storage</h3>
<p>먼저, Storage는 왜 필요한가?
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/3fc8524e-a500-43b4-a7ab-74b3aaa1fc4d/image.png" alt=""> 
위 그림의 Combinational Circuit과 Sequential Circuit는 디지털 논리 회로에서 배웠다. 
Combinational Circuit는 input만 알면 output을 확신할 수 있는 반면, Sequential Circuit는 input을 알아도 output을 확신할 수 없다. 이 회로는 과거의 input 값들을 저장하고 있다가 output을 결정할 때 사용한다. 따라서 값을 저장할 수 있는 storage가 반드시 필요하다.</p>
<p><strong>값을 저장하는데 사용하는 예제</strong>
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/e8ebebb5-50ac-41b9-b212-c8027099e0e8/image.png" alt=""></p>
<p>호출 버튼 예제를 사용했다. Call 버튼을 누르면 불이 켜지고, 버튼에서 손을 떼도 여전히 불이 켜져 있다. Cancel 버튼을 누르면 불이 꺼지는 기능을 가진다. </p>
<h3 id="sr-latch">SR Latch</h3>
<p>(사실 이 전에 단순한 로직들을 연결해보는 시도들이 있는데.. 내용을 자세하게 서술할 필요는 없다고 생각했다. 강의 내용을 다시 보니 단순함을 기반으로 하는 복잡성을 다시 발견할 수 있었다.)
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/4817dcf6-bdd6-40b4-a4e2-d503640bfea0/image.png" alt=""></p>
<p>SR Latch의 진리표를 보면 이렇게 된다.</p>
<ul>
<li>Reset이 0→1 되면 Q는 0이 된다 (값을 초기화한다)</li>
<li>Set이 0→1 되면 Q는 1이 된다 (<strong>Set 값을 저장한다</strong>)</li>
</ul>
<h4 id="sr-latch를-사용한-호출-버튼-구현">SR Latch를 사용한 호출 버튼 구현</h4>
<p>이제 호출 버튼의 저장 기능을 SR Latch를 사용하면 구현할 수 있다.</p>
<ul>
<li>Call<ul>
<li>Set에 1을 주면(Call Press) Q가 1이 된다</li>
<li>Set이 0이 되어도(Call Release) Q는 1을 유지한다</li>
</ul>
</li>
<li>Cancel<ul>
<li>Reset에 1을 주면 Q는 0이 된다</li>
</ul>
</li>
</ul>
<h4 id="sr-latch의-문제">SR Latch의 문제</h4>
<p>하지만 SR Latch를 사용했을 때 피할 수 없는 문제가 있다. S와 R이 동시에 1이 되면 Q 값이 010101 바뀌는 것을 무한 반복한다. 이 문제를 Oscillation이라고 한다. 호출 버튼 예제에서는 Call과 Cancel 버튼을 동시에 누르는 경우이다. 무한 반복을 멈출 수 없게 되므로 전원을 차단할 때 까지 버튼은 계속 불이 깜빡깜빡 거릴 것이다. 시스템 설계는 언제나 사용자의 오용도 처리할 수 있어야 하고, 이 시스템이 단순히 호출 버튼이 아니라 미사일 발사 버튼이라면 오우.. 끔찍한 문제가 발생할 것이다. 이 문제는 필히 해결해야 한다.</p>
<p>S와 R이 동시에 1이 되지 않도록 inverter와 and 게이트를 붙였다.
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/f428021e-c400-40f6-81f4-1e655ae691f5/image.png" alt=""></p>
<p>그러나 impulse diagram을 보면 알겠지만 하드웨어의 물리적 delay로 인해 S와 R이 동시에 1이 되는 순간이 발생한다. 찰나의 순간이겠지만.. 버튼의 회로 설계 오류로 미사일이 발사된다면? </p>
<h3 id="clock">Clock</h3>
<p>그래서 이 문제를 해결하기 위해 도입된 것이 Clock이다. 앞에서 로직 게이트를 붙였을 때는 물리적 한계 때문에 문제를 제대로 해결하지 못했다. 하지만 Clock은 또 다른 input이며, 0과 1을 일정 주기로 반복하며 값을 바꾼다. Clock이 1일 때만 input에 의미 있는 값이 실린다. </p>
<p>버튼 예제에 적용해보면 Clock은 SR이 둘다 1인 경우가 아닐 때까지 기다린다. 그러다 Clock이 1인 동안 S1과 R1에 값을 실어 보낸다. </p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/03c4ca4a-a47a-4d72-b660-9c40d94dab7b/image.png" alt=""></p>
<p>Clock은 input 값이 안정화되는 것을 보고 움직이는 것이 아니다. Clock은 일정 주기로 0과 1을 반복하고, Clock이 1인 동안 input 값들이 타이밍을 맞춰서 들어간다. </p>
<p>이때 input값들이 컴포넌트를 통과하는 것도 물리적 회로를 통해서기 때문에 앞에서 살펴봤던 delay가 발생한다. Flip-flop의 input을 바꿀 때, clock edge에 너무 임박해서 바꾸면 delay로 인한 오류가 발생할 수 있다. Setup Time Violation과 Hold Time Violation이 있다. 
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/cd14ea6c-6d62-45d9-9fe5-fdfea83375fd/image.png" alt=""></p>
<ul>
<li>set-up time : D는 edge 이전에 여유 시간을 가지고 바뀌어 안정되어야 한다. 위의 예에서 set-up time이 너무 짧아서, Cm이 떨어졌을 때 Ds에 Dm 값이 바로 반영되지 않았다. Qs가 1이 되는 순간이 잠깐 발생하므로 원하는 값이 반영되지 않는 순간이 발생한다. </li>
<li>hold time : D는 edge 이후에 여유 시간을 가지고 안정되어야 한다. 위의 예에서 Cm이 떨어지는 것보다 Dm이 더 빨리 떨어져서, Ds에 떨어진 값이 반영되었다. 원하지 않는 값이 반영되었다.</li>
<li>Set-up time과 Hold time은 짧을 수록 좋다. 빠를수록 더 빠른 clock이 들어갈 수 있기 때문이다. </li>
</ul>
<h3 id="clock-frequency">Clock Frequency</h3>
<ul>
<li>Clock period : 한번 올라갔다가 내려가는(time interval) 시간</li>
<li>Clock cycle : time interval이 몇번 반복되는지</li>
<li><strong>Clock Frequency : 1/period</strong>
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/278a9a4d-3e29-4ebb-8843-991a1f01f86e/image.png" alt="">
Clock Frequency가 빠를 수록 더 많은 Cycle이 돈다. 클럭 속도가 3.2GHz인 CPU는 초당 32억 번의 사이클을 실행한다. 일반적으로 클럭 속도가 높을수록 CPU 속도가 빠르다. 클럭 속도가 빠르면 사이클이 많이 돌 수 있고, 연산을 할 때 input 값들이 들어가서 나오는 속도가 빠르다는 뜻이다.</li>
</ul>
<h3 id="sr-latch의-한계">SR Latch의 한계</h3>
<p>Clock을 도입하여 SR Latch의 Oscillation 문제를 해결했음에도 SR Latch는 한계를 가진다. 1bit를 저장하는 예시는 매우 단순하기 때문에 SR Latch를 사용해도 큰 문제는 없다. 하지만 스토리지 간에 데이터 이동이나 교환이 일어나는 상황을 생각해보자. 단순히 1bit가 이동하는 경우는 없다. 더 많은 비트들을 커버할 수 있는 스토리지가 필요한데, SR Latch는 복잡한 스토리지 시스템에 사용되지 못한다.</p>
<p>SR Latch는 저장 기능에서 매우 훌륭한 기능을 가진 컴포넌트이다. 영원히 값을 저장할 수 있기 때문이다. 하지만 <strong>SR Latch에 너무 많은 권한을 부여했기 때문에 설계자가 제어하기 어렵다. 따라서 권한을 뺏어 설계자에게 제어권을 넘기려고 한다.</strong></p>
<ol>
<li>2개의 input을 가지면서 timeless storing capa를 가진다.<ul>
<li>Clk이 1이고 R이 0이면, S는 영원히 값을 저장한다.</li>
<li>컴퓨터 시스템에는 수십억개의 Latch가 들어가야 할텐데, input 값이 너무 많아지고 오류 위험도 커진다.</li>
</ul>
</li>
<li>Clk이 1인 시간에 의존적이다.<ul>
<li>그 시간이 더 길면 많은 Latch를 통과하고, 그렇지 않으면 적은 Latch를 통과한다.</li>
<li>목표에 맞춰서 Clock을 다르게 줄 수 없다. 단위가 너무 세분화되어 복잡도를 감당할 수 없다.</li>
</ul>
</li>
</ol>
<h3 id="elaborate-bit-storage">Elaborate Bit Storage</h3>
<p>앞에서 말한 SR Latch의 두 가지 한계점을 보완해 만든 스토리지를 알아본다. 한계점을 어떻게 보완했는지 하나씩 살펴보자.</p>
<ol>
<li>2개의 input을 가지면서 timeless storing capa를 가진다.
 =&gt; input은 1개, Storing Capa는 1 Cycle을 가지는 D Latch
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/0f4aa570-4ed6-469b-867a-52f32818cf3c/image.png" alt=""></li>
</ol>
<ul>
<li>input이 SR 두개에서 D 한개로 바뀌었다.</li>
<li>D 값이 0으로 떨어지면, inverter에 의해 Q가 reset된다.</li>
</ul>
<ol start="2">
<li>Clk이 1인 시간에 의존적이다.
 =&gt; Clk이 1인 동안이 아니라, 0→1 되는 순간(Clock Rising Edge)에 유효한 값을 전달하는 D Flip Flop
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/9b86ae1d-d410-4d48-b523-cf19b7e84c7b/image.png" alt="">
Additional Logic의 정체는 바로 컨버터가 붙은 D Latch이다!
D Flip Flop은 두개의 D Latch가 붙어 만들어진다.</li>
</ol>
<p>Additional Logic이 하는 일</p>
<ul>
<li><strong>Rising edge 순간</strong>의 input value D를 저장했다가</li>
<li>D의 값 변화는 상관 없이 D1에 input을 feed한다.</li>
</ul>
<h3 id="d-flip-flop">D Flip Flop</h3>
<p>그리하여 1bit를 저장할 때 설계자가 제어하기 편하도록 만든 스토리지 컴포넌트인 D Flip Flop이 완성되었다! D FLip Flop을 다시 한번 정리해보자.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/be77cb65-4601-46cc-bb08-3e628b2a549d/image.png" alt=""></p>
<ol>
<li>input이 1개로 줄었다.</li>
<li>Clock의 Rising Edge에만 값을 전달한다.</li>
</ol>
<h3 id="결론">결론</h3>
<p>내용이 상당히 많았는데, 서론에서 이 포스팅은 <strong>Flip-flop의 동작 원리를 Latch와 Clock을 도입하여 설명하기 위함</strong>이라고 했다. 지금부터 요약해서 답해보겠습니다. (요약이긴 했는데 흐름성을 강조하고 싶어서 매우 구구절절임)</p>
<p>SR Latch는 input인 Set이 1이 되면 그 값을 Q로 보내고, 내부적으로는 이 값을 영구적으로 유지합니다. 하지만 SR Latch는 사용자의 오용(동시에 버튼 누름)으로 인해 Oscilation 문제가 발생할 수 있는데, 이 문제를 해결하려면 S와 R이 동시에 1이 되지 않도록 막아야 합니다. 조합 로직을 붙여도 하드웨어의 delay 시간이라는 근본적인 문제 때문에 로직을 추가적으로 붙이는 방식으로는 해결할 수 없죠. 그래서 Clock이라고 하는 제 3의 input을 반강제로 도입합니다. Clock이 허락하는 경우에만 S1과 R1에 의미 있는 값이 실립니다. SR Latch의 내부 input은 Clock의 주기에 맞춰서 움직입니다. Clock이 수많은 컴포넌트 내부의 input에 다 맞춰서 움직여줄 수 없기 때문입니다. 이렇게 SR Latch가 만들어졌습니다. 1 비트를 저장하는데 더할나위 없는 컴포넌트입니다. 그럼에도 SR Latch는 여러개의 비트를 저장하는데 문제가 있습니다.</p>
<p>우선 input이 2개라는 점입니다. 비트 개수만큼의 SR Latch를 사용할 때 저장하고자 하는 비트가 수백개, 수천개로 늘어나면 집적도에서 문제가 발생합니다. 또 클락이 1인 시간에 의존적이게 됩니다. 1인 시간이 길면 더 많은 래치를 통과하죠. 이런 방식으로는 우리가 의도하는 속도로 데이터를 저장하기 어렵습니다. 그래서 SR Latch의 권한을 빼앗아 만든 것이 Flip Flop입니다. input을 SR 2개에서 D 1개로 줄였고, Rising edge of clock을 도입하여 클락이 1이 되는 순간에만 값이 저장되도록 합니다. 결국 Flip-flop은 input을 1개로 줄여 복잡한 비트를 저장하는 컴포넌트에서 집적도의 이점을 가져갔고, Riding edge of clock을 도입하여 데이터를 저장하는 속도를 설계자가 제한할 수 있는 통제권을 부여합니다. </p>
<p>이 포스팅에서는 1bit storage component의 변화와, clock을 알아보았다. Clock은 컴퓨터 시스템 성능 평가에서 워낙 중요한 요소이므로 알아두어야 하는 필수적 요소이고, 1bit storage component의 변화에서 SR Latch -&gt; D Flip flop으로 가는 흐름에서 설계자의 통제를 위해 뛰어난 성능의 컴포넌트의 권한을 뺏고 기능을 제거하여 단순화했다. 나중에 Register File까지 살펴보면 알겠지만 이렇게 단순한 컴포넌트들을 붙여서 복잡한 단계의 컴포넌트로 도약하는 순간이 온다. 이러한 접근 방식은 HW뿐만 아니라 SW를 설계할 때도 적용되므로 앞으로 공부할 때 이런 접근들이 또 있는지 주의해보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[병행 프로세스와 동기화]]></title>
            <link>https://velog.io/@mingadinga_1234/%EB%B3%91%ED%96%89-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EB%8F%99%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@mingadinga_1234/%EB%B3%91%ED%96%89-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EB%8F%99%EA%B8%B0%ED%99%94</guid>
            <pubDate>Wed, 04 May 2022 12:57:19 GMT</pubDate>
            <description><![CDATA[<h2 id="병행-프로세스">병행 프로세스</h2>
<p>병행 프로세스는 다른 프로세스의 상태를 전혀 모르는 상태로 실행한다. 이것을 병행 프로세스의 비동기성이라고 한다. 병행 프로세스가 비동기적으로 실행될 때, 공유 자원에 접근하는 경우 데이터의 무결성이 훼손될 수 있다. 따라서 중간에 싱크가 필요한 경우, 운영체제가 개입하여 적절한 처리가 필요하다.</p>
<p>공유된 자원 접근의 rule</p>
<ul>
<li>한 번에 한 프로세스만이 접근하도록 하고</li>
<li>해당 자원에 대해 의도했던 실행을 완료하도록 보장한다.</li>
</ul>
<p>프로세스가 공유 자원에 접근할 때 처리할 것</p>
<ul>
<li>count라는 변수에 프로세스 A와 프로세스 B가 접근하는 상황에서,</li>
<li>A의 count에 대한 조작 중 CPU가 B로 넘겨지더라도</li>
<li>B의 count에 대한 조작은 허용되어서는 안된다.</li>
</ul>
<h2 id="경쟁-상태">경쟁 상태</h2>
<ul>
<li>프로세스들이 공유 데이터에 대해 서로 접근을 시도하는 상황</li>
<li>이로 인해 발생하는 문제<ul>
<li>상호 배제</li>
<li>교착 상태(Deadlock)</li>
<li>기아(Starvation)</li>
</ul>
</li>
</ul>
<h2 id="상호-배제">상호 배제</h2>
<p>임계 영역</p>
<ul>
<li>Critical Resource에 대해 접근하고 실행하는 프로그램 내의 코드 부분</li>
<li>Critical Resource : 두 개 이상의 프로세스가 동시에 사용할 수 없는 자원</li>
<li>ex) PA : cnt = cnt+1, PB : cnt = cnt-1</li>
</ul>
<p>Mutual Exclusion</p>
<ul>
<li><strong>한 번에 하나의 프로세스만이 임계영역을 실행해야함</strong></li>
<li>임계 영역의 성공적인 실행을 위해서는 맨 먼저 상호배제가 지켜져야함</li>
<li>임계 영역에 있지 않은 프로세스가 다른 프로세스의 임계 영역 진입을 막으면 안됨</li>
<li>비어 있는 임계 영역에 대한 진입은 바로 허용하되, 특정 프로세스의 진입 시도가 계속 무산되어 기아를 겪으면 안됨</li>
</ul>
<h3 id="⭐임계-영역을-진입할-때와-나올-때-꼭-해야하는-일⭐">⭐임계 영역을 진입할 때와 나올 때 꼭 해야하는 일⭐</h3>
<ul>
<li>임계 영역에 들어가고자 하는 프로세스는 먼저 임계 영역 내에 다른 프로세스가 있는지 확인한 후 <strong>있으면 기다린다</strong></li>
<li>없다면 들어가면서 <strong>자신이 나올 때까지 다른 프로세스가 들어오지 못하도록 한다</strong></li>
<li><strong>임계 영역을 벗어날 때</strong>는 자신이 나오는 사실을 알려 다른 프로세스가 들어올 수 있도록 한다</li>
</ul>
<h2 id="상호-배제를-위한-소프트웨어-기법들">상호 배제를 위한 소프트웨어 기법들</h2>
<p>운영체제의 지원 없이 프로세스들 간에 자신의 프로그램에서 임계영역 앞뒤로 적절한 코딩을 하여 상호배제를 해결하는 방식이다. Busy Wait로 인해 CPU를 낭비할 수도 있고, 프로그래머의 실수로 인한 오류도 생길 수 있다.</p>
<h4 id="peterson-solution"><a href="https://www.youtube.com/watch?v=MqnpIwN7dz0">Peterson Solution</a></h4>
<p>** 참고 : Dekker 알고리즘은 Peterson 알고리즘에 의해 간결화되었다.</p>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/4b639409-1e64-4ee3-a9bb-ce0f979a4466/image.png" alt=""></p>
<p>변수의 의미</p>
<ul>
<li>flag[i] : 어느 것이 본인의 차례인지 확인</li>
<li>turn : flag가 둘다 true가 되어 두 프로세스 모두 임계 영역 진입이 불가능한 문제가 발생할 때, turn 값을 지정하여 둘다 true가 되는 경우 trun이 가리키는 프로세스를 실행한다.</li>
</ul>
<p>임계 영역에 들어가는 조건
    - 상대 flag가 false이거나
    - 상대 flag가 true이고 turn이 0이면</p>
<h4 id="lamport의-베이커리-알고리즘"><a href="https://www.youtube.com/watch?v=VDzdb27Gxvo">Lamport의 베이커리 알고리즘</a></h4>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/e20cead7-d0a2-49dd-96d3-a84352aca79d/image.png" alt=""></p>
<p>알고리즘 설명</p>
<ul>
<li><p>n개의 프로세스들이 상호 배제를 지키도록 하는 알고리즘</p>
</li>
<li><p>choosing : 현재 i번째 프로세스가 number 값을 받는 중인지</p>
<ul>
<li>true이면 받는 중, false이면 값을 다 받았다는 신호</li>
</ul>
</li>
<li><p>number : 진입을 원하는 프로세스가 받는 값</p>
<ul>
<li>진입을 원한 적이 없거나(초기화 상태), 진입을 하고 끝난 프로세스는 값이 0</li>
<li>진입 희망을 요청한 순서대로 오름차순 값을 가짐</li>
</ul>
</li>
<li><p>for문 : 상호배제가 필요한 프로세스들을 검사</p>
<ul>
<li><p>첫번째 while문 : number 값을 받고 있는 프로세스가 있다면 기다린다</p>
</li>
<li><p>두번재 while문 : 현재 프로세스 값이 비교대상보다 크다면 기다린다</p>
<p>  → 임계영역에 도달하려면 비교 대상의 프로세스에서 while문이 거짓이어야함</p>
</li>
</ul>
</li>
</ul>
<p>임계 영역 진입 조건</p>
<ul>
<li>자신의 number 값이 가장 작으면</li>
<li>진입이 원하는 프로세스가 기존 값보다 1 큰 값을 받는데, 이는 큐처럼 진입 희망을 요청한 순서대로 처리하기 위함임</li>
</ul>
<h2 id="상호-배제를-위한-하드웨어-기법들">상호 배제를 위한 하드웨어 기법들</h2>
<p>인터럽트 금지 기법과 하드웨어 명령어를 사용한 기법이 있다. 상식적으로 인터럽트를 금지하면 임계 영역의 실행보다 더 시급한 일을 못하게 되고, 인터럽트 금지는 처리기 단위이므로 멀티 코어 시스템에서는 다른 처리기에서 접근할 가능성이 있기 때문에 사용할 수 없다. 주로 하드웨어 명령어인 test and set이나 exchange를 활용한다.</p>
<p>아이디어</p>
<ul>
<li>하드웨어는 특정 메모리 주소에 대한 <strong>접근을 한 번에 하나의 요청</strong>으로 제한한다.</li>
<li>특정 메모리 위치에 대한 읽기와 쓰기 등의 <strong>작업을 한 번의 접근에 처리해주는 명령어</strong>가 있다면</li>
<li>이런 종류의 기계명령어는 원자적(Atomic)으로, 실행 동안 끊기지 않고(Indivisible) 완료된다.</li>
<li>기계 명령어는 실행이 끝날 때까지 중간에 CPU를 뺏기지 않는다는 점을 이용한다.</li>
</ul>
<h4 id="testandset">testandset</h4>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/27e260f7-eec9-4009-bd7e-a155baf8fa09/image.png" alt=""></p>
<p>test and set 명령어는 target을 true로 바꾸고 매개변수로 받았던 bool 값을 반환한다.
이 명령어를 활용한 알고리즘을 분석해보자.</p>
<ul>
<li>lock이 false로 초기화되었다.</li>
<li>i번째 프로세스가 최초로 실행되었다고 가정할 때, while문의 조건은 거짓이 되어 임계 영역에 진입한다. lock은 true 값을 가진다.</li>
<li>임계 영역 실행을 마치면 lock을 false로 돌린다.</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>간단함</li>
<li>다중처리 시스템에도 쉽게 쓸 수 있음</li>
<li>한 프로그램 내에서 서로 다른 변수를 사용하여 여러개의 임계영역을 지원함<ul>
<li>lock이 임계영역에 대응</li>
</ul>
</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>여전히 바쁜 대기를 한다</li>
<li>차례가 정해지지 않기 때문에 어떤 프로세스는 기아를 겪을 수 있다</li>
<li>임계영역 실행 중 높은 우선순위를 가지는 프로세스에게 CPU를 뺏길 경우 <strong>교착 상태</strong>에 빠질 수 있다<ul>
<li>CPU를 뺏은 높은 우선순위의 프로세스는 lock이 true이기 때문에 while문을 계속 맴돈다.</li>
<li>이 while문을 빠져나오려면 lock이 false로 바뀌어야 하는데, 이 문장이 CPU를 뺏긴 낮은 우선순위의 프로세스가 실행해야 한다.</li>
<li>그런데 우선순위가 낮으므로 다시 실행할 수 없어 계속 while문을 맴도는 교착 상태에 빠진다.</li>
</ul>
</li>
<li>교착 상태 해결<ul>
<li>Priority가 낮은 프로세스에게 이 임계 영역에 접근하는 프로세스들의 우선순위 중 가장 높은 값+1을 임시로 주어 임계 영역에 진입힌다.</li>
<li>우선 순위가 높기 때문에 CPU를 뺏기지 않는다.</li>
<li>빠져나올 때 우선순위를 원상복구한다.</li>
</ul>
</li>
</ul>
<h2 id="세마포어">세마포어</h2>
<h4 id="세마포어란">세마포어란?</h4>
<ul>
<li>특수한 명령들로만 접근할 수 있게 허용되는 보호된 변수</li>
<li>프로그래밍 언어와 운영체제 수준에서 병행성을 위해 제공되는 기법이다</li>
</ul>
<h4 id="세마포어의-종류--값의-범위에-따라">세마포어의 종류 : 값의 범위에 따라</h4>
<ul>
<li>Binary Semaphore : 0 또는 1</li>
<li>Counting, Integer Semaphore : 음이 아닌 모든 정수</li>
</ul>
<h4 id="세마포어를-위한-특수한-명령">세마포어를 위한 특수한 명령</h4>
<ul>
<li>세마포어 값을 초기화</li>
</ul>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/b3cd1baf-5042-441f-8837-9897d109b49f/image.png" alt=""></p>
<ul>
<li>P(wait, down)<ul>
<li>아직 사용 가능하다면 1 감소하여 사용 표시</li>
<li>사용 불가능하다면 사용 가능해질 때까지 wait</li>
</ul>
</li>
<li>V(signal, up)<ul>
<li>실행 가능한 프로세스가 있다면 실행 상태로 만듦</li>
<li>없다면 사용하고 있지 않음을 표시</li>
</ul>
</li>
<li>S에 대한 접근은 P, V를 통해서만 허용된다</li>
</ul>
<h4 id="block--wait-vs-busy-waiting">block &amp; wait VS busy waiting</h4>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/496dd19e-d7fa-4ee3-b672-c260c0c87ab2/image.png" alt="">
busy waiting</p>
<ul>
<li>while에서 맴돌기 때문에 CPU 낭비</li>
<li>하지만 다른 프로세스가 금방 실행된다.</li>
</ul>
<p>block and wakeup</p>
<ul>
<li>CPU 낭비 없이 바로 대기로 빠짐</li>
<li>하지만 큐로 들어가기 때문에 실제 실행 속도는 느릴 수 있다.</li>
<li>임계 영역이 매우 짧게 끝나는 경우는 busy waiting이 낫다.<ul>
<li>busy waiting은 짧게 while문을 맴돌고 다른 프로세스가 바로 실행된다.</li>
<li>반면 block and wakeup은 대기에 들어가고 나중에 실행된다.</li>
</ul>
</li>
</ul>
<h4 id="이진-세마포어를-사용한-상호배제-알고리즘">이진 세마포어를 사용한 상호배제 알고리즘</h4>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/95fa3501-a7fd-4c1d-bc84-3c088becc317/image.png" alt=""></p>
<ul>
<li>s가 1로 초기화되었고, i번째 프로세스가 최초 실행된다고 가정하면</li>
<li>P(s)를 거쳐 s는 0이 되고, 임계 영역에 진입한다.<ul>
<li>임계 영역을 실행 도중에 CPU 뺏겨도 s가 0이므로 대기 상태로 들어간다.</li>
</ul>
</li>
<li>V(s)를 거쳐 s는 1이 된다.<ul>
<li>s가 1이 되고 다른 애가 뺏으면 이제 임계 영역을 실행할 수 있다.</li>
</ul>
</li>
</ul>
<h4 id="정수-세마포어를-활용하는-예시--pool-관리">정수 세마포어를 활용하는 예시 : Pool 관리</h4>
<ul>
<li>공유자원을 여러 명이서 사용할 수 있는 경우, Pool로 관리되고 있다고 한다.</li>
<li>예를 들어 프린터기가 10개 있는 실습실에서, 비어있는 프린터가 있다면 누구나 출력 작업을 할 수 있도록 한다.</li>
<li>s를 10으로 초기화하고, 임계 영역을 출력 작업으로 놓는다.</li>
<li>이때 s는 임계영역의 진입이 허용되는 프로세스 수를 나타낸다.<ul>
<li>임계 영역 진입 전, P에 의해 s가 1 감소한다. (사용 표시)</li>
<li>임계 영역 실행 후, V에 의해 s가 1 증가한다. (사용 완료 표시)</li>
<li>s가 0이면 현재 사용 가능한 프린터가 없다는 뜻으로, 대기한다.</li>
</ul>
</li>
</ul>
<h2 id="생산자-소비자-문제">생산자 소비자 문제</h2>
<p>문제 설명</p>
<ul>
<li>생산자 : 데이터를 만들어 버퍼에 저장한다.</li>
<li>소비자 : 버퍼에 있는 데이터를 소비한다.</li>
<li>생산자와 소비자가 버퍼에 동시에 접근할 수 있으므로, 버퍼는 공유 자원이다.</li>
<li>버퍼에 대한 접근, 즉 저장하고 꺼내는 일들은 상호배제 되어야 한다.</li>
<li>버퍼가 꽉 차있을 때는 생산자가 기다려야 하고, 소비할 데이터가 없으면 소비자가 기다려야 한다.</li>
<li>참고로 버퍼는 원형 버퍼이다.</li>
</ul>
<h4 id="알고리즘">알고리즘</h4>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/5195df4d-0f4c-4769-be5b-45e97392fd9b/image.png" alt=""></p>
<ul>
<li>in : 버퍼에 넣을 위치</li>
<li>out : 버퍼에서 꺼낼 위치</li>
</ul>
<h4 id="세마포어-활용">세마포어 활용</h4>
<ul>
<li><p>s : 버퍼 접근 상호배제. 이진 세마포어</p>
</li>
<li><p>e, f : 채우거나 꺼낼 수 있는 공간이 있는지 확인. 정수 세마포어</p>
<ul>
<li>e : 빈 공간의 개수</li>
<li>f :  데이터가 있는 공간의 개수
<img src="https://velog.velcdn.com/images/mingadinga_1234/post/d1a23b7a-159e-4a6e-bfdb-f672bb72e7f7/image.png" alt=""></li>
</ul>
</li>
<li><p>버퍼에 접근하는 임계 영역 앞뒤로 s 세마포어의 P, V가 사용된다.</p>
</li>
<li><p>e와 f도 동작에 맞게 변경한다.</p>
</li>
<li><p>만약 버퍼가 꽉 차서 e가 0이라면, 생산자 코드의 P(e)에서 대기에 걸린다.</p>
</li>
<li><p>버퍼가 비어서 f가 0이라면, 소비자 코드의 P(f)에서 대기에 걸린다.</p>
</li>
<li><p>단점 </p>
<ul>
<li>다음 차례의 임계 영역 진입을 위한 선택 기준이 없어서 기아를 유발함</li>
<li>임계 영역 앞뒤의 세마포어 연산 순서가 중요하다. 만약 소비자에서 P(f)와 P(s)의 순서를 바꾼다면.<ul>
<li>P(s)를 먼저 통과해 s가 1이 된다.</li>
<li>P(f)에서 f가 0이어서 (버퍼가 빈 상태) 대기에 걸린다.</li>
<li>그런데 대기를 풀어줄 생산자 임계 영역 진입 전, s가 1이기 때문에 임계 영역에 진입할 수 없다.</li>
<li>결국 교착 상태에 빠진다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="eventcount와-sequencer">Eventcount와 Sequencer</h2>
<p>Eventcount와 Sequencer</p>
<ul>
<li>Eventcount와 Sequencer는 특별한 명령으로만 접근 가능한 정수형 변수이다.</li>
<li>초기값은 0이고, 세마포어와 달리 값이 감소하지 않는다.</li>
<li>Sequence : 번호표. ticket()에 의해 증가한다.</li>
<li>Eventcounter : 현재 처리 중인 번호. advance()에 의해 증가한다.</li>
</ul>
<p>연산 설명</p>
<ul>
<li>임계영역의 진입을 시도하는 프로세스들에게 순번 표를 부여하여, 기다린 순서대로 처리되도록 하여 <strong>기아를 방지</strong>한다. (vs 세마포어)</li>
<li>ticket(s) : 번호표 뽑기<ul>
<li>s 증가</li>
</ul>
</li>
<li>read(E) : 전광판의 숫자 보기<ul>
<li>E 읽기, 현재 처리 중인 번호 확인</li>
</ul>
</li>
<li>advance(E) : 한 명이 서비스될 때마다 창구 직원에 의해 숫자 증가<ul>
<li>E 증가, 대기 중인 프로세스를 깨운다.</li>
</ul>
</li>
<li>await(E, v) : 그 값이 내 번호표 값이 될 때까지 기다린다<ul>
<li>E &lt; v이면, 프로세스 E를 대기시킨다.</li>
</ul>
</li>
</ul>
<p>변수</p>
<ul>
<li>p, c : 생산자와 소비자를 위한 sequencer 변수</li>
<li>in, out : 생산자와 소비자를 위한 eventcount 변수</li>
<li>array[n] : 버퍼</li>
</ul>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/fb7de252-32a7-4f39-95c4-9b365b1cb45c/image.png" alt="">
생산자</p>
<ul>
<li><p>await(in, pord) : 내 차례인지 확인</p>
<ul>
<li>pord와 in의 관계<ul>
<li>in &lt; pord : pord는 번호표만 받으면 올라가고, in은 생산이 완료되어야 하기 때문에, 작업이 밀리면 pord가 in보다 크다.</li>
<li>in == pord : 자기 차례에 해당되는 순간은 in과 port가 같다.</li>
<li>in &gt; pord : 시스템 오류</li>
</ul>
</li>
<li>in ≥ pord라면 아래로 내려간다.</li>
<li>in &lt; pord라면 대기로 빠진다. 이 대기는 생산자가 생산을 해서 in이 증가하면 해결된다.</li>
</ul>
</li>
<li><p>await(out, pord-n+1) : 버퍼가 full인지 확인</p>
<ul>
<li>버퍼가 full인지 확인하는 방법<ul>
<li>데이터를 저장할 수 있는 공간이 1개 이상이면 full이 아니다.</li>
<li>데이터를 저장할 수 있는 공간은 버퍼의 전체 크기 중 예약된 애들은 빼고, 소비해서 생기는 추가 공간을 더하면 된다. 이 값이 1보다 크면 full이 아니다.</li>
<li>생산된 횟수인 in이 아니라 생산측 번호표를 뺀 이유 : 어차피 도착한 순서대로 실행되기 때문에, 예약이 꽉 차면 더이상 값을 저장할 수 없다.</li>
<li>n - pord + out ≥ 1이면 full이 아닌 것이다.</li>
<li>full이 아닌 조건 : out &lt; n - port + 1</li>
</ul>
</li>
<li>n - pord + out ≥ 1 : full이 아니므로 정상 실행</li>
<li>n - pord + out &lt; 1 : full이므로 대기한다. 이 대기는 소비자가 소비를 해서 out이 증가하면 해결된다.</li>
</ul>
</li>
<li><p>advance(in)</p>
</li>
</ul>
<pre><code>- 생산 완료 후, 현재 생산 번호표 1 증가
- await(in, pord) : 내 차례인지 확인
    - 이 대기 조건을 해결할 수 있다.
- await(in, out-1) : empty인지 확인
    - 이 대기 조건을 해결할 수 있다.</code></pre><p>소비자</p>
<ul>
<li><p>await(out, cord) : 내 차례인지 확인</p>
<ul>
<li>cord와 out의 관계<ul>
<li>out &lt; cord : cord는 번호표만 받으면 올라가고, out은 소비가 완료되어야 하기 때문에, 작업이 밀리면 cord가 out보다 크다.</li>
<li>out == cord : 자기 차례에 해당되는 순간은 out과 cord가 같다.</li>
<li>out &gt; cord : 시스템 오류</li>
</ul>
</li>
<li>out ≥ cord라면 아래로 내려간다.</li>
<li>out &lt; cord라면 대기로 빠진다. 이 대기는 생산자가 생산을 해서 out이 증가하면 해결된다.</li>
</ul>
</li>
<li><p>await(in, cord+1) : 버퍼가 empty인지 확인</p>
<ul>
<li>버퍼가 empty인지 확인하는 방법<ul>
<li>실제 생산된 횟수 - 소비 예약 횟수 &lt; 1이면 empty이다.</li>
<li>empty : in - cord &lt; 1</li>
</ul>
</li>
<li>in - cord &lt; 1 : empty이므로 대기.<ul>
<li>생산을 해서 in이 증가하면 해결된다.</li>
</ul>
</li>
<li>in - cord ≥ 1 : empty가 아니므로 진행한다.</li>
</ul>
</li>
<li><p>advance(out)</p>
<ul>
<li>소비 완료 후, 현재 소비 번호표 1 증가</li>
<li>await(out, cord) : 내 차례인지 확인<ul>
<li>이 대기 조건을 해결할 수 있다.</li>
</ul>
</li>
<li>await(out, pord-n+1) : 버퍼가 full인지 확인<ul>
<li>이 대기 조건을 해결할 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="monitor">Monitor</h2>
<p>모니터</p>
<ul>
<li>공유 데이터들과 임계 영역을 관리하는 소프트웨어 구성체</li>
<li>공유 데이터를 위한 변수, 초기화 루틴, 임계영역을 코딩한 프로시저로 이루어졌다.</li>
<li>변수 : 프로시저를 통해서만 접근 가능</li>
<li>프로세스 : 모니터의 프로시저 호출, 실행하여 모니터 안으로 진입하고 변수에 접근한다.</li>
<li>상호 배제 실현 : 언제나 모니터의 진입을 한 프로세스로 제한한다. 한번에 하나 이상의 프로세스만 모니터 안에 있도록 한다.</li>
</ul>
<p>모니터의 의의</p>
<ul>
<li>실수를 줄일 수 있도록 시스템에서 제공되는 언어 수준의 구조이다.</li>
<li>동기화 관련 부분이 모두 모니터 내부에 표현되어 있으므로, 제대로 작동되면 이것을 사용하는 병행 프로세스들 역시 오류 없이 실행된다.</li>
<li>사용자는 프로그램의 적당한 위치에 모니터 프로시저를 호출만 하면 된다.</li>
</ul>
<p>모니터 운영 방식</p>
<ul>
<li>대기 큐(진입 큐) : 한 프로세스가 들어가 있을 때를 대비해 <strong>호출될 프로시저 개수만큼</strong>의 대기 큐가 있어야 한다.</li>
<li>조건 큐 : 모니터 내의 프로세스가 실행 중에 특정 조건 때문에 대기해야할 경우, 다른 프로세스의 실행을 위해 이 조건 큐에 들어가서 기다린다. <strong>모니터에서 요구되는 조건의 개수</strong>만큼 조건 큐가 존재한다.</li>
<li>신호자 대기 큐 : 조건 대기를 해결해줄 프로세스가 조건을 만족시키면 기다리던 프로세스가 모니터 진입을 하고, 해결 프로세스는 잠시 모니터를 비켜준다. 이 용도로 사용되는 큐이다. 대기하던 프로세스가 실행되고 나가면 다시 모니터에 진입하여 나머지 작업을 실행한다.</li>
<li>조건 변수 : 모니터에서만 선언하고 사용한다.<ul>
<li>cwait(c) : 조건의 대기. 프로세스를 조건 큐에 대기시키고, 다른 프로세스의 모니터 진입을 가능하게 한다.</li>
<li>csignal(c) : 깨우기. 대기되었던 프로세스를 재개시키고, 자신은 신호자 대기 큐로 비켜준다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/e5d7276d-a5d6-4690-86fa-4f01b74fb93a/image.png" alt=""></p>
<ul>
<li>버퍼에 동시 접근하는 프로시저 : append, take</li>
<li>공유 데이터 : buffer</li>
<li>지역 변수 : nextin, nextout, count</li>
<li>조건 변수 : notfull, notempty</li>
</ul>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/dfc74d0a-4db0-4f14-a930-790e594fe711/image.png" alt=""></p>
<ul>
<li><p>생산자는 데이터를 만들고 append(x)를 호출하여 모니터 진입 요청</p>
</li>
<li><p>내부에 이미 프로세스가 있으면, append 대기 큐에서 기다리다.</p>
</li>
<li><p>모니터 내부가 비어있으면, 진입하여 append 프로시저의 full 조건을 검사한다.</p>
</li>
<li><p>만약 full이 맞으면, notfull 조건 큐로 이동한다.</p>
<ul>
<li>notfull 조건을 벗어날 때까지 기다린다. 소비자가 소비를 하여 csignal(notfull)으로 해당 프로세스를 깨우면 그때 다시 모니터에 진입하여 나머지 작업을 실행한다.</li>
</ul>
</li>
<li><p>full이 아니라면, 데이터를 버퍼에 저장하고 신호 큐로 이동한다.</p>
<ul>
<li>이 프로세스는 empty여서 notempty 조건 큐에 대기하고 있는 프로세스의 대기를 해결한다.</li>
<li>데이터를 버퍼에 저장하면 이제 소비자 프로세스는 나머지 작업을 진행할 수 있다. 따라서 데이터 저장이 끝나면 이 프로세스는 신호 큐로 비켜주고, 소비자 프로세스 작업을 진행한다.</li>
<li>만약 notempty 조건 큐가 비어있었다면 마저 명령을 실행한다. 여기서는 깨워준 후 작업이 모두 끝났으므로 모니터를 빠져 나온다.</li>
</ul>
</li>
</ul>
<h2 id="식사하는-철학자-문제">식사하는 철학자 문제</h2>
<p><img src="https://velog.velcdn.com/images/mingadinga_1234/post/ecc3c70b-d0cf-4daf-8a59-747812397d4b/image.png" alt=""></p>
<ul>
<li>5명의 철학자가 앉아있고, 식탁에는 접시 5개와 5개의 포크가 있다.</li>
<li>스파게티를 먹으려면 자신의 오른쪽, 오니쪽 포크 두개가 필요하다.</li>
<li>포크는 공유 자원이며, 철학자들의 정상적인 식사를 보장해야 한다.</li>
</ul>
<p>해결 방법</p>
<ol>
<li>동시 참여 가능한 프로세스 개수를 제한한다.</li>
<li>포크를 집는 순서를 제한한다.<ul>
<li>홀수 철학자는 왼, 오</li>
<li>짝수 철학자는 오, 왼</li>
</ul>
</li>
<li>모니터를 사용한다.<ul>
<li>모니터 안에는 프로세스 하나만 존재할 수 있으므로</li>
<li>왼쪽 포크를 집는 동안 다른 철학자가 오른쪽 포크를 집어갈 가능성을 배제한다.</li>
</ul>
</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>