<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>id_entity.log</title>
        <link>https://velog.io/</link>
        <description>TIL을 기록하기 위한 게시글들 | 노션에 기록해 둔 것들 옮길 예정 !</description>
        <lastBuildDate>Tue, 18 Jun 2024 08:30:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>id_entity.log</title>
            <url>https://velog.velcdn.com/images/id_entity/profile/a7e19af2-3005-469b-af5a-8174425ee363/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. id_entity.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/id_entity" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2024년 팀네이버 테크 신입 공채 후기]]></title>
            <link>https://velog.io/@id_entity/2024%EB%85%84-%ED%8C%80%EB%84%A4%EC%9D%B4%EB%B2%84-%ED%85%8C%ED%81%AC-%EC%8B%A0%EC%9E%85-%EA%B3%B5%EC%B1%84-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@id_entity/2024%EB%85%84-%ED%8C%80%EB%84%A4%EC%9D%B4%EB%B2%84-%ED%85%8C%ED%81%AC-%EC%8B%A0%EC%9E%85-%EA%B3%B5%EC%B1%84-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 18 Jun 2024 08:30:04 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-서론">🤔 서론</h2>
<img src="https://velog.velcdn.com/images/id_entity/post/20b2c68b-0c92-472d-9a96-f50c354631c2/image.png" width="700">


<p>취업 ... 했다 .... 그것도 무려 네이버에 ...!!! 신입으로 !!</p>
<p>예전에는 티스토리 사용할 때 Apple Developer Academy @ POSTECH 1기 후기 작성하고 이런 글을 언제 또 쓸 일이 있을까 싶었는데
생각보다 빠르게 쓰게 되어서 기쁘다 ㅎㅎ</p>
<p>나도 다른 분들 후기 글 보면서 정말 도움을 많이 받았기 때문에
이 글을 보는 다른 분들에게 많은 도움이 되고 싶다는 생각이다</p>
<p>그런고로 말할 수 있는 범위 내에서 최대한 자세히 쓸 예정 !!</p>
<img src="https://velog.velcdn.com/images/id_entity/post/853ce127-4829-4cf3-94e1-07677ced0fe6/image.png" width="400">
자 .. 드가자 ..

<br>

<p>&lt;쓰는 중에 미래에서 온 나&gt;
중간에 글을 다시 보니까 &#39;팩트&#39;라기보단 내가 어떻게 공부했는지에 대한게 큰듯 ?? 합니다 ??</p>
<br>

<hr>
<h2 id="🙋♂️-간단한-나의-스펙">🙋‍♂️ 간단한 나의 스펙</h2>
<blockquote>
<p>전형 준비하면서 느낀 점은 스펙이 큰 영향을 끼치진 않는다는 것이다
그런고로 &#39;이정도 스펙인데 가능할까요?&#39; 이런 질문은 필요가 없을 것 같음 !</p>
</blockquote>
<pre><code>- 대학교
  - 중앙대학교 18학번
  - 주전공 : 전자전기공학부
  - 부전공 : 소프트웨어공학부
  - 학점 : 4.02 / 4.5

- 대외활동
  - Apple Developer Academy @ POSTECH 1기 ( 2022.03 ~ 2022.12 )
  - SOPT 32nd iOS PART ( 2023.03 ~ 2023.08 )
  - NEXTERS 24th iOS PART ( 2024.01 ~ 2024.03 )</code></pre><p>사람들이랑 프로젝트 하는걸 좋아해서 다양한 대외활동을 진행했는데
넥스터즈까지 하고 나니까 더 이상 프로젝트를 위한 대외활동은 그만하자... 라는 마인드이긴 했다</p>
<p>플젝보다는 그냥 내 실력을 갈고 닦는게 중요하다는 마인드 ...
(근데 네이버 떨어지면 부스트캠프는 지원해보려 하긴 했음 ㅋ 부스트캠프는 교육이니까 ~)</p>
<br>

<hr>
<h2 id="📆-간략한-프로세스-일정-설명">📆 간략한 프로세스 일정 설명</h2>
<p><a href="https://recruit.navercorp.com/micro/teamnaver2024/tech">공고 링크</a></p>
<p>전체 전형이 내가 기록해둔걸로는</p>
<pre><code>- 서류 모집 :                3월 5일 ~ 3월 18일
- 코딩테스트 :             3월 23일
- 서류 + 코딩테스트 결과:     4월 9일     (목)
- 1차 면접 일정 발표 :         4월 11일
- 1차 면접 :                 4월 25일
- 1차 면접 결과 :             5월 3일    (금)
- 2차 면접 일정 :             5월 13일
- 2차 면접 :                 5월 28일
- 2차 면접 결과 :             6월 14일    (금)</code></pre><p>무려 시작부터 결과 발표까지 3개월이나 걸친 긴 프로세스였다 ...</p>
<p>지원자도 많을테고, 그만큼 많은 사람들 면접도 보고 서류도 보고 하느라 시간 오래걸린건 이해가 된다만 ...</p>
<img src="https://velog.velcdn.com/images/id_entity/post/68c17a22-3617-43b7-9943-0f12794f99ca/image.png">

<p>시간이 너무 안가 ....
프로세스 하나 끝내고 결과 나오기까지 오래 기다려야 해서 피가 너무 말리는 ... ㅠㅜ</p>
<br>

<hr>
<h2 id="📋-서류--🧑💻코딩테스트">📋 서류 + 🧑‍💻코딩테스트</h2>
<p>지원하게 되면 먼저 서류를 작성해야 한다 (당연한 말)</p>
<p>문항은 총 3개였는데, 실질적으로 작성해야 하는 건 2개뿐이었다 
( 하나는 깃허브나 포트폴리오 링크 )</p>
<br>

<h3 id="1번-문항">1번 문항</h3>
<pre><code>다음 중 본인의 가장 자신 있고 희망하는 분야를 한 가지 선택해 주세요.

■ Front-End ■ Back-End ■ Android ■ iOS ■ Data ■ 

공통선택한 분야에 **관심을 갖게 된 계기**와 **자신 있는 이유**(그동안의 노력, 경험, 강점 포함) 등에 대해 구체적으로 설명해 주세요.
※ 작성 예시 : ■ Front-End / 관심 계기 및 자신 있는 이유 :
※ 구체적인 희망 직무 분야가 미정이신 경우 &#39;공통&#39;으로 선택하시고 상세 사유를 작성해 주세요.</code></pre><br> 

<p>지금까지 iOS를 위주로 많이 해왔기 때문에 당연하게도 iOS 관련한 이야기를 썼다</p>
<p>적혀있는대로, 아직 정해둔 파트가 없다면 공통으로 적어도 무관할듯 ??</p>
<p>이 부분에서 가장 주의 깊게 고려한 부분은</p>
<blockquote>
<p>** 왜 **</p>
</blockquote>
<p>문항에도 적혀 있듯, 관심을 갖게 된 계기와 자신 있는 이유를 적어야 하는데,
<strong>왜</strong> 관심을 갖게 되었고, <strong>왜</strong> 자신 있는지,
이에 대한 충분하고 구체적인 근거들을 프로젝트랑 연관지어서 작성했다</p>
<p>그리고 나는 장점을 두 가지 썼는데
개발자로서의 장점과, 자신 있는 분야(나는 iOS)와 연관된 장점을 작성했다</p>
<img style="margin:50px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/f3b1cdcd-5df1-4ab1-af96-95339296401d/image.png" width="300">
<p align="left" style="color:gray">대충 완벽한 나를 나타내는 짤</p> 



<br>

<p>사실 팁이랄건 아니긴 하지만 ... 이번에 서류 작성하면서 느낀게</p>
<p>네이버 말고도 다른 회사 서류도 많이 작성했는데, 그러면서 글 실력이 는 것도 있지만
항상 <code>어제의 나와 오늘의 나는 다르다</code>는 마인드를 가졌음</p>
<p>무슨 의미냐면,
오늘 <code>이 장점 쓰면 진짜 좋을 것 같음 !!!</code>이라는 생각이 들어서 작성해둔게
내일 다시 생각해보면 별로라고 생각할수도 있고 더 좋은 장점이 떠오를수도 있다는 것</p>
<img align="center" src="https://velog.velcdn.com/images/id_entity/post/100b0b91-169e-4048-ab16-4c5f3378ff83/image.png" width="300">

<p>무튼 그래서 최대한 어필하려고 한 것들은 내가 개발을 얼마나 좋아하고 재미있어하는지인 것 같다 !</p>
<br>



<h3 id="2번-문항">2번 문항</h3>
<pre><code>가장 열정을 가지고 임했던 프로젝트(목표/과제 등)를 소개해 주시고, 
해당 프로젝트의 수행 과정 및 결과에 대해 기재해 주세요. (최대 1000자)</code></pre><p>이거는 타이밍이 좋다고 생각한게, 내가 NEXTERS 활동을 하면서
내가 얼마나 부족한지, 뭘 공부해야 하는지 알게 되었고,
이 때문에 공부한 것들을 다른 프로젝트의 리팩토링 과정에서 적용해나갔다</p>
<img style="margin:50px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/0291a978-5d9f-474f-b78d-7bda8078f841/image.png">
<p align="left" style="color:gray">참고로 나는 나한테 굉장히 가혹한 편 ..</p>

<br>

<p>이렇게 적용하는 과정에서 진짜 열심히 했고, 내 나름대로의 독창적인(아마?) 분석을 하기도 했는데 (이건 내 다른 게시글에서 볼 수 있음 !!) 이 분석 내용들도 간략하게나마 작성했다
(1차 면접 때 이와 관련된 질문이 나오기도 한거 보면 흥미롭게 보신 것 같기도 ?)</p>
<p>여기서도 역시 
<code>왜</code> 리팩토링을 하게 되었고, 
<code>왜</code> 리팩토링 과정에서 이런 기술 스택을 사용했고, 
<code>왜</code> 그런 분석을 하게 되었는지 등을 자세히 쓸려고 했다</p>
<p style="color:gray">
글로만 이렇게 쓰는게 아니라 `왜`를 계속 물어보는게 개발자로서의 옳은 태도라고 생각함
처음에 MVC를 적용했으면 왜 그랬는지, 
MVC에서 어떤 문제를 느껴서 MVVM으로 바꾸게 되었는지 등
</p>



<br>

<h3 id="3번-문항-선택">3번 문항 (선택)</h3>
<pre><code>[선택] 3. 본인의 대표적인 개발 경험이나 희망 분야 관련 과제 성과, 활동 등을 가장 잘 보여줄 수 있는 
Github, 블로그 등의 URL을 작성하시거나 자료를 첨부하시고, 간단한 소개나 설명을 해 주세요.

공동 프로젝트였다면 본인의 역할을 명확히 써 주세요.
오픈소스 컨트리뷰션, 프로젝트, 본인이 작성한 소스코드 등 (임시저장 후 복수 첨부 가능 / 최대 200MB)수강하셨거나 
별도로 공부하신 컴퓨터공학 관련 학습/과제/프로젝트 활동을 보여 주셔도 좋습니다.
</code></pre><p>요건 선택문항인 만큼 좀 부담 없이 쓰려고 한 듯 하다</p>
<p>딱히 크게 말할건 없고 그냥 팩트만 작성했다</p>
<p>작성한 것들</p>
<ul>
<li>깃허브 링크</li>
<li>앱 한 줄 소개</li>
<li>기술 스택</li>
<li>기간</li>
<li>인원</li>
<li>역할</li>
</ul>
<p>지금와서 더 나을 수 있지 않을까 싶은거는
깃허브 링크를 제대로 꾸미고 뭐 했는지 보기 쉽게 만들면 어땠을까 싶은 ...</p>
<br>

<h3 id="코딩테스트">코딩테스트</h3>
<pre><code>사실 코딩테스트는 ... 할 말이 더더욱 없다
왜냐하면 🐶 못봤기 때문 ...</code></pre><p>그리고 코딩테스트 문제가 뭐가 나왔는지 이야기할수도 없고 ...
정말 어떻게 붙었을까 싶을 정도로 코테를 못봤기 때문에 ....</p>
<p>조금 아래에서 이야기하겠지만 코딩테스트가 그렇게 크지 않을수도 있겠다 .. 싶은 느낌 ?</p>
<img style="margin:50px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/1fdfd1c3-8573-467a-a55c-4bab247cf0a0/image.png" width="400">
<p align="left" style="color:gray">실제로 서류+코테 붙고 들어간 공채 오픈채팅방 닉네임을 이왜진이었을 지은...</p>


<p>하지만 나같은 특이케이스가 또 있을까 싶기도 하고 실무 때에도 필요가 있지 않을까 싶어서 꾸준히 공부하긴 할거다</p>
<p>다른 분들이 2024년 코테 관련 후기 올려놓은 글들도 있으니 그거 확인하길 !!!</p>
<br>

<h3 id="후기">후기</h3>
<p>제대로 취준을 시작한거는 2023년 12월정도부터니까 ... 이것저것 많이 지원하지는 못했지만
이때까지는 막 서류나 코딩테스트가 &#39;완전 넘사다&#39;, &#39;너무 어렵다&#39; 이런 느낌은 없었다</p>
<p style="color:gray">
  이전 취준 과정에서 코테 승패 기록은
  <br>
  - 현대 오**버 (승)
  <br>
  - 팀 네*버 (승)
  <br>
  - 이베* 재팬 (승)
  <br>
  - CJ 올**영 (참패 ㅋㅋ)
</p>

<br>

<p>취준 시작하고 나서부터는 별 일 없는 이상
1일 1알고리즘을 오전 시간대(주로 코테가 오전이라서)에 풀었고
<code>프로그래머스 AI 문제 추천(?)</code> 이걸로 준비했다</p>
<p>코테가 얼마 안남은 시점에는 하루종일 코테만 팠음 ...</p>
<p>이렇게 매일 풀다보니 프로그래머스 레벨2는 쉽게 풀리고
레벨3는 재밌게(?) 고민하면서 풀 수 있었다
레벨4는 입만 험해졌음 ㅋㅋ</p>
<img src="https://velog.velcdn.com/images/id_entity/post/095b593d-b2f9-483e-9509-6e97d597b835/image.png">



<p>그리고 바로 위에도 말해놓은 것처럼 코테를 못봐도 서류를 흥미롭게 작성하면 충분히 가능성이 있으니까 !!
코테에 너무 일희일비하지 말자 !!
(기만인가 ..)</p>
<br>

<h3 id="결과">결과</h3>
<p>보자마자</p>
<p>엥? 했음</p>
<img src="https://velog.velcdn.com/images/id_entity/post/91006599-a32b-44de-a8cd-87354b138358/image.png" width="700">

<p>기 받아가십쇼</p>
<br>



<hr>
<h2 id="🧮-1차-면접--기술-역량-인터뷰-">🧮 1차 면접 ( 기술 역량 인터뷰 )</h2>
<p>여기까지 읽으신 분들은 얼추 많은 정보들을 찾아보지 않았을까 싶은데
찾아보신 것들 다 맞는 말입니다</p>
<p>악명 높습니다 ...</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/b8846d52-ad16-4ac8-b301-1f305f398c76/image.png" width="500">

<br>

<p>그래서 혼자서 준비하기보다 다른 사람들과 같이 하면 좋을 것 같았고
오픈채팅방에서 어쩌다보니 내가 면접 스터디를 파게 되었다</p>
<p>스터디를 하면서 너무 잘하는 스터디원들 때문에 주눅들기도 하고
(진짜 이건 기만 아니고 ㄹㅇ로 ;; 사람들 개잘함 ;; )
근데 오히려 여기서 더 자극받고 더 열심히 하게 된 것도 있다</p>
<p>그리고 집단지성이 좋긴 하잖슴 ~</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/26e9affd-bf97-45df-bd9f-e1860fe400b8/image.png">

<p>다시 후기로 넘어가자면 ...</p>
<p>1차 면접 때는 기술 역량을 봄 크게는</p>
<pre><code>- Computer Science
- 창의 / 수리 / 논리 문제
- 간단한 손 코딩
- 위 세 가지와 관련된 꼬리문제</code></pre><p>요롷게 나오는 것 같다
각각 어떻게 준비했는지 이야기해드리겠슴다</p>
<br>

<h3 id="computer-science">Computer Science</h3>
<p>먼저 말하자면, 내 스펙에서도 말했듯, 나는 전공생이지만 전공생이 아니다(?)</p>
<p>전자전기공학부를 나와서 <code>운영체제</code> 같은 과목을 듣긴 했다만 찐 전공생에 비해서는 얕게 배웠고
<code>데이터베이스</code>나 <code>컴퓨터네트워크</code>는 듣긴 들었지만 (수강할 당시에는)크게 필요성을 못느껴서 시험만 보고 머리 속에서 휘발되었다</p>
<img style="margin:50px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/b0d625b2-bca0-41c1-8c6c-c5bf926bf721/image.png">
<p align="left" style="color:gray">모두 각 자리에 잘 분류되어 있는 모습이다.</p>


<p>무튼 이정도로 CS가 준비가 안되어있던 상황이었고, 1차 면접 전까지의 기간(대략 2주)동안 OS, 컴퓨터네트워크, 데이터베이스, 알고리즘, 자료구조를 준비하기에는 시간이 절대적으로 부족해서 선택과 집중을 했다</p>
<p>그렇게 가장 우선순위를 두고 공부한건 <code>운영체제</code>
왜냐하면, iOS 개발을 하면서 가장 밀접한 부분이라고 생각했기 때문 !
그래서 가장 질문이 많이 나올 것 같았다</p>
<p>결론은 좋은 전략이었음 !!
(사람마다 다를 수 있으므로 함부로 따라하지 말 것)</p>
<br>

<p>그래서 운영체제 공부를 어떻게 했냐하면</p>
<p>그냥 냅다 함</p>
<ul>
<li>공룡책 중요하다고 생각하는 부분들 읽기</li>
<li>유투브 강의들 보기 (널널한 개발자, 우아한테크, 노마드 코더, 얄팍한 코딩사전)</li>
</ul>
<p>이렇게 일단 한 바퀴 돌리는데, 여기서 중요하다고 생각한건</p>
<blockquote>
<p>단순히 외우려고 하지 않고
<code>왜 쓰는지</code>, <code>어디에서 쓰는지</code>, <code>각 요소가 뭘 하는지</code>
이런 질문들을 계속 던지면서 깊게 파보기</p>
</blockquote>
<p>이게 중요한 이유는, 막상 한 바퀴 돌리고 났을 때</p>
<p><code>&quot;그래 운영체제가 어떤 역할을 하지?&quot;</code> 라고 스스로 질문했는데
만족스러운 대답을 할 수 없었다</p>
<p>뭐 보통 이야기한다면 <code>&quot;한정된 자원을 효율적으로 쓸 수 있게 분배한다&quot;</code>가 될 수 있는데
이거에 대해 <code>&quot;어떻게 효율적으로요?&quot;</code>와 같은 꼬리질문 하기가 애매하잖슴..</p>
<p>내가 저 대답보다 나은게 있을거라고 생각한 이유는 운영체제가 실제로 하는 굉장히 많은 것들</p>
<ul>
<li>프로세스 생성 / 종료</li>
<li>프로세스 메모리 할당 / 해제</li>
<li>가상 메모리 관리</li>
<li>입출력 관리</li>
<li>커널 영역 사이의 인터페이스</li>
<li>등등...</li>
</ul>
<p>이런 더 구체적인 대답이 있지 않을까 ?
더 꼬리질문 받고 궁금해할만한 대답이 있지 않을까 ?
이렇게 생각해서 !!</p>
<img style="margin:50px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/85b0cecb-8786-42a5-8bbc-e8e3b50b5ea7/image.png" width="300">
<p align="left" style="color:gray">(그새 휘발되었다 ㅋㅋㅋㅋㅋㅋㅋㅋ... 출근 전에 다시 공부해야지..)</p>

<p>그냥 단순히 생각해봐도
<code>&quot;자원을 효율적으로 관리하도록 합니다 !&quot;</code>  보다는
<code>&quot;프로세스 스케줄링, 메모리 할당 / 해제 , 가상 메모리 관리 등을 합니다 !&quot;</code>
이런 대답이 더 이야기할 거리가 많을 것이기에 !!</p>
<br>

<p>그렇게 여어어어어얼심히 공부하고 나서는
전체적인 운영체제와 이게 어떻게 돌아가는지 <code>스스로 말하면서 설명하는</code> 연습을 했다</p>
<p style="color:gray">
  다른 얘기이긴 하지만, 자료구조도 공부했는데 공부하고 나서 티비에다가 아이패드 연결하고 엄마아빠한테 이해 되도록 설명하는 연습 하기도 함
</p>

<p>왜냐하면 내 언어가 다른 사람들에게는 낯설수도 있기 때문에
그리고 말 하면서 정리하는게 내가 아는 지식들을 정리하기 좋다고 생각했기 때문 !</p>
<p>이건 꼭 해보길 추천 !!</p>
<br>

<h3 id="창의--수리--논리-문제--손코딩">창의 / 수리 / 논리 문제 + 손코딩</h3>
<p>요 두 개는 공부하면서 되게 재미있었다 (공부라기보다는 바쁜 와중에 나름대로 쉬면서 공부한 느낌)</p>
<p>크게 보면 두 가지를 많이 함</p>
<ul>
<li>문제적 남자 보기</li>
<li>책 보기</li>
</ul>
<p>문제적 남자는 운영체제 공부하다가 쉴 때 틈틈히 봤다
이거 보다보면 이런 방향으로도 생각할 수 있구나가 트이게 됨
(부작용: 재미있어서 공부 안하고 계속 보게 됨)</p>
<br>

<p>그리고 책은 두 가지 추천</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/37aa5492-6687-4518-b13c-490663ca3254/image.png" width="300">

<p><a href="https://m.yes24.com/Goods/Detail/415753">링크</a></p>
<br>

<img style="margin:10px 0 10px 0" align="left" src="https://velog.velcdn.com/images/id_entity/post/dc221189-4644-4ab2-bf64-9db7bcfd0978/image.png" width="300"/>

<p><a href="https://m.yes24.com/Goods/Detail/44305533">링크</a></p>
<p style="color:gray">이 게시글은 유료광고를 포함하고 있지 않습니다.<br> 당연히도 ㅋㅋ</p>

<p>&#39;후지산을 어떻게 옮길까&#39;는 면접 전전날에 집에 있는거 봤는데
오우 상당히 괜찮았음</p>
<p>&#39;코딩인터뷰 완전분석&#39;은 문제 보면서 코딩으로 구현해보면 손코딩 연습에 도움이  많이 됨</p>
<p>근데 &#39;후지산<del>&#39; 책은 비슷한 책 많이 있던거 같고
&#39;코딩인터뷰</del>&#39; 책은... 사실 대체 불가능인거 같기도 함</p>
<br>

<h3 id="후기-1">후기</h3>
<p>살살 쓰다가 이제서야 인지하게 됐는데 먼가 면접이나 코테에 대한 팁보다는
내가 어떻게 준비했는지를 쓴 글이 되어가는듯한 ....</p>
<p>머 어때 <del>~</del></p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/c118f2f1-8b57-4648-81fe-ae95e48b800c/image.png" width="300">

<p>무튼 1차 면접은 정말 색다른 면접이었다
문제풀이를 시킬줄은 ....</p>
<p style="color:gray">근데 그래도 애플 개발자 아카데미 면접이 어나더레벨로 신박했음 ㅋㅋㅎ</p>

<p>면접을 다 마무리하고 나서는 아래와 같은 생각이 들었다</p>
<blockquote>
<p>이유를 더 생각해볼걸</p>
</blockquote>
<p>왜냐하면 단순히 공부하고 설명에서 끝나는게 아니라 <code>공부한 지식들을 실제로는 어떻게 적용할 수 있을지, 어떻게 사용할 수 있을지</code> 등을 더 대비하고 가면 좋지 않았을까 싶었다</p>
<p>1차 면접에서 꿀팁을 하나만 꼽자면 이거라고 생각 ...</p>
<br>

<p>떨어질 것 같았나 붙을 것 같았나 생각을 해보면 ...
사실 붙는거 7 떨어지는거 3 정도인 것 같다</p>
<p>면접 마무리 후 질문 시간에 피드백 주실게 있는지 여쭤봤는데
면접관 중 한 분이 되게 잘 즐기고 있는 것 같다고 하셨기 때문에
내가 얼마나 개발을 좋아하는지나 열정있게 하는지가 드러난 것 같았다</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/8edb30df-48d6-4f9b-9a56-26c017f2d7d2/image.png" width="400">


<br>

<h3 id="결과-1">결과</h3>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/2bfa992f-6f7a-4d35-9d22-27aa4a429a02/image.png" width="700">

<p><strong>TMI</strong></p>
<p>합격 결과를 받고 너무 신기하고 흥분돼서 실수로 메일을 삭제했는데
삭제된 메일함에서 복구 버튼인 줄 알고 영구 삭제되었던 ...</p>
<p style="color:gray">
  2차 면접 때 네이버 관련 앱의 개선사항 관련해서 질문하시면 
  <br>
  이거 이야기할 생각이었음 ㅋㅋ
</p>

<img align="left" src="https://velog.velcdn.com/images/id_entity/post/6f48d4fe-d1f9-4dbb-803b-8fcd3a798a4c/image.png" width="300">

<p>그런데도 간직(?)하려고 메일 다시 받고 싶어서
재전송 가능한지 문의 넣었었음 ㅋㅋㅋㅋ</p>
<p>그래서 재전송 붙음 ㅋㅋㅋ</p>
<p>이것도 기 받아가십쇼 ...</p>
<br>

<hr>
<h2 id="🗣️-2차-면접--종합-역량-인터뷰-">🗣️ 2차 면접 ( 종합 역량 인터뷰 )</h2>
<p>자자 이제 1차 면접보다 더더 정보가 없는 그 2차 면접입니다 ...</p>
<p>대부분의 블로그 후기들에 적혀있을텐데 ...
뭐 이거 준비해라 저거 준비해라 할 것 없이 그냥 다 준비해야 합니다 ...</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/55b93fec-76e0-422f-9deb-d8ad347c0dde/image.png" width="200">

<p>우선 여기까지 오면 5월 중순쯤 되어서 너무 지쳤기 때문에
더 열심히 준비할 수 있었지만 그러지는 못했음 ...</p>
<p>2차 면접은 크게 준비한건</p>
<pre><code>- 1차 면접 때의 복기
- 1분 자기소개
- 자기소개서 관련 질문
- 인성 질문
- CS 및 기술 질문
- 진행한 프로젝트 관련한 경험 정리</code></pre><p>요정도 .... 
많네 ..</p>
<p>하나하나 빠르게 살펴보겠다</p>
<br>

<h3 id="1차-면접-때의-복기">1차 면접 때의 복기</h3>
<p>일단 (준비할 시간은 충분할 것 같지만) 시간이 너무너무 없다면 이거만큼은 확실하게 준비하는게 좋을 듯 하다</p>
<p>대부분의 2차 면접 후기에서도 강조된 부분이기도 하고
나도 중요하다고 생각하는 부분이기 때문 ( ^____^ 유남쌩 ? )</p>
<p>무튼 1차 면접 끝나고 받았던 질문을 다시 받아적어두든 잊기 전에 다시 복기하는걸 추천한다</p>
<img style="margin:30px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/818beba6-5a9f-476b-8a1d-1c8be062b7a2/image.png" width="250">
<p align="left" style="color:gray">내 머리속의 지우개가 작동하기 전에 ....</p>

<p>스스로 생각했을 때 
<code>아 이건 더 잘 대답할 수 있었는데 싶은 것</code>
<code>제대로 대답하지 못했던 것</code>
<code>다시 보니까 틀리게 대답한 것</code>
요런 것들은 다시 찾아보고 깊게 공부해보는거 추천..!!</p>
<br>

<h3 id="1분-자기소개">1분 자기소개</h3>
<p>개인적으로 나는 완전 각 잡힌 1분 자기소개를 별로 안좋아한다
자기소개를 하는건데 너무 준비한 티가 나면 인위적인 모습이 드는 것 같은..?
그래서 이건 크게 오래 준비하진 않고 틈틈히 생각했던 것 같음 !</p>
<p>내가 어떤 사람인지, 이 자리까지 오기에 어떤 노력을 거쳤는지
이런 것들을 짧고 굵게 말하려고 노력함</p>
<br>

<h3 id="자기소개서-관련-질문">자기소개서 관련 질문</h3>
<p>이것도 크게 말할건 없지만 ... 
그냥 단순히 서류 제출할 때 쓴 것들 다시 정리해봄
관련 경험이나 기술적인 어려움이나 등등...</p>
<br>

<h3 id="인성-질문">인성 질문</h3>
<p>내가 최종 면접을 본게 처음이라 인성 준비를 어떻게 해야할지 1도 몰랐는데
열심히 구글링 했다 ㅋㅋ</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/11495732-ab48-4e54-9fdd-5f276e3cbfd9/image.png" width="300">

<p>구글링 하다보면 (링크가 어디있는지 모르겠어서 ㅠ) 어떤 분이 개발자 면접 질문 받은거 싹 다 아카이빙 해 둔 노션 페이지를 찾을 수 있다</p>
<p>이런 질문 리스트로 내가 한 경험들 다시 리마인드 하고 회고도 하고 도움이 많이 된 것 같다
그대로 나온 질문은 없었지만, 대비한 질문들로 면접 때 어떻게든 연관시켜서 생각할 수 있게 됐듯</p>
<blockquote>
<p>그런고로 개발자 인생 회고 함 하는거 필수 !</p>
</blockquote>
<br>

<h3 id="cs-및-기술-질문">CS 및 기술 질문</h3>
<p>이건 자기소개서랑 연관이 있기도 한데, 자기소개서에 사용한 기술에 대해 많이 쓴다 ? 그러면 자소서에 쓴 것 관련해서 깊게 이야기한다고들 한다
(나는 기술적인걸 많이 쓰진 않아서 딱히 없긴 했지만)</p>
<p>대신 나는 자기소개서에  <code>~~에서 불편한 점을 느껴서 운영체제와 컴퓨터 네트워크에 대한 필요성을 느껴 공부할 예정입니다</code> 라는 식의 내용을 썼는데, 이거에 대비하기 위해서 운영체제랑 컴퓨터 네트워크를 열심히 공부했다</p>
<p>1차 면접 대비할 때 운영체제 공부를 해 둬서 2차 준비할 때에는 컴퓨터 네트워크 위주로 공부했음
(근데 사실 이와 관련해서 질문이 많이 나오지는 않았음 ..)</p>
<br>

<h3 id="진행한-프로젝트-관련한-경험-정리">진행한 프로젝트 관련한 경험 정리</h3>
<p>하 이것도 좀 준비를 많이 할 걸 싶었던 부분 중 하나다</p>
<img style="margin:30px 0 10px 0" src="https://velog.velcdn.com/images/id_entity/post/2e3c54c1-d611-4d47-a790-080609313fd9/image.png" width="300">
<p align="left" style="color:gray">붙어서 다행이지 떨어졌으면 진짜 후회했을듯 ...</p>

<p>나는 대외활동 되게 많이 한 편이라 (애플 개발자 아카데미, SOPT, 넥스터즈) 프로젝트도 되게 많이 했어서 이와 관련해서 많이 물어보셨다</p>
<blockquote>
<p>기술적인 것보다도 <code>협업적인 것</code> 들</p>
</blockquote>
<p>나랑 비슷한 케이스라면 필수 !!</p>
<br>

<h3 id="후기-2">후기</h3>
<p>이번에는 1차 때보다 더더 못봤다는 생각이 많이 들었다 ...
2차 끝나고는 그래도 분위기는 좋았어서 잘 봤다고 생각했는데 복기하고 나니까 조졌다는 생각밖에 안들었음 ...</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/416ea64e-6180-4e8e-8993-8ea059252bae/image.png" width="200">

<p>그래서 결과 나올 동안 떨어지는 악몽도 꾸고... 붙는 꿈도 꾸고... 여자친구한테 하소연도 많이 하고...
(Thanks and Love to SAJ)</p>
<p>그렇게 2주라는 기간을 감정기복이 굉장히 심한 상태로 지내다보니 결과가 나왔고 ...</p>
<br>

<h3 id="결과-2">결과</h3>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/e53f5865-fbd3-4b70-b241-063b94ba4a18/image.png" width="700">

<p>붙었다 !!!!!!</p>
<p>결과 메일을 키고 확인하는데 도저히 못보겠어서 손으로 가린 상태로 스크롤 내림
예전 전형은 탈락이면 궁서체인거 같아서
글씨체 확인하고 <code>어..?</code>
초록색 글씨 확인하고 <code>어...!!!!!?</code></p>
<p>보자마자 눈물이 나오더라 ㅠ</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/22cfec6d-b3af-439c-85e9-fc52c26c8d64/image.png" width="200">

<p>사실 팩트로 보자면 취준 기간은 6개월이었고 그렇게 긴 시간이 아닐수도 있지만
피말리는 기간을 3개월동안 보내고 노력하던 모습이 주마등처럼 지나가면서 눈물이 안날 수가 없었음....</p>
<p>바로 엄마한테 달려가서 부에에에엥ㅇ(진짜 우아아악 함) 하면서 핸드폰 보여줬는데
엄마도 같이 울고 ㅋㅋ 난리였음</p>
<p style="color:gray">지금도 그때 생각하면 울컥 함 ㅠㅠ</p>


<p>무튼 이렇게 길면 길고 짧으면 짧은 취준 기간이 끝났고, 이번에 떨어지면 iOS 말고 웹을 해볼까 고민하고 있었는데 어떻게든 iOS로 신입 채용을 뚫었다 ...
(들어가서 iOS 할지 안할지는 네이버 마음 ~)</p>
<p style="color:gray">네이버 하고 싶은거 다 해 !</p>

<p>이제는 신입으로서 어떻게 성장해나갈 수 있을지, 어떻게 선배들한테 예쁨 받을 수 있을지를 생각해야지..!</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/181267a6-b5fa-4272-9523-dbd403059718/image.png" width="200">

<br>

<hr>
<h2 id="❗️-당부의-말씀">❗️ 당부의 말씀</h2>
<p>글을 끝맺음 하기 전에 짧게나마 말하고 넘어가고 싶은 부분이...</p>
<blockquote>
<p>제 개인적인 경험이고, 
다른 분들은 자기소개서, 스펙, 경험, <code>담당 면접관</code>에 따라 다른 경험을 하실 수도 있습니다
제 말이 답은 아니라는 점 ...!!!!
내가 면접관이라면 어떤 사람들을 뽑을까? 에 대한 생각을 통해서 준비를 해 나가시는게 베스트일 것 같습니다 :)</p>
</blockquote>
<br>

<p>그리고 마지막으로..</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/e230973b-48e8-4df2-bfe7-9ec2b24b6eaf/image.png" width="400">
제 기 받아가십쇼 !!!!!

<p>모두 합격을 기원하며 !!</p>
<img align="left" src="https://velog.velcdn.com/images/id_entity/post/6bf7e75a-ca30-42b9-9856-18b834f6dc47/image.png" width="500">
]]></description>
        </item>
        <item>
            <title><![CDATA[[Object Oriented] 5. 책임과 메시지]]></title>
            <link>https://velog.io/@id_entity/Object-Oriented-5.-%EC%B1%85%EC%9E%84%EA%B3%BC-%EB%A9%94%EC%8B%9C%EC%A7%80</link>
            <guid>https://velog.io/@id_entity/Object-Oriented-5.-%EC%B1%85%EC%9E%84%EA%B3%BC-%EB%A9%94%EC%8B%9C%EC%A7%80</guid>
            <pubDate>Thu, 09 May 2024 08:55:13 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="자율적인-책임">자율적인 책임</h2>
<blockquote>
<p>객제치향 공동체를 구성하는 단위는 <code>자율적인</code> 객체
즉, 객체가 맡은 책임을 어떻게 수행하는지는 객체 <code>스스로</code>, 자율적으로 판단해서 행동</p>
</blockquote>
<ul>
<li><p>협력관계 내에서 객체는 요청을 받아서 어떤 행동을 수행
→ 이 수행을 <code>책임</code>이라고 함</p>
</li>
<li><p>A 객체와 B 객체가 협력관계 내에 있다고 가정
→ 이때, A객체가 B 객체에게 특수한 요청을 함
→ B 객체는 이 요청을 수행하기만 하면 됨, <code>어떻게 수행할지는 전적으로 B의 자율에 맡김</code></p>
</li>
<li><p>재판장이 모자장수에게 <code>증언을 요청</code></p>
<ul>
<li>“증언하라”
→ 모자장수가 <code>자율적으로 알아서 증언</code>하면 됨</li>
<li>“목격했던 장면을 떠올려라” / “떠오르는 기억을 시간 순서대로 ~” / “말로 간결하게 표현”
→ 책임을 <code>어떻게 수행할지를 제한</code>하고 있으므로 원활한 수행이 이루어지지 않을 수도 있음</li>
<li>“설명하라”
→ 어떤걸 설명하라는지 <code>너무 모호(추상적)</code></li>
</ul>
</li>
<li><p>추상적이고 포괄적인 책임은 협력관계에서 해당 책임을 재사용할 수 있도록 해줌
→ 자율성을 보장할 수 있도록 추상적이되, 협력의 의도를 파악할 수 있을 정도로 뚜렷해야 함</p>
</li>
<li><p>자율적인 책임의 특징은 협력을 위해 <code>어떻게</code>가 아니라 <code>무엇을</code> 해야 하는지가 핵심</p>
</li>
</ul>
<br>


<h3 id=""></h3>
<hr>
<h2 id="메시지와-메서드">메시지와 메서드</h2>
<h3 id="메시지">메시지</h3>
<blockquote>
<p>어떤 객체가 다른 객체에게 요청을 하기 위해 전송하는 것</p>
</blockquote>
<ul>
<li><p>메시지의 구성
→ <code>메시지 이름(함수명)</code>과 <code>인자(전달 값)</code> 으로 구성
→ <code>증언하라(어제, 왕국)</code></p>
</li>
<li><p>메시지 전송의 구성
→ 수신자와 메시지의 조합
→ <code>모자장수.증언하라(어제, 왕국)</code></p>
</li>
<li><p>모자 장수는 증언하라는 메시지를 전달받았을 때, 처리 방법을 자유롭게 선택할 수 있음
→ 모자 장수가 메시지 자체를 변경하지만 않는다면, 책임을 수행하는 방법을 바꿔도 재판장은 이를 알 수 없음
→ 객체의 외부와 내부가 분리되어 있다는 것</p>
</li>
</ul>
<br>


<h3 id="메서드">메서드</h3>
<blockquote>
<p>메시지를 처리하기 위해 내부적으로 선택하는 방법</p>
</blockquote>
<br>

<h3 id="다형성">다형성</h3>
<blockquote>
<p>서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응하는 것</p>
<p>서로 다른 타입에 속하는 객체들이 동일한 메시지를 수신할 경우 서로 다른 메서드를 이용해 처리</p>
</blockquote>
<ul>
<li><p>다형성을 만족시킨다는 것
→ 객체들이 동일한 책임을 공유한다는 것
→ 메시지 송신자의 입장에서는 다형적인 수신자들을 구별할 필요가 없고, 송신자의 요청만 수행하면 됨
→ <code>대체 가능성</code>을 의미</p>
</li>
<li><p>다형성이 설계를 유연하고 재사용 가능하게 만듬
→ <code>다형성</code>이 수신자의 종류를 <code>캡슐화</code></p>
</li>
<li><p>송신자와 수신자 간의 <code>결합도를 메시지에 대한 결합도로 낮춤</code></p>
</li>
</ul>
<br>

<h3 id="유연하고-확장-가능하고-재사용성이-높은-협력의-의미">유연하고 확장 가능하고 재사용성이 높은 협력의 의미</h3>
<ul>
<li><p><code>송신자가 수신자에 대해 매우 조금만 알아도 협력이 가능</code></p>
<ul>
<li><p>협력이 유연해짐
→ 송신자 입장에서 수신자가 메시지를 이해하기만 하면 어떤 타입으로 바꿔도 상관이 없음
→ 송신자는 수신자에게 어떤 메시지를 보낼 수 있는지만 알고 있음
→ 송신자에 대한 파급효과 없이 유연하게 협력 변경 가능</p>
</li>
<li><p>협력이 수행되는 방식을 확장할 수 있음</p>
</li>
<li><p>협력이 수행되는 방식을 재사용할 수 있음
→ 협력에 영향을 미치지 않고 다른 객체가 수신자의 자리를 대체할 수 있음</p>
</li>
</ul>
</li>
</ul>
<h3 id="-1"></h3>
<br>

<hr>
<h2 id="메시지를-따라라">메시지를 따라라</h2>
<h3 id="객체지향의-핵심-메시지">객체지향의 핵심, 메시지</h3>
<ul>
<li>객체지향의 핵심은 <code>책임을 수행</code>하는 <code>자율적인 객체</code>들의 <code>협력</code>을 통해 어플리케이션을 구축하는 것
→ 협력을 하기 위해 사용할 수 있는 유일한 수단은 <code>메시지의 전송</code>
→ 그렇기 때문에 메시지를 중심으로 객체의 내부 구조를 정의해야 함
→ 독립된 객체의 상태와 행위에 대해 고민하지 말고 시스템의 기능을 구현하기 위해 객체가 다른 객체에게 제공해야 하는 메시지에 대해 고민
→ 객체가 메시지를 선택하는 것이 아닌, 메시지가 객체를 선택하게 하기</li>
</ul>
<br>

<h3 id="책임-주도-설계-다시-살펴보기">책임-주도 설계 다시 살펴보기</h3>
<blockquote>
<p>책임을 완수하기 위해 협력하는 객체들을 이용해 시스템을 설계하는 방법</p>
</blockquote>
<ul>
<li>책임-주도 설계의 역할, 책임, 협력을 식별
→ <code>애플리케이션이 수행하는 기능을 시스템의 책임으로 보는 것에서 시작</code>
→ 시스템의 책임을 동작하게 하기 위해 적절한 협력관계를 찾기
→ 이렇게 찾은 시스템의 책임의 협력관계를 몇 가지 객체들의 책임으로 분산하여 할당</li>
</ul>
<br>

<h3 id="whatwho-사이클">What/Who 사이클</h3>
<blockquote>
<p>책임-주도 설계를 위해, <code>어떤 행위가 필요한지를 먼저 결정한 후에 객체를 결정하는 사이클</code></p>
</blockquote>
<ul>
<li>협력이라는 맥락에서, 객체부터 정하는 것이 아닌, 메시지부터 먼저 결정하는 것
→ 이렇게 메시지들이 모여, <code>책임을 구성함</code></li>
</ul>
<br>

<h3 id="묻지-말고-시켜라">묻지 말고 시켜라</h3>
<ul>
<li><p>책임-주도 설계는 객체가 아닌 객체들이 주고받는 메시지에 집중하여 객체지향의 장점을 극대화
→ 메시지에 집중하게 되면, 메시지 수신자의 캡슐화를 증진시킴
→ 그 결과, 더 유연하고 재사용 가능한 설계할 수 있음 &amp; 결합도가 낮아짐</p>
</li>
<li><p>‘어떻게’보다 ‘무엇을’에 집중하기
→ 객체의 인터페이스의 크기를 급격하게 줄일 수 있음
→ 외부에서 이 객체에 의존하게 되는 영역이 더 줄어듬
→ 협력관계의 송/수신자 사이의 결합도가 줄어듬</p>
</li>
</ul>
<h3 id="-2"></h3>
<br>

<hr>
<h2 id="객체-인터페이스">객체 인터페이스</h2>
<h3 id="인터페이스">인터페이스</h3>
<blockquote>
<p>두 사물이 마주치는 경계 지점에서 서로 상호작용할 수 있도록 이어주는 방법이나 장치</p>
</blockquote>
<ul>
<li>인터페이스가 갖는 3가지 특징<ul>
<li>인터페이스를 사용할 수만 있으면, 내부 동작 원리는 몰라도 됨</li>
<li>인터페이스를 변경하지 않고 내부 동작 원리만 바꾸는 것은 인터페이스에 아무 영향도 끼치지 않음</li>
<li>동일한 인터페이스를 제공하기만 한다면, 손쉽게 사용할 수 있음</li>
</ul>
</li>
</ul>
<br>

<h3 id="책임-메시지-그리고-인터페이스">책임, 메시지, 그리고 인터페이스</h3>
<ul>
<li><p>책임의 수행이 자율적이어야 함
→ 자율적이라 함은, 수행만 한다면, 수행 방법은 어떻게 하든 상관 없음</p>
</li>
<li><p>한 객체가 다른 객체에게 요청을 할 때 사용하는 메시지
→ 객체의 인터페이스가 객체가 수행할 수 있는 책임으로 채워져, 인터페이스를 통해 메시지를 전송
→ 특정 메시지를 수신했을 때, 그에 대한 동작을 수행
→ 메서드는 특정 메시지를 수행하는 방법을 의미
→ 이렇게 <code>메시지와 메서드를 구분</code>했기에, 객체의 내부와 외부를 분리된 영역으로 구분할 수 있고, 다형성을 통해 다양한 타입의 객체를 수용할 수 있는 유연성 부과</p>
</li>
<li><p>객체가 책임을 수행하기 위해 메시지를 받기 위한 통로인 인터페이스
→  객체가 다른 객체와 협력하기 위한 접점</p>
</li>
</ul>
<h3 id="-3"></h3>
<br>

<hr>
<h2 id="인터페이스와-구현의-분리">인터페이스와 구현의 분리</h2>
<h3 id="객체-관점에서-생각하는-방법">객체 관점에서 생각하는 방법</h3>
<ul>
<li><p>맷 와이스펠드의 인터페이스 관련 세 가지 원칙</p>
<ul>
<li><code>좀 더 추상적인 인터페이스</code>
→ 자율적인 책임을 부여한다
→ 단, 너무 추상적이면 역효과</li>
<li><code>최소 인터페이스</code>
→ 외부에서 사용할 필요가 없는 인터페이스는 최대한 노출하지 않기
→ 외부에 최소한의 정보만 공개할 수 있고, 그만큼 결합도가 낮아지며, 재사용성이 올라감</li>
<li><code>인터페이스와 구현 간에 차이가 있다는 점을 인식</code>
→ 아래에서 더 설명</li>
</ul>
</li>
</ul>
<br>

<h3 id="구현">구현</h3>
<blockquote>
<p>객체를 구성하지만 인터페이스에 해당하지 않는 모든 것</p>
</blockquote>
<ul>
<li><code>객체의 상태</code></li>
<li><code>객체의 행동(메서드)</code></li>
</ul>
<br>

<h3 id="인터페이스와-구현의-분리-원칙">인터페이스와 구현의 분리 원칙</h3>
<blockquote>
<p>객체 외부에 노출되는 인터페이스와 내부에 숨겨지는 구현을 명확하게 분리해서 고려
→ 외부에 공개되는 인터페이스와 내부에 감춰지는 구현, 두 가지 영역으로 나누어 설계</p>
</blockquote>
<ul>
<li><p>변경에 대한 안전지대와 위험 지대를 구분
→ 안전지대를 만드는 것은 객체를 더욱 자율적이게 만듬
→ 이 안전지대에서 변경을 주었을 때에는 외부에 어떤 변경사항도 야기해서는 안됨</p>
</li>
<li><p>이 원칙을 수행하기 위한 객체 설계 방법
→ <code>캡슐화</code></p>
</li>
</ul>
<br>

<h3 id="캡슐화">캡슐화</h3>
<blockquote>
<p>객체의 자율성을 보존하기 위해 구현을 외부로부터 감추는 것
(정보 은닉이라고도 함)</p>
</blockquote>
<p><strong>상태와 행위의 캡슐화</strong></p>
<ul>
<li>객체는 스스로 상태를 관리하고, 행동을 내부에 보관
→ <code>데이터 캡슐화</code>
→ 인터페이스와 구현을 분리하기 위한 전제 조건</li>
</ul>
<p><strong>사적인 비밀의 캡슐화</strong></p>
<ul>
<li>외부 객체가 객체 본인 내부를 알 수 없도록 막고, 일부만 의사소통 가능하게 노출
→ <code>인터페이스</code></li>
<li>외부에 제공할 필요가 있는 메시지들의 모음
→ <code>공용 인터페이스</code>
→ 개인적인 비밀은 공용 인터페이스의 뒤에 감춤</li>
</ul>
<h3 id="-4"></h3>
<br>

<hr>
<h2 id="책임의-자율성이-협력의-품질을-결정한다">책임의 자율성이 협력의 품질을 결정한다</h2>
<ul>
<li><p>첫 번째 이유 - <code>자율적인 책임은 협력을 단순하게 만듬</code>
→ 세부사항을 무시하고 의도만을 명확하게 표현하면, 협력을 이해하기 쉽게 됨
→ 책임이 적절하게 추상화 됨</p>
</li>
<li><p>두 번째 이유 - <code>자율적인 책임은 모자 장수의 외부와 내부를 명확하게 분리</code>
→ 책임이 자율적이기에, 책임만 완수한다면 어떻게 동작할지는 모자 장수의 몫
→ 요청하는 객체가 몰라도 되는 사적인 부분은 <code>캡슐화</code> 됨
→ 인터페이스와 구현이 분리됨</p>
</li>
<li><p>세 번째 이유 - <code>책임이 자율적일 경우 책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않음</code>
→ 변경에 의한 파급효과가 객체 내부만으로 한정됨
→ 두 객체 간의 결합도가 낮아짐</p>
</li>
<li><p>네 번째 이유 - <code>자율적인 책임은 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공</code>
→ 다양한 문맥에서 재사용할 수 있게 됨
→ 설계가 유연해지고, 재사용성이 높아짐</p>
</li>
<li><p>다섯 번째 이유 - <code>객체가 수행하는 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워짐</code>
→ 책임이 자율적일수록 객체의 응집도를 높은 상태로 유지하기 쉬워짐</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[연습장] Clean Architecture의 객체지향적 관점에서의 해석]]></title>
            <link>https://velog.io/@id_entity/%EC%97%B0%EC%8A%B5%EC%9E%A5-Clean-Architecture%EC%9D%98-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%A0%81-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C%EC%9D%98-%ED%95%B4%EC%84%9D</link>
            <guid>https://velog.io/@id_entity/%EC%97%B0%EC%8A%B5%EC%9E%A5-Clean-Architecture%EC%9D%98-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%A0%81-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C%EC%9D%98-%ED%95%B4%EC%84%9D</guid>
            <pubDate>Fri, 12 Apr 2024 05:50:38 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="서론">서론</h1>
<p>최근 들어서 프로젝트의 설계와 구조에 대한 관심이 컸었고,
이에 대한 계기는 <a href="https://github.com/Nexters/moyamoya-ios-app">Funch 프로젝트</a>의 개발 과정에 있다</p>
<p>현직자 형이랑 같이 개발을 하는데 무슨 레이어.. 저런 레이어.. 등등..
초반에는 전혀 이해도 안되는 이야기를 하길래 조금 <code>절망스럽기도 했다</code></p>
<p>하지만 여기서 끝내면 이성민이 아니지 ㅋ</p>
<p>프로젝트 중에는 개발하느라 바빴고, 
끝나자마자 Clean Architecture를 공부하기 시작했다</p>
<p>가장 괜찮은 공부 방법이 &#39;그&#39; 클린 아키텍쳐 서적을 읽는거였는데,
아니나 다를까 전혀 이해가 안됐고 ... 내 또다른 멘토 형이랑 밥 먹으면서
객체지향부터 공부해보면 좋을 것 같아서 책을 추천 받았다
-&gt; <code>&lt;객체지향의 사실과 오해&gt;</code></p>
<p>책은 다 읽었는데 면접, 코테, 취준 하느라 5장부터 블로그를 못썼는데,
조만간 다시 시작할 예정 ...</p>
<p>무튼 책을 읽고 클린아키텍쳐를 다시 생각해보니 ...
꽤나 흥미롭게 책임과 역할과 협력을 대입해가면서 분석할 수 있었다</p>
<p>이걸 공고 지원서에도 많이 썼고, 면접을 앞두고 있는데,
그 전에 스스로 한 번 정리하는 차원에서 글을 쓰게 됐다</p>
<br>

<hr>
<h1 id="본론">본론</h1>
<p>결국 iOS 개발을 하는 이유가 <code>서비스</code>를 제공하기 위해서이고,
그 <code>서비스</code>에 <code>Clean Architecture</code>를 적용하려고 하는거다</p>
<p>그래서 상세적인 레이어로 들어가기 전에 서비스를 사용하는 유즈케이스와
서비스가 담당해야 하는 책임, 협력 등에 대해서 살펴보겠다</p>
<h2 id="가장-거시적인-측면---서비스">가장 거시적인 측면 - 서비스</h2>
<blockquote>
<p>사람들이 <code>서비스</code>, 또는 <code>어플리케이션</code>을 왜 사용할까 ?
즉, 사용자들의 서비스를 사용함에 있어서의 <code>유즈케이스</code>는 뭘까?</p>
</blockquote>
<p>위 질문에 대해 가장 먼저 생각을 해봤다</p>
<p>그래서 내가 나름대로 생각한 유즈케이스는 아래와 같다</p>
<blockquote>
<p>특정 목적의 실행 ( 사실 유즈케이스 자체의 의미인 것 같긴 하다만... )</p>
</blockquote>
<p>왜냐하면 ... 카카오톡이나, 네이버나, 29CM이나.. 등등
주된 서비스의 사용 이유는 (상세적인 것은 다르겠지만) 특정 목적을 실행하는 것이다</p>
<ul>
<li>카카오톡을 통해서 지인과 원격으로 대화하기</li>
<li>네이버를 사용하면서 검색, 쇼핑, 뉴스 등등을 통해 정보를 얻기</li>
<li>29CM을 통해 쇼핑하기</li>
</ul>
<p>하지만 이렇게 서비스를 하나의 객체라고 생각하면, 너어어어어어무 많은 책임을 갖는다</p>
<br>

<h2 id="조금-더-깊게-들어가기---레이어">조금 더 깊게 들어가기 - 레이어</h2>
<p>너무 많은 책임을 조금 분산시키기 위해, <code>목적의 실행</code>이라는 책임을 조금 나눠보겠다</p>
<blockquote>
<ul>
<li>목적을 수행할 수 있는 화면을 보여준다 -&gt; <code>Presentation Layer</code></li>
<li>목적을 수행한다 -&gt; <code>Domain Layer</code></li>
</ul>
</blockquote>
<p>이렇게 생각해보면 <code>목적의 실행</code>이 
<code>Presentation</code> 과 <code>Domain</code> 사이의 협력관계로 생각할 수 있다</p>
<p><code>Domain</code>에서는 목적을 수행하고
<code>Presentation</code>에서는 유저에게 목적을 수행하기 위한 요소들을 보여준다</p>
<p>.</p>
<p>그래서 사실 볼륨이 작은 서비스들은 이 두 레이어만 있어도 되지 않을까라는 개인적인 생각이다</p>
<p>하지만 생각해보면, <code>목적을 수행</code>하기 위해서는, 대부분 <code>특정 정보</code>를 보여줘야 한다
즉, 내부/외부 데이터베이스로부터 <code>정보를 가져와야</code>한다</p>
<p>이런 관점에서, <code>Domain</code> 레이어를 다시 두 가지 책임으로 나눈다</p>
<blockquote>
<ul>
<li>특정 정보를 사용/가공하여 목적을 수행한다 -&gt; <code>Domain Layer</code></li>
<li>정보를 가져온다 -&gt; <code>Data Layer</code></li>
</ul>
</blockquote>
<p>.</p>
<p>이렇게 생각해보면, Clean Architecture의 세 가지 레이어의 책임이 나온다</p>
<blockquote>
<ul>
<li><code>Presentation</code> - 목적 수행을 위한 화면을 보여준다</li>
<li><code>Domain</code> - 특정 정보를 사용/가공하여 목적을 수행한다</li>
<li><code>Data</code> - 특정 정보를 가져온다</li>
</ul>
</blockquote>
<p>이를 협력관계로 보면 아래와 같다</p>
<blockquote>
<p><code>Presentation</code> - <code>Domain</code>: 유저와의 상호작용을 통해 특정 정보를 보여주며 가공한다 
<code>Domain</code> - <code>Data</code>: 특정 정보를 보여주고 가공하기 위해 외부/내부로부터 정보를 가져온다</p>
</blockquote>
<br>

<h2 id="조금-조금-더-깊게-들어가기---각-레이어">조금 조금 더 깊게 들어가기 - 각 레이어</h2>
<h3 id="presentation-레이어"><code>Presentation</code> 레이어</h3>
<p>Presentation은 결국 <code>화면을 보여주고, User Interaction을 처리</code>해야 한다
즉, 화면에서 보여지는 모든 것을 해야한다</p>
<p>이렇게 보면, Presentation 또한 너무 많은 책임이 있어서 나눈다 !</p>
<blockquote>
<ul>
<li>화면을 보이기 -&gt; <code>View</code></li>
<li>화면에서의 Interaction을 처리하기 -&gt; <code>ViewModel</code></li>
<li>화면에 정보를 띄우기 -&gt; <code>Model</code> -&gt; <code>Domain의 Entity</code></li>
</ul>
</blockquote>
<p>(MVVM 측면에서의 분리이다, 다른 패턴을 쓴다면 당연히 달라질 것이다)</p>
<p>기본적은 MVVM 측면에서는 이렇게 생각할 수 있다</p>
<p>여기에 추가적으로 <code>Coordinator</code>나, <code>DIContainer</code>등을 사용해서 책임을 더 분산시킬 수 있을 것 같다 !</p>
<br>

<h3 id="domain-레이어"><code>Domain</code> 레이어</h3>
<p>Domain은 <code>특정 정보를 사용/가공하여 목적을 수행</code>해야 한다
즉, Data 레이어로부터 정보를 가져오고, 이를 가공하고 사용해야 한다</p>
<p>이 또한 단일 객체에서 담당하기에는 책임이 막대하기 때문에, 나눈다 !</p>
<blockquote>
<ul>
<li>화면에 보일 정보의 형태 -&gt; <code>Entity</code></li>
<li>정보의 가공 및 사용 -&gt; <code>UseCase</code></li>
<li>정보를 가져오기 -&gt; <code>Repository</code> -&gt; <code>Data의 Repository</code></li>
</ul>
</blockquote>
<br>

<h3 id="data-레이어"><code>Data</code> 레이어</h3>
<p>Data는 <code>특정 정보를 가져와</code>야 한다
어디서? 데이터베이스에서
어느 데이터베이스에서? 내부? 외부?</p>
<p>이렇게 서로 아는 것이 다르기 때문에, 나눈다 !</p>
<blockquote>
<ul>
<li>정보를 가져오는 것을 요청하는 부분 -&gt; <code>Repository</code></li>
<li>&#39;외부&#39; 데이터베이스와 연결되는 부분 -&gt; <code>Network</code> (이름 개인차 有)</li>
<li>&#39;내부&#39; 데이터베이스와 연결되는 부분 -&gt; <code>Persistent Storage</code> (이름 개인차 有)</li>
</ul>
</blockquote>
<br>

<hr>
<h1 id="결론">결론</h1>
<p>이렇게 보면, 얼추 우리가 아는 Clean Architecture의 형태가 된다</p>
<p>프로젝트 볼륨, 의도, 또는 다른 아키텍쳐 적용 여부에 따라 각 역할과 책임과 협력관계가 달라질 수 있겠지만
<code>나</code>는 Clean Architecture에서는 이렇게 분석해보았다</p>
<p>처음 Clean Architecture가 나온 의미가 이와는 다를 수 있겠지만 머 ...</p>
<p>무튼 분석하면서 해당 아키텍쳐에 대해 훨씬 자세하게 이해할 수 있었던 것 같다 !
이후로도 책임과 협력과 역할 측면에서 쭉 분석해봐야겠다 !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[연습장] Coordinator Pattern 고민 및 연습 기록]]></title>
            <link>https://velog.io/@id_entity/%EA%B1%B4%EB%B9%B5-Coordinator-Pattern-%EC%97%B0%EC%8A%B5-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@id_entity/%EA%B1%B4%EB%B9%B5-Coordinator-Pattern-%EC%97%B0%EC%8A%B5-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Mon, 08 Apr 2024 08:19:00 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="서론">서론</h1>
<p>먼저 왜 Coordinator Pattern 의 연습이 필요했냐면,
&#39;출시&#39;는 했지만 코드는 개판인 프로젝트인 &lt;건빵&gt;의 리팩토링 과정에
반영한 것들 이것저것 생각하다 나온 디자인 패턴 중 하나이기 때문</p>
<p>약 스포 하자면 아래 다이어그램 아닌 다이어그램이 우리 서비스의 흐름이다
굉장히 ... 복잡하다 ...</p>
<p><img src="https://velog.velcdn.com/images/id_entity/post/544e1a26-9f77-4330-af93-c768b5bc717e/image.png" alt=""></p>
<p>이 복잡한 흐름을 Coordinator Pattern으로 조금이나마 간략하게 하려고 한다 !</p>
<p>무튼 꽤나 복잡한 상태이기 때문에 바로 프로젝트에 적용해보려고 하면 난리 날 것 같아서 연습으로 먼저 해봤다 !
이후에 적용 다 완료되면 <code>연습기</code> 말고 <code>설계할 때 생각한 것들</code>, <code>적용할 때 생각한 것들</code> 모두 올릴 것 같다 !!</p>
<br>

<hr>
<h1 id="고민">고민</h1>
<p>연습하고자/고민하고자 했던 요소들은 아래와 같다</p>
<blockquote>
<ul>
<li>TabBar를 어떻게 관리할까</li>
<li>LaunchScreen에서 유저/비유저 분기처리를 해야하는데, Coordinator에 어떻게 적용할까</li>
<li>29CM과 같은 서비스는 탭이 개별로 NavigationController를 갖는데, 없던걸 만드는것보다 있는걸 없애는게 쉬우니 적용해보자</li>
</ul>
</blockquote>
<p>일단 요정도 ??</p>
<br>

<p>.</p>
<br>

<h2 id="첫-번째-고민---appcoordinator와-launchscreen">첫 번째 고민 - AppCoordinator와 LaunchScreen</h2>
<p>위에 적어둔 고민거리가 대부분 여기에 포함되어 있다</p>
<p><code>AppCoordinator</code>는 최상단에 위치한 Coordinator로, 전체적인 앱 흐름을 관리하는 역할을 한다</p>
<ul>
<li>그렇기 때문에, 맨 처음에 로그인 했는지 안했는지를 판별해야지 다음 플로우로 넘어가는데</li>
<li><code>LaunchScreen</code>에서 보통 로그인 여부를 판단한다 !</li>
</ul>
<p>음.. 시작하자마자 고민을 하게 됐는데...</p>
<blockquote>
<p>LaunchScreen을 어떻게 관리할까 ?</p>
</blockquote>
<br>


<h3 id="생각의-흐름">생각의 흐름</h3>
<p>맨 처음 든 생각은</p>
<blockquote>
<ol>
<li><code>AppCoordinator</code>
에서 <code>LaunchScreenCoordinator</code>로 이동한 뒤</li>
<li><code>LaunchScreenViewController</code>를 실행시키고</li>
<li><code>LaunchScreenViewModel</code>에서 <code>viewWillAppear</code> 이벤트가 도달하면</li>
<li>로그인 여부를 판단하고, 이에 따라 <code>AppCoordinator</code>에게 적절한 플로우를 실행하라고 메시지를 전송하는 것</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/id_entity/post/2496da57-4809-44a9-bdd7-c0d6531d0df9/image.png" alt=""></p>
<p>Coordinator 하나 만드는데에도 꽤나 많은 리소스가 필요한데,
그걸 <code>LaunchScreen</code> 하나 때문에 <code>ViewController</code> <code>ViewModel</code> <code>Coodinator</code>를 모두 만든다는 생각에 &#39;흠...&#39;싶을 것 같다</p>
<p>그래서 기각 ㅎㅎ</p>
<br>

<br>

<p>그 다음으로 든 생각은</p>
<blockquote>
<ol>
<li><code>AppCoordinator</code>에서 <code>LaunchScreenViewController</code>를 실행</li>
<li><code>LaunchScreenViewModel</code>에서 로그인 여부를 판단하고</li>
<li><code>AppCoordinator</code>에게 적절한 플로우를 실행하라고 메시지 전송</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/id_entity/post/588cb4d2-9910-475a-b370-6e82247f34e8/image.png" alt=""></p>
<p>먼저 이 방법에 대해 말하기 전에 알아둬야 할게,
요번 건빵에서는 <code>DIContainer</code>도 만들어서 의존성을 주입해주는 방식을 쓰고 싶었다
하지만 꽤나 높은 러닝커브와 과도한 리소스가 필요할 것 같아서 일단은 기각시켰다</p>
<p>이걸 왜 말하냐 
-&gt; <code>DIContainer</code>에 미련이 남은 미련 줄줄 <code>바짓가랑이 붙잡는st.</code>이기 때문이다
-&gt; <code>DIContainer</code>를 적용할 수 있는 확장성을 생각했다는 의미 ..</p>
<pre><code>- DIContainer는 Presentation, Domain, Data 등 모든 레이어를 알고 있고,
- AppCoordinator가 DIContainer를 의존하고 있어서
- AppCoordinator도 Application 레이어에 존재해야 한다</code></pre><p>어 ? 나쁘지 않은데 ?</p>
<p><code>LaunchScreenVC</code>를 Presentation 레이어에 두고, <code>AppCoordinator</code>에서 실행시키면 되지 않을까 ?</p>
<p>이렇게 하면 내가 생각했을 때 얻게되는 (내 생각에서의) 이점이</p>
<blockquote>
<ul>
<li>추가적인 <code>Coodinator</code>를 만들지 않아도 된다는 것</li>
<li><code>SceneDelegate</code>에서 <code>AppCoordinator</code>에 <code>UIWindow</code>를 인스턴스로 넘겨준다면
<code>LaunchScreenVC</code>를 <code>UIWindow</code> 위에서 실행시켜서
별도로 <code>NavigationController</code>를 만들지 않아도 되는 것</li>
</ul>
</blockquote>
<p>음 .. 이전까지는 <code>LaunchScreen</code>을 위해 <code>UINavigationController</code>를 만드는게 의미가 있을까? 하는 궁금증도 생겼고,
조금 더 알아봐야 하겠지만 굳이..? 라는 생각이 들었다</p>
<p>결과적으로 첫 번째 방법보다는 두 번째 방법이 더 좋다는 생각이 들었다
하지만 이걸 적용할지 말지는 건빵을 좀 더 자세히 들여다보고 생각해볼듯 ...</p>
<br>

<p>.</p>
<br>

<h2 id="두-번째-고민---tabbarcontroller와-navigationcontroller">두 번째 고민 - TabBarController와 NavigationController</h2>
<p>지금 취준중인데, 그 과정에서 어떤 기업의 서비스를 살펴보다가 <code>UINavigationController</code> 위에 <code>UITabBarController</code>가 있는 것 (아마? ㅎㅎ;;)을 확인했다</p>
<p>이렇게 되면, <code>Tab</code> 별로 <code>Navigation</code>이 관리되지 않고,
<code>Tab</code> 위에 계속 화면이 쌓이게 되는 것이다</p>
<p>뷰와 <code>Tab</code>의 흐름에 따라서 적절한지, 적절하지 않은지 다를 것이라고 생각한다</p>
<blockquote>
<ul>
<li><p>만약 <code>TabBar</code>를 계속 보여주고 싶고, <code>Tab</code>별로 별도의 <code>Navigation</code>이 필요하다면,
<code>TabBarController</code> 아래에 <code>UINavigationController</code>를 두는 것 대신,
각 <code>Tab</code> 위에 <code>UINavigationController</code>를 둬야 할 것이다</p>
</li>
<li><p>그렇게 뎁스가 깊은 서비스가 아니기 때문에,<code>Tab</code> 별로 <code>Navigation</code>을 관리해야 할 필요가 없다면
<code>TabBarController</code> 아래에 <code>UINavigationController</code>를 두고 단일 Navigation으로 가져가는 것도 괜찮을 것 같다</p>
</li>
</ul>
</blockquote>
<p>하지만 내가 봤던 서비스는 뎁스가 괴애애앵장히 깊었고, 따라서 첫 번째 방법이 적절하다는 생각이 들었....</p>
<p>무튼 건빵은 서비스 볼륨은 나름 크지만 뎁스는 깊지 않기 때문에,
두 번째 방법으로 가도 되긴 하지만, 연습을 위해서는 첫 번째 방법을 채택했다</p>
<br>

<hr>
<h1 id="연습">연습</h1>
<p>첫 번째 고민에서는 첫 번째 방법을</p>
<pre><code>1. AppCoordinator 에서 LaunchScreenCoordinator로 이동한 뒤
2. LaunchScreenViewController를 실행시키고
3. LaunchScreenViewModel에서 viewWillAppear 이벤트가 도달하면
4. 로그인 여부를 판단하고, 이에 따라 AppCoordinator에게 적절한 플로우를 실행하라고 메시지를 전송하는 것</code></pre><p>두 번째 고민에서는 첫 번째 방법을</p>
<pre><code>1. 만약 TabBar를 계속 보여주고 싶고, Tab별로 별도의 Navigation이 필요하다면,
2. TabBarController 아래에 UINavigationController를 두는 것 대신,
3. 각 Tab 위에 UINavigationController를 둬야 할 것이다</code></pre><p>이 두 가지를 고려하면서 연습을 해봤다</p>
<br>

<p>.</p>
<br>

<h2 id="coordinatortype">CoordinatorType</h2>
<p>모든 Coodinator가 가져야 할 요소들이다
&#39;추상화&#39;시켜 &#39;메시지&#39;를 전송할 수 있어야 하므로, protocol로 추상화</p>
<pre><code class="language-swift">protocol CoordinatorType: AnyObject {
    var parent: ParentCoordinatorDelegate? { get set }
    var navigationController: UINavigationController { get }
    var children: [CoordinatorType] { get set }
    var flowType: CoordinatorFlowType { get }

    func start()
    func finish()
}

extension CoordinatorType {
    func finish() {
        children.removeAll()
        parent?.finish(child: self)
    }
}</code></pre>
<br>

<p>.</p>
<br>

<h2 id="appcoordinator">AppCoordinator</h2>
<p>먼저 AppCoordinator에서 할 책임은 </p>
<ul>
<li>LaunchScreenFlow를 보여주는 것과</li>
<li>MainFlow를 보여주는 것</li>
</ul>
<p>즉, <code>showLaunchScreeFlow</code>와 <code>showMainFlow</code>라는 메시지를 전송할 수 있어야 한다</p>
<br>

<p>그렇게 먼저 만든 프로토콜</p>
<pre><code class="language-swift">protocol AppCoordinatorType: CoordinatorType {
    func showLaunchScreenFlow()
    func showMainFlow()
}</code></pre>
<p>그리고 이에 대한 구현부</p>
<pre><code class="language-swift">final class AppCoordinator: AppCoordinatorType {

    weak var parent: ParentCoordinatorDelegate? = nil
    var children: [CoordinatorType] = []
    var flowType: CoordinatorFlowType { .app }

    var navigationController: UINavigationController
    private var tabBarController: UITabBarController?

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() {
        showLaunchScreenFlow()
    }

    func showLaunchScreenFlow() {
        let launchScreenCoordinator = LaunchScreenCoordinator(navigationController: self.navigationController)
        launchScreenCoordinator.start()
        launchScreenCoordinator.parent = self
        self.children = [launchScreenCoordinator]
    }

    func showMainFlow() {
        let tabs: [Tab] = Tab.allCases
        let tabNavigations: [UINavigationController] = tabs.map(makeTabNavigation)
        let tabBarController = makeTabBarController()

        self.tabBarController = tabBarController
        self.tabBarController?.setViewControllers(tabNavigations, animated: false)
        self.tabBarController?.selectedIndex = 0

        Array(zip(tabs, tabNavigations))
            .map { tab, navigation in makeTabCoordinator(type: tab, from: navigation) }
            .forEach { coordinator in
                coordinator.parent = self
                coordinator.start()
                children.append(coordinator)
            }

        guard let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate else { return }
        sceneDelegate.changeRootViewController(to: tabBarController, animated: true)
    }
}</code></pre>
<br>

<h3 id="showlaunchscreenflow">showLaunchScreenFlow()</h3>
<pre><code class="language-swift">func showLaunchScreenFlow() {
    let launchScreenCoordinator = LaunchScreenCoordinator(navigationController: self.navigationController)
    launchScreenCoordinator.start()
    launchScreenCoordinator.parent = self
    self.children = [launchScreenCoordinator]
}</code></pre>
<p><code>LaunchScreen</code>을 보여주는 <code>Coordinator</code>를 만들고 실행시킨다</p>
<br>

<h3 id="showmainflow">showMainFlow()</h3>
<pre><code class="language-swift">func showMainFlow() {
    let tabs: [Tab] = Tab.allCases
    let tabNavigations: [UINavigationController] = tabs.map(makeTabNavigation)
    let tabBarController = makeTabBarController()

    self.tabBarController = tabBarController
    self.tabBarController?.setViewControllers(tabNavigations, animated: false)
    self.tabBarController?.selectedIndex = 0

    Array(zip(tabs, tabNavigations))
        .map { tab, navigation in makeTabCoordinator(type: tab, from: navigation) }
        .forEach { coordinator in
            coordinator.parent = self
            coordinator.start()
            children.append(coordinator)
        }

    guard let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate else { return }
    sceneDelegate.changeRootViewController(to: tabBarController, animated: true)
}</code></pre>
<ol>
<li><code>Tab</code> 별로 <code>UINavigationController</code>를 만든다</li>
<li><code>TabBarController</code>를 만든다</li>
<li>1.에서 만든 <code>Tab</code> 별 <code>UINavigationController</code>를 <code>setViewControllers()</code>로 적절히 설정해준다</li>
<li><code>Tab</code>과 1.에서 만든 <code>Tab</code> 별 <code>UINavigationController</code>로 각 <code>Tab</code>에 알맞는 <code>Coordinator</code>를 만들고,</li>
<li>현재 <code>Coordinator</code>의 <code>children</code>에 추가한다</li>
</ol>
<p>이렇게 되면 각 <code>Tab</code> 별로 <code>UINavigationController</code>를 갖고,
각각 <code>Coordinator</code>도 갖게 된다</p>
<br>

<hr>
<h1 id="마치며">마치며</h1>
<p>다음에는 프로젝트 세팅 관련 글로 돌아올 예정 ...</p>
<p>.</p>
<p>사실 코드 설명은 ... 글을 쓰다보니 지쳐서 조금 간략하게 설명했지만 ...
아래 레포가 연습한 레포이니까 참고하면 좋을듯 ㅎㅎ ;;
<a href="https://github.com/seongmin221/coordinator-pattern-practice">Coordinator Pattern Practice</a></p>
<p>.</p>
<p>참고
<a href="https://medium.com/@maysam.shahsavari/a-comprehensive-guide-to-coordinator-pattern-in-swift-7e7647ecc525">A comprehensive guide to Coordinator Pattern in Swift</a>
<a href="https://somevitalyz123.medium.com/coordinator-pattern-with-tab-bar-controller-33e08d39d7d">Coordinator pattern with Tab Bar Controller</a>
<a href="https://jeonyeohun.tistory.com/310">[iOS] 메이트러너: 코디네이터 패턴 적용기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[리팩토링] 건빵 - 시작 전 계획]]></title>
            <link>https://velog.io/@id_entity/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%EA%B1%B4%EB%B9%B5-%EC%8B%9C%EC%9E%91-%EC%A0%84-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@id_entity/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%EA%B1%B4%EB%B9%B5-%EC%8B%9C%EC%9E%91-%EC%A0%84-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Sun, 31 Mar 2024 00:51:33 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="서론">서론</h2>
<p>SOPT 32기 앱잼 때 한 &lt;건빵&gt;을 리팩토링 하려고 한다</p>
<p>이에 대한 이유는 ... 아래와 같음</p>
<ul>
<li><p>사실 가장 큰 이유는 역량 강화겠지..? 
<code>성능을 ~에서 ~까지 ~% 개선했다</code> 또는 <code>~~를 사용해 Developer Experience를 개선했다</code> 등 ...</p>
</li>
<li><p>맨 처음 앱잼 할 때 있었던 기능들이 많았는데, 현실적으로 힘들다는 생각에 다이어트를 많이 시켰다
그래서 그 때 넣고자 했던 기능들 (지도, 위치기반 등)을 추가해야 하는데,
지금 코드에서 추가하면 정말 개판이 될 것 같아 추가 기능 개발 전에 리팩토링을 돌려야 한다는 생각</p>
</li>
<li><p>원래 일정대로라면 작년 말? 쯤에 출시를 했어야 했는데 App Store에서 빠꾸먹어서 ...
계속 미루다미루다 2월 중순쯤에 출시를 했다
무튼 요는 이게 아니라 32기 앱잼이 끝난 이후(2023.08쯤?)부터 지금까지 새롭게 공부한거나 알게 된 것들을 잘 적용해보고 싶은 생각</p>
</li>
</ul>
<p>크게 이렇게 3가지 이유 때문에 리팩토링을 하게 되었다 !!</p>
<br>

<hr>
<h2 id="리팩토링-계획">리팩토링 계획</h2>
<p>요번 리팩토링 때는 아래의 것들을 적용하려고 한다</p>
<blockquote>
<ol>
<li><code>Clean Architecture</code>
넥스터즈 24기를 하면서 리드 개발자 형님의 도움에 클린 아키텍처를 잘 &#39;이해&#39;하게 되었다
그래서 이번엔 실제로 내가 설계하고 적용해보면서 체화하고 싶은 ...!!</li>
</ol>
<ol start="2">
<li><code>Coordinator Pattern</code>
이건 내 개인적인 욕심 ?
원래 ViewController에서 담당하던 &#39;뷰의 전환&#39;이라는 역할을 다른 애한테 넘겨주고 싶었다
그동안 MVC 또는 MVVM 쓰면서 고생 많았지 ㅠㅠ 이제 편히 쉬렴 ... 이제는 역할을 많이 덜어줄거다</li>
</ol>
<ol start="3">
<li><code>Entity 설계</code>
이제까지 프로젝트를 진행하면서 팀원들끼리 크게 Entity를 정하고 간 적이 없었다
그래서 각자 필요할때마다 만들고 싶은 Model을 만들고 .. 하다보니
겹치는 Entity가 많았기 때문에, 이번에는 뷰 보면서 필요한 것들로 적절히 분배하고 설계할 생각</li>
</ol>
<ol start="4">
<li><code>&#39;제대로 된&#39; 디자인 시스템</code>
Funch 프로젝트를 진행하면서 얼추 만들어보긴 했는데 ... 그때도 다시 보면 좀 난잡하다
이제는 그래도 여기저기서 많이 쓰이는 요소들을 묶어서 디자인 시스템으로 관리해보고자 한다</li>
</ol>
<ol start="5">
<li><code>에러처리</code>
부끄럽지만 ... 지금까지 개발 하면서 제대로 된 에러처리를 한 적이 없 ....ㅠ
그냥 냅다 <code>return nil</code> 로 때려박은 경험이 많다 ...
그래서 요번엔 더 나은 UX를 위해 에러처리도 제대로 해보고 싶은 생각</li>
</ol>
<ol start="6">
<li><code>DIContainer 설계</code>
이것도 Funch 프로젝트를 하면서 처음 알게 된 애인데, 리드 형이 메모리 개선되는 것을 보여주니까 꽤나 유용하다는 생각이 들었다
지난번에는 <code>SwiftUI</code>에서 <code>EnvironmentObject</code>로 적용했었는데, 이번에는 UIKit에서 나름대로의 방법(?)으로 적용해보고 싶은 생각</li>
</ol>
<ol start="7">
<li><code>Combine</code>
이전에 RxSwift로 플젝을 잠시 진행한 적이 있어서 공부를 좀 했었는데,
역시 순정은 못이기지 ... 는 장난이고 
좀 더 Raw 한 Combine도 사용하면서 custom publisher나 subscriber도 만들면 좋은 경험이겠다 싶어서 사용 예정 !</li>
</ol>
</blockquote>
<p>자잘한 것들 더 따져보면 새롭게 적용하려는게 더 많을 수도 있지만 ...
일단은 요정도 생각이 들었다</p>
<p>다 사용할지 안할지도 모르겠고, 해보고 싶은 것들은 이정도 !!</p>
<p>맨 처음으로는 Coordinator Pattern 설계를 하지 않을까 싶다 !
다음 글에 작성할 예정 ㅎ</p>
<br>

<hr>
<p>건빵 레포를 ... 공개하고 싶은데 ... 지금은 너무 부끄러운 코드들이라 ...
리팩토링이 얼추 마무리 되면 공개하겠다 !!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Object-Oriented] 4. 책임, 역할, 협력]]></title>
            <link>https://velog.io/@id_entity/Object-Oriented-4.-%EC%B1%85%EC%9E%84-%EC%97%AD%ED%95%A0-%ED%98%91%EB%A0%A5</link>
            <guid>https://velog.io/@id_entity/Object-Oriented-4.-%EC%B1%85%EC%9E%84-%EC%97%AD%ED%95%A0-%ED%98%91%EB%A0%A5</guid>
            <pubDate>Wed, 20 Mar 2024 06:55:30 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="서론">서론</h2>
<ul>
<li>객체지향에 입문한 사람들의 가장 큰 실수
→ ‘협력’을 고려하지 않고 객체가 뭘 갖고 뭘 할 수 있는지부터 생각하는 것
→ <code>객체지향에서 중요한 것은 ‘협력’</code>
→ 객체들이 어떻게 서로 협력해내는지
→ 어떤 협력에 참여하는지 ⇒ 객체가 필요한 행동 결정
→ 객체가 필요한 행동 ⇒ 객체가 가질 상태 결정</li>
</ul>
<br>

<h3 id=""></h3>
<hr>
<h2 id="협력">협력</h2>
<h3 id="요청하고-응답하며-협력하는-사람들">요청하고 응답하며 협력하는 사람들</h3>
<ul>
<li>협력은 여러 객체가 참여하며, 연쇄적으로 이루어짐
→ 시작은 한 객체가 도움을 청할 때 시작
→ 처리를 할 수 있을 것 같은 다른 객체에 요청을 보냄</li>
</ul>
<br>

<h3 id="재판-속의-협력">재판 속의 협력</h3>
<p><img src="https://velog.velcdn.com/images/id_entity/post/582fc03e-f536-493a-9c67-2c18f146ce6f/image.png" alt=""></p>
<ul>
<li>앨리스의 이야기 속에서의 협력<ol>
<li>누군가가 왕에게 재판을 <code>요청</code></li>
<li>왕이 하얀 토끼에게 증인을 부를 것을 <code>요청</code></li>
<li>요청을 받은 토끼는 모자 장수에게 증인석으로 입장할 것을 <code>요청</code></li>
<li>모자 장수는 증인석에 입장함으로써 토끼의 요청에 <code>응답</code> = 토끼의 왕의 요청에 대한 <code>응답</code></li>
<li>왕은 모자 장수에게 증언할 것을 <code>요청</code></li>
<li>모자 장수는 알고 있는 내용을 증언하여 왕의 요청에 대해 <code>응답</code></li>
</ol>
</li>
</ul>
<ul>
<li><p>누군가 ⇒ 왕 : 재판하라
→ 왕은 재판을 수행할 의무가 있음 &amp; 재판에 필요한 지식이 있음</p>
</li>
<li><p>왕 ⇒ 토끼 : 목격자 불러와라
→ 토끼는 목격자에 대해 알고 있음 &amp; 목격자를 부를 의무가 있음</p>
</li>
<li><p>왕 ⇒ 모자 장수 : 증언하라
→ 모자 장수는 증언할 내용을 알고 있음 &amp; 증언할 의무가 있음</p>
</li>
</ul>
<br>

<h3 id="-1"></h3>
<hr>
<h2 id="책임">책임</h2>
<h3 id="책임의-분류">책임의 분류</h3>
<ul>
<li><code>책임</code> : 객체에 의해 정의되는 <code>응집도 있는</code> 행위의 집합
→ <code>객체가 알아야 할는 정보와 객체가 수행할 수 있는 행위에 대해 개략적으로 서술한 문장</code></li>
</ul>
<br>

<ul>
<li><p>책임의 구성</p>
<ul>
<li><p>객체가 무엇을 알고 있는가 ( knowing )</p>
<ul>
<li>개인적인 정보에 관해 아는 것</li>
<li>관련 객체에 관해 아는 것</li>
<li>자신이 유도하거나 계산할 수 있는 것에 관해 아는 것</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>- 무엇을 할 수 있는가 ( doing )

    - 객체를 생성하거나 계산을 하는 등의 스스로 하는 것
    - 다른 객체의 행동을 시작시키는 것
    - 다른 객체의 활동을 제어하고 조절하는 것</code></pre><br>

<ul>
<li><p>앨리스의 이야기</p>
<ul>
<li><p>왕</p>
<ul>
<li>Doing: 왕은 재판을 집행 / 토끼에게 증인을 불러오도록 요청 / 증인에게 증언하라고 요청
→ “<code>다른 객체들의 활동을 제어하고 조율</code>”
→ 하는 것에 관련된 책임을 수행</li>
</ul>
</li>
<li><p>토끼</p>
<ul>
<li>Knowing: 토끼는 목격자가 모자장수임을 알고 있음
→ “<code>관련된 객체에 대해 아는 것</code>”
→ 아는 것에 대한 책임</li>
<li>Doing: 증인에게 증인석에 입장하도록 요청
→ “<code>다른 객체의 행동을 시작시키는 것</code>”
→ 하는 것에 대한 책임</li>
</ul>
</li>
<li><p>모자 장수</p>
<ul>
<li>Knowing: 자신이 알고 있는 사실을 증언해야 함
→ “<code>자신이 유도하거나 계산할 수 있는 것에 관해 아는 것</code>”
→ 아는 것에 대한 책임</li>
<li>Doing: 스스로 증인석에 입장
→ “<code>객체를 생성하거나 계산을 하는 등의 스스로 하는 것</code>”
→ 하는 것에 대한 책임</li>
</ul>
</li>
</ul>
</li>
</ul>
<br>

<ul>
<li><code>책임</code>은 객체의 <code>외부</code>에 제공해 줄 수 있는 정보와 <code>외부</code>에 제공해 줄 수 있는 서비스의 모음
→ 책임은 객체의 <code>공용 인터페이스</code></li>
</ul>
<br>

<h3 id="책임과-메시지">책임과 메시지</h3>
<ul>
<li><p>A객체(송신자) ⇒ B객체(수신자): 요청 전송
→ <code>요청</code> 은 수신자의 책임이 수행되게 함
→ 이런 과정을 <code>메시지 전송</code> 이라 함</p>
</li>
<li><p>책임의 수준 ≠ 메시지의 수준
→ 책임은 객체의 협력을 위해 수행해야 하는 것들을 개략적으로 서술한 것
→ 메시지는 이 책임을 필요한 여러 메시지로 분할해서 진행</p>
</li>
</ul>
<blockquote>
<p>객체지향 설계의 시작점</p>
<p><code>협력</code>에 참여하기 위해 
어떤 객체가 어떤 <code>책임</code>을 수행해야 하고
어떤 객체로부터 <code>메시지</code>를 수신할 것인지를 결정하는 것</p>
</blockquote>
<br>

<h3 id="-2"></h3>
<hr>
<h2 id="역할">역할</h2>
<h3 id="책임의-집합이-의미하는-것">책임의 집합이 의미하는 것</h3>
<ul>
<li>어떤 객체가 수행하는 <code>책임의 집합</code> = 협력에서 해당 객체가 수행하는 <code>역할</code></li>
</ul>
<br>

<h3 id="역할이-답이다">역할이 답이다</h3>
<ul>
<li>모자 장수, 요리사, 앨리스가 증인으로 선택된 상황
→ 총 3 가지의 협력 상황
→ 모자 장수, 요리사, 앨리스를 <code>증인</code> 이라는 역할로 포괄한다면, 단일 협력 상황으로 추상화 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/id_entity/post/32fa4b6e-4778-4ab6-a7ec-338ea460fc33/image.png" alt=""></p>
<ul>
<li>추상화된 협력<ol>
<li>누군가가 <code>판사</code>에게 재판을 요청</li>
<li><code>판사</code>는 토끼에게 증인을 부를 것을 요청</li>
<li><code>판사</code>의 요청을 받은 토끼는 <code>증인</code>에게 증인석으로 입장할 것을 요청</li>
<li><code>증인</code>은 증인석에 입장하여 토끼의 요청에 응답</li>
<li><code>증인</code>이 증인석에 입장함으로써, 토끼에 대한 <code>판사</code>의 요청에 대한 응답</li>
<li><code>판사</code>는 <code>증인</code>에게 증언할 것을 요청</li>
<li><code>증인</code>은 자신이 알고 있는 내용을 증언함으로써 <code>판사</code>의 요청에 응답</li>
</ol>
</li>
</ul>
<br>

<ul>
<li>역할을 대체할 수 있는 객체는 동일한 메시지를 이해할 수 있는 객체여야 함</li>
</ul>
<br>

<ul>
<li><p>메시지가 책임을 의미함
→ 동일한 역할 수행 가능 = 동일한 책임의 집합 수행 가능
→ 동일한 역할 수행 가능 = 동일한 메시지를 수신할 수 있음
→ 동일한 역할 수행할 수 있는 객체들끼리 묶어서 <code>추상화</code> 가능</p>
</li>
<li><p>추상화를 한다면 ( 역할을 부여한다면 )
→ 인지 과부화 줄일 수 있음 = 단순성, Simplicity
→ 협력이 유연해짐 = 유연성, Flexibility
→ 재사용성이 높아짐 = 재사용성, Reusability</p>
</li>
</ul>
<br>

<h3 id="협력의-추상화">협력의 추상화</h3>
<ul>
<li><code>역할</code>은 여러 객체가 협력에 참여 가능하게 하여 <code>협력을 추상화</code> 할 수 있게 함</li>
<li><code>협력의 추상화</code>는 협력의 개수를 줄이고, 협력에 참여하는 객체를 추상적인 역할로 대체</li>
</ul>
<br>

<h3 id="대체-가능성">대체 가능성</h3>
<ul>
<li><p><code>역할</code>은 협력 안에서 구체적 객체로 대체 가능
→ 동일 역할이면, 다른 객체로 대체 가능
→ 동일 역할(동일한 책임의 집합)을 모두 수행할 수 있어야 함</p>
</li>
<li><p><code>객체</code>는 역할에 주어진 책임 이외에도 다른 책임을 수행할 수 있음
→ <code>역할</code>이 암시하는 것 보다 더 많은 책임 가질 수 있음
→ 역할-객체 관계 = <code>일반화-특수화 관계</code></p>
</li>
</ul>
<br>

<h3 id="-3"></h3>
<hr>
<h2 id="객체의-모양을-결정하는-협력">객체의 모양을 결정하는 협력</h2>
<h3 id="흔한-오류">흔한 오류</h3>
<p><strong>객체에 대한 선입견</strong></p>
<ul>
<li>객체의 존재 이유는 데이터를 저장하기 위해
→ 진짜 객체의 존재 이유는 <code>협력에 참여하기 위해</code>
→ 실제로 중요한 것은 <code>객체의 행동(책임)</code></li>
<li>객체지향이 클래스-클래스 간의 관계를 표현하는 정적인 측면에 집중
→ 객체지향은 협력에 중점을 두고, 객체는 협력에 참여할 때 동적임</li>
</ul>
<br>

<h3 id="협력을-따라-흐르는-객체의-책임">협력을 따라 흐르는 객체의 책임</h3>
<ul>
<li><p>객체를 설계하기 전에 올바른 협력을 설계해야 함
→ <code>설계에 참여하는 객체들이 주고받을 요청과 응답의 흐름을 설계해야 함</code></p>
<ol>
<li>객체에게 책임을 할당 = 객체가 외부에 제공할 행동</li>
<li>해당 행동에 필요할 데이터 결정</li>
<li>클래스의 구현</li>
</ol>
</li>
<li><p>협력에 필요한 책임을 얼마나 합리적, 적절하게 설계했는지가 설계의 품질을 결정</p>
</li>
</ul>
<blockquote>
<p>협력을 가장 먼저 정의하자</p>
</blockquote>
<br>

<h3 id="-4"></h3>
<hr>
<h2 id="객체지향-설계-기법">객체지향 설계 기법</h2>
<ul>
<li><p>책임-주도 설계
→ 책임들을 식별하고 책임을 할당</p>
</li>
<li><p>디자인 패턴
→ 반복적으로 사용하는 해결 방법을 정의해 둔 템플릿</p>
</li>
<li><p>테스트-주도 개발
→ 테스트를 먼저 작성하고 통과하는 것들만 코드로 작성</p>
</li>
</ul>
<br>

<h3 id="책임-주도-설계">책임-주도 설계</h3>
<ul>
<li><p>객체의 책임을 중심으로 시스템을 구축하는 방법
→ 시스템의 기능은 더 작은 책임으로 분할
→ 각 책임은 특정 객체에 할당
→ 특정 책임을 여러 객체가 수행할 수 있다면, 추상화</p>
</li>
<li><p>시스템의 책임 ⇒ 객체의 책임으로 할당
→ 객체가 책임을 수행할 때, 협력자를 찾아 다른 책임을 할당</p>
</li>
</ul>
<blockquote>
<p>책임-주도 설계 정리</p>
<ul>
<li>시스템이 사용자에게 제공해야 하는 시스템 책임을 파악</li>
<li>시스템 책임을 더 작은 책임으로 분할</li>
<li>분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 할당</li>
<li>객체가 책임을 수행하는 도중 도움이 필요하면 또 이 도움이라는 책임을 질 다른 객체를 찾음</li>
<li>해당 객체에게 책임을 할당하고, 협력을 이룸</li>
</ul>
</blockquote>
<br>

<h3 id="디자인-패턴">디자인 패턴</h3>
<p>-</p>
<h3 id="테스트-주도-개발">테스트-주도 개발</h3>
<p>-</p>
<br>

<hr>
<p><a href="https://m.yes24.com/Goods/Detail/18249021">객체지향의 사실과 오해</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Object-Oriented] 3. 타입과 추상화]]></title>
            <link>https://velog.io/@id_entity/Object-Oriented-3.-%ED%83%80%EC%9E%85%EA%B3%BC-%EC%B6%94%EC%83%81%ED%99%94</link>
            <guid>https://velog.io/@id_entity/Object-Oriented-3.-%ED%83%80%EC%9E%85%EA%B3%BC-%EC%B6%94%EC%83%81%ED%99%94</guid>
            <pubDate>Sun, 10 Mar 2024 07:27:02 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="서론">서론</h2>
<img src="https://cloudfront-ap-northeast-1.images.arcpublishing.com/chosun/K5YVAUVN4NQFRTJ4HTEUE2NY6A.jpg" width="300">

<p>과거 런던의 지하철 노선도</p>
<img src="data:image/jpeg;base64,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" width="300">

<p>현재 런던 지하철 노선도</p>
<blockquote>
<p>과거와 현재의 런던 지하철 노선도를 살펴보면, 훨씬 가독성이 좋음</p>
<p>과거의 런던 지하철 노선도는 다른 것들보다 아래 요소들을 보이는데에 집중함</p>
<ul>
<li>거리</li>
<li>실제 위치</li>
</ul>
<p>하지만 사람들은 실제 위치나 거리에 생각보다 신경쓰지 않아 현재는 다른 요소들에 집중함</p>
<ul>
<li>순서</li>
<li>환승 가능 역</li>
</ul>
<p>즉, 과거에는 목적이 잘못 설정되어 가독성 떨어지고, 사람들이 보기 어려운 노선도를 사용했지만,
현재는 사람들이 노선도를 보는 목적을 제대로 파악하여 간단히 만들었음 → 지하철 노선도를 <code>추상화</code></p>
</blockquote>
<br>

<hr>
<h2 id="추상화를-통한-복잡성-극복">추상화를 통한 복잡성 극복</h2>
<ul>
<li><p>현실에 존재하는 것들을 이해해야 하는데, 그렇다기엔 너무 복잡
→ 이해하기 쉽고 간단한 것으로 현실을 <code>분해</code>하고 <code>단순화</code> 해야 함</p>
</li>
<li><p>추상화란 현실에서 시작하되, 목적에 따라 정말 필요한 요소들만 남겨 본질을 보이게 함</p>
</li>
<li><p>하지만, 추상화도 목적에 맞지 않게 사용한다면, 잘못 사용되는 것</p>
</li>
</ul>
<blockquote>
<p>이 책에서 <code>추상화</code>의 정의</p>
<p>어떤 양상, 세부 사항, 구조를 좀 더 명확하게 이해하기 위해 
특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법이다.</p>
<p>복잡성을 다루기 위해 추상화는 두 차원에서 이뤄진다.</p>
<ul>
<li>첫 번째 차원은 구체적인 사물들 간의 공통점은 취하고 차이점은 버리는 <code>일반화</code>를 통해 단순하게 만드는 것이다.</li>
<li>두 번째 차원은 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거함으로써 <code>단순</code>하게 만드는 것이다.</li>
</ul>
<p>모든 경우에 추상화의 목적은 목잡성을 이해하기 쉬운 수준으로 단순화하는 것이라는 점을 기억하라.</p>
</blockquote>
<pre><code>따라서, 객체지향 패러다임은, `객체`라는 `추상화`를 통해 현실의 복잡성을 극복한다</code></pre><br>

<hr>
<h2 id="객체지향과-추상화">객체지향과 추상화</h2>
<h3 id="모두-트럼프일-뿐">모두 트럼프일 뿐</h3>
<blockquote>
<p>이상한 나라의 앨리스 이야기 중
앨리스가 정원에 입장해 하트 여왕과 다양한 트럼프 병사들, 
그리고 하얀 토끼를 만나는 장면에 대한 묘사</p>
<p>앨리스는 마지막에 “기껏해야 트럼프에 불과해. 무서워할 필요 없어” 라고 말함</p>
</blockquote>
<br>

<h3 id="그룹으로-나누어-단순화하기">그룹으로 나누어 단순화하기</h3>
<p>앨리스의 그룹화</p>
<ul>
<li><p>앨리스는 “기껏해야 트럼프에 불과해. 무서워할 필요 없어” 이라고 말함
→ 다양한 트럼프 병사들을 그저 ‘트럼프 병사’로 그룹화 함
→ 하지만 이 그룹에 ‘하얀 토끼’는 포함되지 않음 / 동일한 특성을 갖고 있지 않기 때문
→ <code>명확한 경계를 가져 구별할 수 있는 것들을 객체라고 함</code></p>
</li>
<li><p>이번 이야기의 등장인물들 중, 정원사, 병사, 신하, 왕자, 공주, 왕, 왕비, 하트 잭 … 등은 
모두 ‘<code>트럼프</code>’와 동일한 외형과 행동 방식을 지니고 있음
→ 위 등장인물들을 모두 트럼프 그룹에 포함시킬 수 있음
→ 하얀 토끼는 트럼프에 속하지 못함
→ 결과적으로 앨리스는 등장인물들으 두 개의 그룹으로 나눔 / 트럼프, 토끼</p>
</li>
</ul>
<br>

<p>개념</p>
<blockquote>
<p><code>개념</code> 이란
공통점을 기반으로 객체들을 묶기 위한 그릇
우리가 인식하고 있는 다양한 사물이나 객체에 적용할 수 있는 아이디어나 관념</p>
</blockquote>
<ul>
<li><p>개념을 이용하면 객체를 여러 그룹으로 <code>분류</code>할 수 있음
→ 개념은 여러 객체의 공통점을 기준으로 객체들을 분류할 수 있는 ‘체’</p>
</li>
<li><p>어떤 객체에 특정 개념을 적용할 수 있게 되어, 해당 개념 그룹에 속하게 될 때
→ 해당 객체를 이 개념의 <code>인스턴스</code>라고 함</p>
</li>
</ul>
<blockquote>
<p>객체란, 특정 개념을 적용할 수 있는 구체적인 사물을 의미함
개념이 객체에 적용되었을 때 객체를 개념의 인스턴스라고 함</p>
</blockquote>
<br>

<h3 id="개념의-세-가지-관점">개념의 세 가지 관점</h3>
<blockquote>
<p>일반적으로 개념을 객체의 분류 장치로 생각할 때, 세 가지 관점이 있음</p>
<ul>
<li><code>심볼</code>: 개념을 가리키는 간략한 이름이나 명칭
e.g. ‘트럼프’라는 이름</li>
<li><code>내연</code>: 개념의 완전한 정의를 나타내며, 내연의 의미를 이용해 객체가 개념에 속하는지 여부를 확인할 수 있음
e.g. ‘트럼프’는 ‘몸이 납작하고 두 손과 두 발이 네모난 몸 모서리에 달려 있음’</li>
<li><code>외연</code>: 개념에 속하는 모든 객체의 집합
e.g. ‘정원사’, ‘병사’, ‘신하’, ‘왕자와 공주’, ‘하객’, ‘하트 잭’, ‘하트 왕’, ‘하트 여왕’ 등</li>
</ul>
</blockquote>
<pre><code>개념을 이용해 공통점을 갖는 객체들을 분류할 수 있음 !!!</code></pre><br>

<h3 id="객체를-분류하기-위한-툴">객체를 분류하기 위한 툴</h3>
<blockquote>
<p><code>분류</code>란
객체에 특정한 개념을 적용하는 작업이다.
객체에 특정한 개념을 적용하기로 결심했을 때 우리는 그 객체를 특정한 집합의 멤버로 분류하는 것.</p>
</blockquote>
<ul>
<li><code>분류</code>가 객체지향의 품질을 결정함
→ 객체를 적절히 분류하면, 유지보수성 증가, 변경에 유연하게 대처 가능
→ 적절한 분류 체계가 객체들 간의 ‘지도’ 역할을 함</li>
</ul>
<br>

<h3 id="분류는-추상화를-위한-도구다">분류는 추상화를 위한 도구다</h3>
<ul>
<li><p><code>추상화</code>의 두 가지 차원
→ 사물 간의 공통점만 취하고 차이점은 버림
→ 필수적인 부분을 강조하기 위해 불필요한 세부사항은 무시</p>
</li>
<li><p><code>개념</code>은 구체적인 사물들 간의 공통점을 기반으로 만든 분류 체계
→ 따라서, 추상화의 두 가지 차원 중, <code>사물 간의 공통점을 취한 것에 해당</code></p>
</li>
</ul>
<br>

<hr>
<h2 id="타입">타입</h2>
<h3 id="타입은-개념이다">타입은 개념이다</h3>
<ul>
<li>개념을 좀 더 컴공스럽게 말한다면 : <code>타입</code></li>
</ul>
<blockquote>
<p><code>타입</code>의 정의</p>
<p>타입은 개념과 동일하다.</p>
<p>따라서 <code>타입</code>이란 우리가 인식하고 있는 
다양한 사물이나 객체에 적용할 수 있는 아이디어나 관념을 의미한다.</p>
<p>어떤 객체에 타입을 적용할 수 있을 때 그 객체를 타입의 <code>인스턴스</code>라고 한다.</p>
<p>타입의 인스턴스는 타입을 구성하는 외연인 객체 집합의 일원이 된다.</p>
</blockquote>
<br>

<h3 id="데이터-타입">데이터 타입</h3>
<p>타입에 관한 두 가지 조언</p>
<ul>
<li><p>타입은 데이터가 어떻게 사용되느냐에 관한 것
→ 숫자형 데이터들끼리는 사칙연산이 가능
→ 문자열 데이터들끼리는 두 문자열을 연결하거나 길이를 알 수 있음
→ 데이터의 타입을 결정하는 것은, 데이터에 적용할 수 있는 작업, 즉, <code>연산자</code> 
→ <code>데이터에 어떤 연산자를 적용할 수 있는지가 이 데이터의 타입을 결정함</code></p>
</li>
<li><p>타입에 속한 데이터를 메모리에 어떻게 표현하는지는 외부에서 철저히 감춰짐</p>
</li>
</ul>
<blockquote>
<p><code>데이터 타입</code>의 정의</p>
<p>데이터 타입은 메모리 안에 저장된 데이터의 종류를 분류하는 데 사용하는 메모리 집합에 관한 메타데이터다.
데이터에 대한 분류는 암시적으로 어떤 종류의 연산이 해당 데이터에 대해 수행될 수 있는지를 결정한다.</p>
</blockquote>
<br>

<h3 id="객체와-타입">객체와 타입</h3>
<ul>
<li>이전에 데이터 타입에 대해 설명한 이유
→ 전통적인 데이터 타입과 객체지향의 타입 사이에는 깊은 연관이 있기 때문
→ 객체지향에서 우리는 객체를 일종의 데이터처럼 사용</li>
</ul>
<br>

<p>객체에 관한 두 가지 조언</p>
<ul>
<li><p>이전에 ‘타입에 관한 두 가지 조언’과 동일</p>
</li>
<li><p>어떤 객체가 어떤 타입에 속하는지를 결정하는 것은 <code>객체가 수행하는 행동</code> 
→ 동일한 행동을 한다면, 동일한 객체로 분류 가능</p>
</li>
<li><p>객체가 내부적으로 어떻게 표현되는지는 외부에서 철저히 감춰짐
→ 객체의 타입은 내부 표현과는 일절 상관 없음</p>
</li>
</ul>
<br>

<h3 id="행동이-우선이다">행동이 우선이다</h3>
<ul>
<li><p>어떤 객체를 다른 객체와 동일한 타입으로 분류하는 기준 ?
→ 두 객체가 동일한 <code>행동</code>을 하는지
→ 동일한 상태를 갖고 있더라도, 다른 행동이라면 다른 타입
→ <code>객체의 타입을 결정하는건 객체의 행동 뿐</code></p>
</li>
<li><p>같은 타입 = 동일한 행동
→ 동일한 행동 = 동일한 책임
→ 동일한 책임 = 동일한 메시지의 수신
→ 같은 타입인 객체는, 내부의 데이터 표현 방식이 다르더라도, 동일한 메시지를 수신해 이를 처리할 수 있음
→ But, 메시지의 처리 방식은 다를 수 있음
→ <code>다형성</code></p>
</li>
<li><p>객체가 할 수 있는 행동만을 외부에 공개하고, 내부의 데이터는 행동 뒤로 감춰야 함
→ <code>캡슐화</code></p>
</li>
<li><p>객체를 원활히 분류하기 위해서는 내부의 데이터가 아니라 <code>외부의 행동</code>을 먼저 고려해야 함
1) 객체가 외부에 제공해야 하는 책임을 결정
2) 책임을 수행하는 데 적합한 데이터를 결정
3) 책임을 수행하는 데 필요한 외부 인터페이스 뒤로 데이터를 캡슐화
→ <code>책임-주도 설계</code></p>
</li>
</ul>
<br>

<hr>
<h2 id="타입의-계층">타입의 계층</h2>
<h3 id="트럼프-계층">트럼프 계층</h3>
<ul>
<li><p>정원사, 병사, 신하, 왕자, 공주 등은 정말 ‘트럼프’ 일까 ?
→ 카드게임을 할 때 트럼프와 외형은 동일하지만, 행동은 동일하지 않음
→ ‘트럼프’가 아니라 ‘트럼프 인간’이 더 정확
→ ‘트럼프 인간’ 타입은 ‘트럼프’ 타입의 객체가 할 수 있는 행동 + 걸어다니는 행동 할 수 있음
→ ‘트럼프 인간’은 ‘트럼프’보다 조금 더 특화된 행동을 함</p>
</li>
<li><p>외연의 관점에서 ‘트럼프’와 ‘트럼프 카드’를 살펴보자
→ ‘트럼프 인간’의 외연은 ‘트럼프’ 외연의 부분집합
→ ‘트럼프 인간’과 ‘트럼프’ 사이의 관계를 <code>일반화/특수화 관계</code>라고 함</p>
</li>
</ul>
<br>

<h3 id="일반화--특수화-관계">일반화 / 특수화 관계</h3>
<ul>
<li><p>일반화와 특수화는 동시에 이뤄짐
→ ‘트럼프 인간’은 ‘트럼프’를 좀 더 구체적으로 표현한 것
→ 어떤 객체가 다른 객체보다 더 구체적인 <code>상태</code>를 표현한다고 <code>일반화 / 특수화 관계가 성립하는 것은 아님</code> 
→ 한 타입이 다른 타입보다 더 구체적인 <code>행동</code>을 해야 함
→ <code>일반화 / 특수화 관계를 결정하는 것도 행동</code></p>
</li>
<li><p>내연, 외연 관점에서의 일반화 / 특수화 관계
→ 일반적인 타입의 외연은 특수한 타입의 외연보다 크다
→ 일반적인 타입의 내연의 가짓수는 특수한 타입의 내연의 가짓수보다 작다</p>
<img src="https://velog.velcdn.com/images/id_entity/post/a61b25b3-ace5-4097-aecc-aab1d288d50c/image.png" width="300">

</li>
</ul>
<br>

<h3 id="슈퍼타입과-서브타입">슈퍼타입과 서브타입</h3>
<ul>
<li><p>일반화 / 특수화 관계
→ 슈퍼타입 / 서브타입 관계
→ <code>슈퍼타입</code>: 일반적인 타입
→ <code>서브타입</code>: 특수한 타입</p>
</li>
<li><p>슈퍼타입과 서브타입의 관계는 두 타입의 <code>행동</code>에 의해 결정됨
→ <code>한 타입이 다른 타입의 서브타입이 되기 위해서는 행위적 호환성을 만족해야 함</code>
→ 어떤 타입을 다른 타입의 서브타입이라고 말할 수 있으려면 다른 타입을 대체할 수 있어야 함
→ Liskov Substitution Principle ( <code>LSP</code> )</p>
</li>
<li><p>일반화 / 특수화 관계를 표기하는 방법
→ 슈퍼타입을 상단에, 서브타입을 하단에
→ 속이 빈 삼각형 화살표가 서브타입에서 슈퍼타입을 향하도록 연결</p>
<img src="https://velog.velcdn.com/images/id_entity/post/bcfce28d-a275-4a99-9b2d-358fad74a9e2/image.png" width="200">

</li>
</ul>
<br>

<h3 id="일반화는-추상화를-위한-도구다">일반화는 추상화를 위한 도구다</h3>
<ul>
<li><p>추상화의 두 번째 차원은 <code>중요한 부분을 강조하기 위해 불필요한 세부사항을 제거해 단순화하는 것</code>
→ 앨리스가 ‘트럼프 인간’이 아니라 ‘트럼프’라고 한 이유도 이와 유사
→ ‘트럼프 인간’이 할 수 있는 구체적인 행동은 불필요해서 단순화 한 ‘트럼프’라고 생각</p>
</li>
<li><p>앨리스는 추상화의 두 가지 기법을 모두 사용함
→ 등장인물들 사이의 차이점은 배제하고 공통점만으로 ‘트럼프 인간’으로 분류함
→ ‘트럼프 인간’을 더 단순한 관점에서 바라보고 불필요한 세부 사항은 무시함으로서 ‘트럼프’로 일반화</p>
</li>
</ul>
<br>

<hr>
<h2 id="정적-모델">정적 모델</h2>
<h3 id="타입의-목적">타입의 목적</h3>
<ul>
<li><p>왜 타입을 사용하는가 ?
→ 인간의 인지 능력으로는 동적으로 변화하는 객체의 복잡성을 따라가기 어렵기 때문
→ 앨리스의 키가 아무리 변해도 앨리스는 앨리스</p>
</li>
<li><p><code>타입은 동적으로 변화하는 객체의 상태에 무관하게 정적인 모습으로 다룰 수 있게 해줌</code></p>
</li>
</ul>
<br>

<h3 id="그래서-결국-타입은-추상화다">그래서 결국 타입은 추상화다</h3>
<ul>
<li>타입을 사용함으로써 객체의 동적인 상태를 정적으로 표현할 수 있게 해줌
→ <code>결국 타입도 추상화</code></li>
</ul>
<pre><code>타입은 시간에 따른 객체의 상태 변경이라는 복잡성을 단순화할 수 있는 효과적인 방법</code></pre><br>

<h3 id="동적-모델과-정적-모델">동적 모델과 정적 모델</h3>
<ul>
<li><p><code>스냅샷</code>: 하나의 객체가 특정 시점에 구체적으로 어떤 상태를 갖는지
→ UML에서 <code>객체 다이어그램</code>이라고도 불림
→ <code>동적 모델</code>: 스냅샷처럼 객체의 변화를 포착하는 것</p>
</li>
<li><p><code>타입 모델</code>: 객체가 가질 수 있는 모든 상태와 행동을 시간에 독립적으로 표현한 것
→ <code>정적 모델</code> 이라고도 함</p>
</li>
<li><p>객체지향 애플리케이션을 잘 활용하기 위해서는 동적 모델, 정적 모델을 적절히 잘 사용해야 함
→ 클래스를 작성하는 시점에는 변화하지 않기 때문에 <code>정적 모델</code>
→ 디버깅 등 객체의 변화를 따라가는 시점에는 <code>동적 모델</code></p>
</li>
</ul>
<br>

<h3 id="클래스">클래스</h3>
<ul>
<li><p>객체지향에서 정적인 모델의 ‘타입’은 주로 <code>클래스</code>를 통해 구현됨
→ 하지만, 클래스는 타입의 다양한 구현 방법 중 하나
→ 따라서, <code>클래스와 타입은 다른 개념</code> 
→ 클래스는 타입의 구현 외에도 코드의 재사용의 용도로도 사용됨</p>
</li>
<li><p>객체를 분류하는 기준은 <code>타입</code> / 타입을 나누는 기준은 객체가 수행하는 <code>행동</code></p>
</li>
</ul>
<br>

<hr>
<p><a href="https://m.yes24.com/Goods/Detail/18249021">객체지향의 사실과 오해</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Object-Oriented] 2장. 이상한 나라의 객체]]></title>
            <link>https://velog.io/@id_entity/Object-Oriented-2%EC%9E%A5.-%EC%9D%B4%EC%83%81%ED%95%9C-%EB%82%98%EB%9D%BC%EC%9D%98-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@id_entity/Object-Oriented-2%EC%9E%A5.-%EC%9D%B4%EC%83%81%ED%95%9C-%EB%82%98%EB%9D%BC%EC%9D%98-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Sun, 03 Mar 2024 04:56:18 GMT</pubDate>
            <description><![CDATA[<h2 id="서론">서론</h2>
<blockquote>
<p>1997년 심리학자 <em>엘리자베스 스펠크</em>와 <em>필립 켈만</em>은 
어린 아기들이 물체를 인지하는 방법을 연구하기 위해 한 가지 실험을 수행</p>
<p>그 결과, <code>사람</code>은 태어난 지 얼마 안 된 시기부터 
뚜렷한 경계를 가지고 함께 행동하는 물체를 하나의 개념으로 인지함</p>
</blockquote>
<br>

<h3 id=""></h3>
<hr>
<h2 id="객체지향과-인지-능력">객체지향과 인지 능력</h2>
<p>위 실험에서와 같이, 사람은 기본적으로 뚜렷한 경계를 가지고 함께 행동하는 물체를 하나의 개념으로 인지</p>
<br>

<h3 id="-1"></h3>
<hr>
<h2 id="객체-그리고-이상한-나라">객체, 그리고 이상한 나라</h2>
<p>이상한 나라의 앨리스에서 앨리스가 정원으로 통하는 문을 통과하기 위해
음료, 부채, 버섯 등을 사용해 키가 변하는 것으로 비유 중</p>
<h3 id="앨리스-객체">앨리스 객체</h3>
<p>음료, 부채, 버섯 등을 사용하는 <code>행동</code>에 따라 앨리스의 키라는 <code>상태</code>가 변경됨</p>
<blockquote>
<p>이런 점에서,</p>
<ul>
<li>앨리스는 상태를 가지며, 상태는 변경 가능하다</li>
<li>앨리스의 상태를 변경시키는 것은 앨리스의 행동이다<ul>
<li>행동의 결과는 상태에 의존적이며, 상태를 이용해 서술할 수 있다</li>
<li>행동의 순서가 결과에 영향을 미친다</li>
</ul>
</li>
<li>앨리스는 어떤 상태에 있더라도 유일하게 식별 가능하다</li>
</ul>
</blockquote>
<br>

<h3 id="-2"></h3>
<hr>
<h2 id="객체-그리고-소프트웨어-나라">객체, 그리고 소프트웨어 나라</h2>
<p>객체를 효과적으로 설명하기 위해서는 <code>상태</code>, <code>행동</code>, <code>식별자</code>를 지닌 실체로 보는 것이 가장 효과적</p>
<blockquote>
<p>이 책에서 <code>객체</code>의 정의는,</p>
<p>객체란 식별 가능한 개체 또는 사물이다.
객체는 자동차처럼 만질 수 있는 구체적인 사물일 수도 있고, 시간처럼 추상적인 개념일 수도 있다.
객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가진다.
소프트웨어 안에서 객체는 저장된 상태와 실행 가능한 코드를 통해 구현된다.</p>
</blockquote>
<br>

<h3 id="상태">상태</h3>
<p>상태가 왜 필요할까 ?</p>
<ul>
<li>어떤 <code>행동</code>의 결과는 그 이전 행동에 대한 결과에 의해 결정됨
→ 하지만, 그 이전의 행동들을 모둘 기억하기에는 비효율적
→ 이전 행동에 대한 결과를 <code>상태</code>로 저장해두고, 현재 상태에 어떤 행동을 가해 새로운 <code>상태</code>로 갱신
⇒ <code>즉, 상태가 있으면, 이전에 실행한 행동들을 모두 기억해두지 않아도 됨</code></li>
</ul>
<br>

<p>상태와 프로퍼티</p>
<ul>
<li>&lt;이상한 나라의 앨리스&gt;에서, ‘앨리스’, ‘토끼’, ‘문’ 등은 객체로 생각할 수 있음 
→ 뚜렷한 경계를 갖고, 식별 가능하며, 상태와 행동을 갖기 때문</li>
<li>하지만, 앨리스의 ‘키’나 ‘위치’는 객체가 아님 
→ 스스로 독립적인 의미보다는, 다른 것의 특성을 표현하기 위한 수단으로 쓰이기 때문 
→ <strong><code>프로퍼티는 객체의 특성을 표현할 수 있음</code></strong></li>
<li>객체를 사용해 다른 객체의 상태를 표현할 때도 있음 
→ ‘앨리스가 음료를 들고 있음’이라는 상태는 ‘앨리스’ - ‘음료’ 사이의 연결로 표현할 수 있음 
→ <strong><code>객체도 객체의 특성을 표현할 수 있음</code></strong></li>
</ul>
<br>

<pre><code>따라서, `모든 객체는 단순한 값과 객체의 조합으로 표현할 수 있다`
이 때, 객체의 상태를 구성하는 모든 특징을 `프로퍼티`라고 한다</code></pre><br>

<p>앨리스’가 ‘음료’를 마시기 위해 들고 있는 상황</p>
<ul>
<li>‘앨리스’와 ‘음료’ 모두 객체로 판단할 수 있음 
→ 앨리스와 음료 모두 서로의 상태에 영향을 줌
→ 앨리스가 음료를 들고 있는 상태에서만 가능
→ 객체들 사이의 링크를 통해서만 메시지를 주고받을 수 있음 
→ ‘앨리스’와 ‘음료’가 상호작용을 하려면 ‘들고 있다’라는 <strong>링크</strong>가 있어야 함 
→ <code>즉, 객체가 다른 객체의 상태를 표현하고 있을 때에는, 링크가 필요하다</code></li>
<li>‘엘리스’의 ‘키’에 따라서 문을 지나갈 수 있는지 없는지 결정됨 
→ <code>앨리스의 키처럼 객체를 구성하는 단순한 값을 속성이라고 함</code></li>
</ul>
<br>

<pre><code>💡 프로퍼티는 단순한 값인 속성과 다른 객체를 가리키는 링크라는 두 가지 종류의 조합으로 표현</code></pre><br>

<blockquote>
<p>이 책에서 <code>객체의 상태</code> 정의</p>
<p>상태는 특정 시점에 객체가 가지고 있는 정보의 집합으로 객체의 구조적 특징을 표현한다. 
객체의 상태는 객체에 존재하는 정적인 프로퍼티와 동적인 프로퍼티 값으로 구성된다. 
객체의 프로퍼티는 단순한 값과 다른 객체를 참조하는 링크로 구분할 수 있다.</p>
</blockquote>
<br>

<p>객체의 자율성</p>
<ul>
<li>객체는 다른 객체의 상태에 직접적으로 접근하고, 변경할 수 없음
→ 자기 자신만이 자신의 상태를 책임짐
→ 다른 객체가 특정 객체에 링크를 통해 메시지를 보낼 수는 있음
→ 하지만, 그 메시지를 통해 특정 행동을 할지 말지는 스스로가 결정
→ <code>객체는 스스로의 행동에 의해서만 상태가 변경됨을 보장하여 자율성을 유지</code></li>
</ul>
<br>

<h3 id="행동">행동</h3>
<p>상태와 행동</p>
<ul>
<li>객체의 상태를 변경하는 것은 객체의 자발적인 행동 뿐
→ 이렇게 객체의 상태를 변경하는 행동은 <code>부수 효과</code>를 갖고 있다고 함</li>
<li>객체의 행동은 객체의 상태를 변경시키지만, 객체의 행동에 대한 결과는 객체의 상태에 의존적</li>
</ul>
<pre><code>- 객체의 행동은 상태에 영향을 받음
- 객체의 행동은 상태를 변경시킴</code></pre><br>

<p>협력과 행동</p>
<ul>
<li>객체와 객체가 협력하는 유일한 방법은 다른 객체에게 요청을 보내는 것
→ 요청을 받은 객체는 이를 수행하기 위해 특정 행동을 함
→ <code>행동이 객체들끼리 협력할 수 있는 유일한 수단</code></li>
<li>객체의 협력 과정에서 스스로의 상태 뿐 아니라, 다른 객체의 상태 변경을 유발할 수도 있음
→ 앨리스가 음료를 마셔서 자신의 키도 줄어들지만, 음료의 양도 줄어듦</li>
</ul>
<br>

<pre><code>객체의 행동으로 인해 발생하는 결과의 두 관점
- 객체 자기 자신의 상태 변경
- 행동에 협력하는 다른 객체에게 메시지 전송
</code></pre><blockquote>
<p>이 책에서 <code>객체의 행동</code> 정의</p>
<p>행동이란 외부의 요청 또는 수신된 메시지에 응답하기 위해 동작하고 반응하는 활동이다.
행동의 결과로 객체는 자신의 상태를 변경하거나 다른 객체에게 메시지를 전달할 수 있다.
객체는 행동을 통해 다른 객체와의 협력에 참여하므로 행동은 외부에 가시적이어야 한다.</p>
</blockquote>
<br>

<p>상태 캡슐화</p>
<ul>
<li>앨리스가 음료를 마심
→ <code>앨리스.drinkBeverage()</code>
→ 음료에게 <code>drunken(quantity)</code> 라는 메시지가 전달됨
→ 두 행동 모두, 송신자는 수신자의 상태에 대해 변경이 있는지 없는지 모름
→ <code>캡슐화</code> 
→ <code>객체는 캡슐 안에 상태를 감추어 외부에 노출하지 않음</code>
→ 외부에 노출되는 것은 <code>행동</code> 뿐, 외부에서 접근할 수 있는 방법도 <code>행동</code> 뿐</li>
<li>객체의 행동을 유발하는 것은 외부로부터의 메시지, 하지만 상태를 변경할지 말지는 객체 스스로가 결정
→ 외부에서는 메시지 수신자의 상태가 변경되는지 아닌지 알지 못함
→ 메시지 송신자는 수신자에게 어떤 간섭도 가하지 못함</li>
<li><code>캡슐화를 통해, 객체의 자율성을 높이고, 협력을 단순하고 유연하게 만듦</code></li>
</ul>
<br>

<h3 id="식별자">식별자</h3>
<ul>
<li>객체가 식별자를 갖는다 = 객체를 서로 구별할 수 있는 특정한 프로퍼티가 객체 안에 존재함
→ 모든 객체는 식별자를 가지며, 이 식별자로 객체들을 구별할 수 있음</li>
<li>단순한 값은 식별자를 갖지 않음
→ 1이라는 숫자가 둘 있을 때, 두 개를 굳이 식별하지 않으려고 하는 것과 비슷한 맥락</li>
<li><code>값(value)</code>은 변하지 않는 양을 모델링함
→ 값은 상태가 바뀌지 않기 때문에, <code>불변 상태</code>를 가진다고 할 수 있음
→ 값은 상태가 변하지 않기 때문에, 상태를 비교해서 동일한지 판단할 수 있음
→ 이런 성질을 <code>동등성</code>이라고 함</li>
<li><code>객체</code>는 시간에 따라 상태의 변동이 있을 수 있음
→ 객체는 상태가 바뀌기 때문에, <code>가변 상태</code>를 가진다고 할 수 있음
→ 타입이 같은 두 객체의 상태가 모두 같더라도, 두 객체는 다른 객체로 판단함
→ 객체는 상태와 무관하게, 식별자로 동일한 객체인지 아닌지 판단
→ 이런 성질을 <code>동일성</code>이라 함</li>
<li>우리는 단순 숫자 1, 1 두 가지를 동일한 값이라고 생각하는 것 → <code>동등성</code> 맥락
키가 180cm인 움파, 룸파 두 명을 키는 같더라도 다른 사람이라 생각하는 것 → <code>동일성</code> 맥락</li>
</ul>
<blockquote>
<p>식별자란 어떤 객체와 구분하는 데 사용하는 객체의 프로퍼티이다.
값은 식별자를 가지지 않기 때문에  상태를 이용한 동등성 검사를 통해 두 인스턴스를 비교해야 한다.
객체는 상태가 변경될 수 있기 때문에 식별자를 이용한 동일성 검사를 통해 비교한다.</p>
</blockquote>
<pre><code>💡 객체의 특성

- 객체는 상태를 가지며 상태는 변경 가능하다.
- 객체의 상태를 변경시키는 것은 객체의 행동이다.
- 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다.
- 행동의 순서가 실행 결과에 영향을 미친다.
- 객체는 어떤 상태에 있더라도 유일하게 식별 가능하다.</code></pre><br>

<h3 id="-3"></h3>
<hr>
<h2 id="기계로서의-객체">기계로서의 객체</h2>
<ul>
<li><code>쿼리</code>: 객체의 상태를 조회하는 작업</li>
<li><code>명령</code>: 객체의 상태를 변경하는 작업</li>
</ul>
<p>기계로서의 객체</p>
<img src="https://velog.velcdn.com/images/id_entity/post/fb226a23-0a78-4116-9b80-999e3d3bc81b/image.png" width="400">


<ul>
<li>기계는 뜯어보지 않는 한, 내부에 있는 요소들을 확인할 수 없음
→ 객체를 이런 기계에 비유해서 생각</li>
<li><code>원형 버튼</code>을 통해서 기계의 상태를 조회할 수 있음 → <code>쿼리</code></li>
<li><code>사각형 버튼</code>을 통해서 기계의 상태를 변경할 수 있음 → <code>명령</code></li>
<li>객체에 접근할 수 있는 방법은 객체가 제공하는 동작 뿐이라는 것을 보여줌</li>
<li>두 개의 동일하게 동작하는 기계가 있다고 해도, 다른 기계로 인지
→ 식별자를 설명할 수 있음</li>
<li>두 개의 기계가 ‘링크’되어 있어야 서로 메시지를 보내며 협력할 수 있음
→ 객체 간의 협력 관계도 설명 가능</li>
</ul>
<br>

<h3 id="-4"></h3>
<hr>
<h2 id="행동이-상태를-결정한다">행동이 상태를 결정한다</h2>
<ul>
<li><p>객체지향의 입문자는 상태를 중심으로 객체를 바라봄</p>
</li>
<li><p>하지만, <code>상태를 먼저 결정하고, 행동을 나중에 결정하는 것은 설계에 나쁜 영향을 끼침</code></p>
<ul>
<li>상태를 먼저 결정할 경우 캡슐화에 저해됨</li>
<li>객체를 협력자가 아닌 고립된 섬으로 만듬
→ 객체가 필요한 이유는 애플리게이션 문맥 내에서 다른 객체와 <code>협력하기 위함</code></li>
<li>객체의 재사용성이 저하됨
→ 상태에 초점을 맞추게 된다면 다양한 협력에 참여하기 어려워짐</li>
</ul>
</li>
<li><p>협력에 참여하는 객체를 잘 만들기 위해서는 <code>행동</code>에 초점을 맞춰야 함</p>
</li>
<li><p>객체지향 설계는 애플리케이션에 필요한 <code>협력</code>을 먼저 생각
→ 협력에 참여하는 데에 필요한 <code>행동</code>을 생각
→ 행동을 수행할 <code>객체</code>를 선택
→ 행동에 필요한 정보가 무엇인지 고려하여 <code>상태</code>를 결정</p>
</li>
<li><p>협력 안에서 객체의 행동은 객체의 책임을 의미함
→ 객체가 어떤 책임이 필요한지부터 생각해야 함
→ <code>책임-주도 설계 ( Responsibility-Driven Design, RDD )</code></p>
</li>
</ul>
<br>

<hr>
<p><a href="https://m.yes24.com/Goods/Detail/18249021">객체지향의 사실과 오해</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Object-Oriented] 1장. 협력하는 객체들의 공동체]]></title>
            <link>https://velog.io/@id_entity/Object-Oriented-1%EC%9E%A5.-%ED%98%91%EB%A0%A5%ED%95%98%EB%8A%94-%EA%B0%9D%EC%B2%B4%EB%93%A4%EC%9D%98-%EA%B3%B5%EB%8F%99%EC%B2%B4</link>
            <guid>https://velog.io/@id_entity/Object-Oriented-1%EC%9E%A5.-%ED%98%91%EB%A0%A5%ED%95%98%EB%8A%94-%EA%B0%9D%EC%B2%B4%EB%93%A4%EC%9D%98-%EA%B3%B5%EB%8F%99%EC%B2%B4</guid>
            <pubDate>Fri, 23 Feb 2024 07:20:06 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="서론">서론</h2>
<blockquote>
<p>“객체지향 소프트웨어는 <code>실세계의 투영</code>이며, 객체란 현실 세계에 존재하는 <code>사물에 대한 추상화</code>이다.”</p>
<p>하지만, 막상 찾아보면, 애플리케이션을 개발하며 실세계에 직접적으로 대응되는 사물을 발견하긴 힘들다.
즉, <em>소프트웨어 방화벽</em>과, <em>실세계의 방화벽</em>의 의미적 거리만큼, 소프트웨어와 실세계 사이에는 어느정도의 의미적 저리가 존재한다</p>
<p>하지만, <code>실세계의 모방</code>이라는 객체지향의 개념은 실무적인 관점에서는 부적합하지만,
객체지향의 기본 사상을 이해하고 학습하기에는 효과적이다</p>
</blockquote>
<h3 id=""></h3>
<hr>
<h2 id="협력하는-사람들">협력하는 사람들</h2>
<p><code>손님</code></p>
<ul>
<li>커피를 마시고 싶어서 커피를 캐시어에게 주문함</li>
</ul>
<p><code>캐시어</code></p>
<ul>
<li>직장인에게 받은 커피 주문을 바리스타에게 전달함</li>
</ul>
<p><code>바리스타</code></p>
<ul>
<li>캐시어에게 받은 커피를 자기 나름대로의 방법으로 제작함</li>
</ul>
<p>‘커피 주문’이라는 <strong>협력</strong>에 참여하는 <code>손님</code>, <code>캐시어</code>, <code>바리스타</code>는
주문된 커피가 손님에게 정확히 전달될 수 있도록 맡은 바 <strong>역할</strong>과 <strong>책임</strong>을 다하고 있음</p>
<p>이 역할, 책임, 협력이 객체지향의 핵심적인 3가지 요소</p>
<h3 id="요청과-응답으로-구성된-협력">요청과 응답으로 구성된 협력</h3>
<p>사람들은 스스로 해결하지 못하는 문제를 마주치면 이를 해결할 수 있는 사람에게 도움을 <code>요청(request)</code>한다</p>
<ul>
<li><code>손님</code> → <code>캐시어</code> : 커피를 주문</li>
<li><code>캐시어</code> → <code>바리스타</code> : 커피를 제조하라</li>
</ul>
<p>요청을 받은 사람은 주어진 책임을 다해 필요한 지식이나 서비스를 제공, 즉, <code>응답(response)</code>한다</p>
<ul>
<li><code>바리스타</code> → <code>캐시어</code> : 커피 완성</li>
<li><code>캐시어</code> → <code>손님</code> : 커피 완성</li>
</ul>
<h3 id="역할과-책임">역할과 책임</h3>
<p>사람들은 다른 사람과 협력하는 과정에서 특정한 <code>역할</code>을 부여받음</p>
<ul>
<li><code>손님</code> : 커피를 주문하는 역할</li>
<li><code>캐시어</code> : 손님으로부터 커피를 주문받아야 함</li>
<li><code>바리스타</code> : 주문된 커피를 제조해야 할 <code>책임</code>이 있음</li>
</ul>
<p>즉, 역할에는 책임이 내포되어 있음</p>
<p>사람들이 협력을 위해 특정한 역할을 맡고 적합한 책임을 수행한다는 사실은 몇 가지 중요한 개념을 제시</p>
<ul>
<li>여러 사람이 동일한 역할을 수행할 수 있다
(캐시어가 일을 그만둔다면, 다른 캐시어를 고용하면 됨)</li>
<li>역할은 대체 가능성을 의미한다
(손님 입장에서 커피를 받기 위해 어떤 캐시어에게 주문하든 상관 없음)</li>
<li>책임을 수행하는 방법은 자율적으로 선택할 수 있다
(바리스타가 커피를 핸드드립으로 내릴지, 커피머신으로 내릴지는 자율적으로 선택 가능)</li>
<li>한 사람이 동시에 여러 역할을 수행할 수 있다
(1인 카페와 같은 경우, 캐시어가 바리스타의 역할을 함께 수행할 수 있음)</li>
</ul>
<h3 id="-1"></h3>
<hr>
<h2 id="역할-책임-협력">역할, 책임, 협력</h2>
<h3 id="기능을-구현하기-위해-협력하는-객체들">기능을 구현하기 위해 협력하는 객체들</h3>
<p>커피를 주문하고 제작해서 손님에게 전달하는 과정을 객체지향으로 돌려보자면,</p>
<p><code>사람</code> = <code>객체</code></p>
<p><code>요청</code> = <code>메시지</code></p>
<p><code>처리하는 방법</code> = <code>메서드</code></p>
<h3 id="역할과-책임을-수행하며-협력하는-객체들">역할과 책임을 수행하며 협력하는 객체들</h3>
<blockquote>
<p>아리스토텔레스 왈 … “인간은 사회적 동물이다”</p>
</blockquote>
<p>→ 하나의 <code>목표</code>를 이루기 위해 <code>사람들</code>이 <code>협력</code>한다
→ 하나의 목표에는 더 작은 <code>책임</code>으로 분할된다
→ 각 책임은 책임을 수행할 수 있는 적절한 역할을 가진 사람에 의해 수행된다
→ 협력에 참여하는 개인은 책임을 수행하기 위해 다른 사람에게 <code>도움을 요청</code>하기도 한다
→ 이런 연쇄적인 요청과 응답으로 구성되는 <code>협력 관계</code>가 완성된다</p>
<p>→ 하나의 <code>어플리케이션</code>을 위해 <code>여러 객체</code>가 <code>협력</code>한다
→ 하나의 어플리케이션은 더 작은 <code>책임</code>으로 분할된다
→ 각 책임은 책임을 수행할 수 있는 적절한 역할을 가진 <code>객체</code>에 의해 수행된다
→ 협력에 참여하는 객체는 책임을 수행하기 위해 다른 객체에 <code>도움을 요청</code>하기도 한다
→ 이런 연쇄적인 요청과 응답으로 구성되는 <code>협력 관계</code>가 완성된다</p>
<p>즉, 객체지향 설계는 적절한 객체에게 적절한 책임을 할당하는 것에서 시작되고,
이 책임은 객체지향 설계의 품질을 결정하는 가장 중요한 요소</p>
<p>따라서, 얼마나 적절한 책임을 선택하느냐가 어플리케이션의 아름다움을 결정</p>
<p>‘역할’은 관련성 높은 ‘책임’의 집합
객체의 ‘역할’은 다음과 같은 특징을 지님</p>
<ul>
<li>여러 객체가 동일한 역할을 수행할 수 있다</li>
<li>역할은 대체 가능성을 의미한다</li>
<li>각 객체는 책임을 수행하는 방법을 자율적으로 선택할 수 있다</li>
<li>하나의 객체가 동시에 여러 역할을 수행할 수 있다</li>
</ul>
<p>&lt;협력하는 사람들&gt;에서와 동일한 내용인걸로 보아
객체지향을 이해하기 위해, 실세계의 모방은 아주 뛰어난 방법 !</p>
<h3 id="-2"></h3>
<hr>
<h2 id="협력-속에-사는-객체">협력 속에 사는 객체</h2>
<p>객체지향의 윤곽은 역할, 책임, 협력이지만, 이 협력에 참여하는 주체는 <code>객체</code></p>
<p>어플리케이션의 핵심을 차지하는 객체가 가져야 할 두 가지 덕목</p>
<ul>
<li>협력적이어야 함
→ 다른 객체의 <code>요청</code>에 <code>응답</code>할지 말지, 응답한다면, <code>어떤 방식</code>으로 응답할지, 객체 스스로 결정</li>
<li>자율적이어야 함
→ ‘자기 스스로의 원칙에 따라 어떤 일을 하거나 자기 스스로를 통제하여 절제하는 것’</li>
</ul>
<p>객체지향 설계의 묘미는 위 두 가지 덕목을 지키는 객체들의 공동체를 설계하는 데에 있음</p>
<h3 id="상태와-행동을-함께-지닌-자율적인-객체">상태와 행동을 함께 지닌 자율적인 객체</h3>
<p>객체는 <code>상태</code> 와 <code>행동</code> 을 함께 지닌 실체라고 정의함</p>
<p>즉, 객체가 협력에 참여하기 위해 어떤 행동을 한다면, 
그 행동을 하는 데 필요한 상태도 함께 지니고 있어야 함</p>
<p>객체가 협력에 참여하는 과정에서 스스로 판단하고 결정하는 자율적인 존재이기 위해</p>
<p><code>객체의 자율성</code>은 객체의 <code>외부</code>와 <code>내부</code>를 명확하게 구분하는 데에서 결정됨</p>
<ul>
<li>객체의 내부는 스스로 관리하고 외부에서 간섭할 수 없도록 차단해야 함</li>
<li>객체의 외부에서는 접근이 허락된 수단을 통해서만 의사소통 해야 함</li>
</ul>
<p>즉, 객체는 다른 객체가 ‘무엇’을 수행하는지는 알 수 있지만, ‘어떻게’ 수행하는지는 알 수 없어야 함</p>
<h3 id="협력과-메시지">협력과 메시지</h3>
<p>현실세계에서는 사람들 간의 의사소통 방식이 다양함
하지만, 객체지향에서 객체들 간의 유일한 의사소통 방법은 <code>메시지</code></p>
<p>즉, 객체들은 메시지를 <code>송신</code>, <code>수신</code>하며 협력해 나가는 존재들</p>
<ul>
<li><code>송신자</code> : 메시지를 전송하는 객체</li>
<li><code>수신자</code> : 메시지를 수신하는 객체</li>
</ul>
<h3 id="메서드와-자율성">메서드와 자율성</h3>
<p>객체는 다른 객체에게 요청하기 위해 메시지를 전송
수신자 객체는 처리 여부에 대해 판단한 후, 자신만의 방법으로 자율적으로 처리</p>
<p>이 때 처리하는 방법을 <code>메서드</code> 라고 함</p>
<p>그리고, <code>메시지</code>와, 메시지의 요청을 처리하기 위한 <code>메서드</code>를 분리하는 것이 객체의 자율성을 높이는 핵심 메커니즘</p>
<h3 id="-3"></h3>
<hr>
<h2 id="객체지향의-본질">객체지향의 본질</h2>
<p>불완전하고 부정확하긴 하지만, 나름의 객체지향의 개념을 포괄하는 내용들</p>
<ul>
<li>객체지향이란 시스템을 상호작용하는 <strong>자율적인 객체들의 공통체</strong>로 바라보고, 객체를 이용해 시스템을 분할하는 방법이다</li>
<li>자율적인 객체란 <strong>상태</strong>와 <strong>행위</strong>를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다</li>
<li>객체는 시스템의 행위를 구현하기 위해 다른 객체와 <strong>협력</strong>하고, 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다</li>
<li>객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다</li>
</ul>
<h3 id="객체를-지향하라">객체를 지향하라</h3>
<p>객체지향에서 핵심은 ‘클래스’가 아니라, 
적절한 책임을 수행한느 역할 간의 유연하고 견고한 협력 관계를 구축하는 것이다</p>
<hr>
<p><a href="https://m.yes24.com/Goods/Detail/18249021">객체지향의 사실과 오해</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기본에 집중하자] Class Diagram 읽기]]></title>
            <link>https://velog.io/@id_entity/tam4ep1j</link>
            <guid>https://velog.io/@id_entity/tam4ep1j</guid>
            <pubDate>Wed, 21 Feb 2024 08:02:06 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="class-diagram의-구성">Class Diagram의 구성</h2>
<p>Class Diagram에는 다양한 요소들이 있음</p>
<ul>
<li>class</li>
<li>protocol</li>
<li>properties</li>
<li>methods</li>
<li>relationships</li>
</ul>
<img src="https://velog.velcdn.com/images/id_entity/post/f77feb30-a323-4a76-bea0-6582d29aa1e1/image.png" width="300">


<p>상자는 <code>Class</code>를 의미함</p>
<img src="https://velog.velcdn.com/images/id_entity/post/5bf09fca-6fb7-4735-87f2-8018f9aa469d/image.png" width="100">

<p><code>open arrowhead</code>는 <code>상속</code>을 의미</p>
<p><code>inherits from</code> 으로 읽기보다,
<code>is a</code> 로 읽기</p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/83ac20d255714012ccf3aadeb8035f3e3432e09470821c3f7d7edbb6712b6b61/original.png" width="300">

<p><code>Sheep Dog</code> <code>is a</code> <code>Dog</code></p>
<hr>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/9d7f3a02942bb8391b65cf3a9c295d07dfa2276f6ae996d2d39bc124d422c262/original.png" width="150">

<p><code>Property</code> 를 의미할 때에는 <code>plain arrowhead</code> 사용</p>
<p><code>has a</code> 로 읽으면 됨</p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/25c6342e5f39edfb74562749159d39db3978105692a0254cb4bf2e9201d23abb/original.png" width="300">


<p><code>Farmer</code> <code>has a</code> <code>Dog</code></p>
<p>Class Diagram에서는 class가 복수이더라도, 항상 단수로 작성해야 함</p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/70ff24a70fe2fa2e64b934cf9740e3adc81c17453fbcb6e0881dc8238f544a44/original.png" width="300">

<p><code>Farmer</code> 가 여러 마리의 <code>Dog</code>를 <code>has a</code> 하고 있는데도,
<code>Dogs</code>라고 쓰지 않고, <code>Dog</code>라고 작성</p>
<hr>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/cda0584400e5b205e42c9f94c71e625b77d05f15b8e3e307ebd60d1b9326c918/original.png" width="300">

<p><code>Protocol</code>은 위에 <code>&lt;&lt;protocol&gt;&gt;</code> 로 작성</p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/e8af0893e9b5f42d09dbeec150a2279bb5eb32b1660852f796c1bd073cae137a/original.png" width="100">

<p><code>Open arrowhead</code>에 <code>dashed line</code> 이면,
프로토콜을 따른다는 의미</p>
<p><code>implements</code> 혹은 <code>conforms to</code> 라고 읽음</p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/3f0e3ca39fbf8e410c9113ff2c1a81a11fc728617a70695f98de355cf0f07ae6/original.png" width="300">

<p><code>Farmer</code> <code>conforms to</code> <code>PetOwning</code></p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/2e5fcba403de02380a443448d1622033a7659b8f8dde887e5f186dcf67a3b004/original.png" width="200">

<p><code>Plain arrowhead</code>에 <code>dashed line</code> 사용해 의존성을 표시함</p>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/53d7ee8fd9ad94c983d6864ee4b6e3020c4ce91bd253b99a6d8e4e6b3e40515e/original.png" width="500">

<p>Delegate를 이처럼 표시 가능</p>
<p><code>dashed line</code> 으로 여러가지를 표현할 수 있음</p>
<ul>
<li>weak property</li>
<li>delegate</li>
<li>프로퍼티로 저장되지는 않지만, method에 전달된 객체</li>
<li>약한 연결이나 callback</li>
</ul>
<img src="https://assets.alexandria.raywenderlich.com/books/des/images/e017e8545b036a3da35d5e1bc36b422ad0efe777fa8596528313b387a564e494/original.png" width="300">

<p><code>프로퍼티나 메소드</code>도 Class diagram으로 표현 가능</p>
<hr>
<h2 id="key-points">Key Points</h2>
<ul>
<li>Class diagram은 클래스와 프로토콜의 관계와, 이들이 갖는 프로퍼티, 메소드를 시각적으로 나타냄</li>
<li>Class diagram은 Object 사이에서의 관계도도 나타냄</li>
<li>상자는 프로토콜을 나타낼 수도 있고, 그러기 위해서는 <code>&lt;&lt;protocol&gt;&gt;</code> 로 표기해둔다</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Clean Architecture] 1. 소개]]></title>
            <link>https://velog.io/@id_entity/Clean-Architecture-1.-%EC%84%A4%EA%B3%84%EC%99%80-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%9E%80</link>
            <guid>https://velog.io/@id_entity/Clean-Architecture-1.-%EC%84%A4%EA%B3%84%EC%99%80-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%9E%80</guid>
            <pubDate>Sat, 27 Jan 2024 01:32:01 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="설계와-아키텍쳐란-">설계와 아키텍쳐란 ?</h2>
<ul>
<li><p>결론은 <code>아키텍쳐</code>와 <code>설계</code>는 아무 차이가 없음</p>
<ul>
<li><code>아키텍쳐</code> 는 저수준의 세부사항과는 분리된 고수준의 무언가를 가리킬 때 사용
e.g. 집의 형태, 외관, 입면도, 공간, 방의 배치 등</li>
<li><code>설계</code>는 저수준의 구조 또는 결정사항 등을 의미할 때
e.g. 콘센트, 전등 스위치, 전등의 위치 등</li>
</ul>
</li>
<li><p><strong>Software Architecture 의 목표</strong></p>
<ul>
<li>필요한 시스템을 만들고 유지보수하는 데 투입되는 비용을 최소화</li>
</ul>
</li>
<li><p>토끼와 거북이’에서 토끼는 자신의 능력을 과신하고 잠을 자버림</p>
<ul>
<li>이와 유사하게, 개발자도 자신의 능력을 믿고 나중에 코드를 고친다든, 
유지보수보다 기능 출시가 우선이라는 등의 과신이 있는데, 
이런 상태로는 엉망진창인, 유지보수가 전혀 되지 않는, 생산성이 떨어지는 코드가 되버림</li>
<li>애초부터 이런 마음가짐을 고치지 않으면 재설계한다 하더라도 같은 실수를 반복하고,
스스로에 대한 과신을 버린 후, 올바른 아키텍쳐를 적용해야지
생산성이 높은, 유지보수 가능한 코드를 작성할 수 있다.</li>
</ul>
</li>
</ul>
<br>

<h2 id="두-가지-가치에-대한-이야기">두 가지 가치에 대한 이야기</h2>
<ul>
<li><p>소프트웨어 시스템은 서로 다른 두 가지 가치를 제공함
→ <code>행위</code>(behavior)와 <code>구조</code>(structure)</p>
</li>
<li><p><code>행위</code></p>
<ul>
<li>기계의 수익 창출 / 비용의 절약</li>
</ul>
</li>
<li><p><code>아키텍쳐</code></p>
<ul>
<li>Soft(부드러운) ware(제품) 이라는 뜻에서 알 수 있듯, 기계의 행위를 쉽게 변경할 수 있음
→ 즉, 소프트웨어는 반드시 부드러워야 함 / 변경하기 쉬워야 함</li>
<li>변경에 드는 어려움은 변경의 범위에만 비례해야 하고, 변경의 형태와는 관련이 없어야 함</li>
</ul>
</li>
<li><p><strong>아이젠하워 매트릭스</strong></p>
</li>
</ul>
<pre><code>| 중요함 &amp; 긴급함 | 중요함 &amp; 긴급하지 않음 |
| --- | --- |
| 중요하지 않음 &amp; 긴급함 | 중요하지 않음 &amp; 긴급하지 않음 |

`행위` 는 긴급하지만 중요하지 않고
`아키텍쳐` 는 긴급하지 않지만 중요함

해당 분류에 대한 우선순위는 아래와 같음

1. 긴급하고 중요함
2. 긴급하지는 않지만 중요한
3. 긴급하지만 중요하지 않은
4. 긴급하지도 중요하지도 않은</code></pre><p>  하지만, 때때로 3.을 최우선순위로 격상시키는 경우가 발생
    → 이런 때에 중요도가 높은 <code>아키텍쳐</code>가 무시되고 중요도가 낮은 <code>기능</code>을 선택하게 됨</p>
<br>

<h2 id="한-줄-요약">한 줄 요약</h2>
<aside>
💡 아키텍쳐가 후순위가 되면 시스템을 개발하는 비용이 더 많이 들고,
일부 또는 전체 시스템에 변경을 가하는 일이 현실적으로 불가능해진다.

</aside>]]></description>
        </item>
        <item>
            <title><![CDATA[[기본에 집중하자] SOLID - Dependency Inversion Principle]]></title>
            <link>https://velog.io/@id_entity/%EA%B8%B0%EB%B3%B8%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EC%9E%90-SOLID-Dependency-Inversion-Principle-55le78kx</link>
            <guid>https://velog.io/@id_entity/%EA%B8%B0%EB%B3%B8%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EC%9E%90-SOLID-Dependency-Inversion-Principle-55le78kx</guid>
            <pubDate>Wed, 17 Jan 2024 07:07:48 GMT</pubDate>
            <description><![CDATA[<h2 id="definition">Definition</h2>
<blockquote>
<p><em>High level modules should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.</em></p>
<p>상위 모듈은 하위 모듈에 의존에서는 안되고, 상위, 하위 모듈 모두 ‘추상’을 의존해야 한다
’추상’은 ‘디테일’을 의존하면 안되고, ‘디테일’은 ‘추상’에 의존해야 함</p>
</blockquote>
<br>

<h2 id="좋지-않은-디자인">좋지 않은 디자인</h2>
<p><code>‘좋은’</code> 디자인, <code>‘좋지 않은’</code> 디자인의 기준은 없지만,
<code>’좋지 않은’</code> 디자인이 갖는 특징들이 있음</p>
<h3 id="rigidity">Rigidity</h3>
<blockquote>
<p>변경을 주기 어려움, 한 곳을 바꾸면 다른 부분을 망가트림</p>
<ul>
<li>OCP를 지키지 않았을 때
어떤 부분에 확장이 필요할 때, 다른 부분도 변경해야 함</li>
<li>어떤 구조가 <code>‘추상’</code>이 아닌 다른 구조에 의존할 때</li>
</ul>
</blockquote>
<h3 id="fragility">Fragility</h3>
<blockquote>
<p>한 곳에서 변경을 주면 다른 부분도 변경해야 함</p>
<ul>
<li>OCP가 지켜지지 않았을 때</li>
<li>어떤 구조가 <code>‘추상’</code>이 아닌 다른 구조에 의존할 때</li>
</ul>
</blockquote>
<h3 id="immobility-or-coupling">Immobility or Coupling</h3>
<blockquote>
<p>여기저기 연결되어있기 때문에 재사용이 어려움</p>
<ul>
<li>어떤 구조가 <code>‘추상’</code>이 아닌 다른 구조에 의존할 때</li>
</ul>
</blockquote>
<p>이런 이유들 때문에, DIP가 좋은 디자인에 직접적으로 영향을 미침</p>
<br>

<h2 id="다른-solid와의-관계">다른 SOLID와의 관계</h2>
<p>OCP와 LSP에서의 해결책은 모두 <code>Abstraction</code>
즉, DIP를 사용했을 때 OCP와 LSP를 지킬 수 있다</p>
<br>

<hr>
<h2 id="예시">예시</h2>
<pre><code class="language-swift">struct Product {
    let name: String
    let cost: Int
    let image: UIImage
}</code></pre>
<pre><code class="language-swift">final class Network {
    private let urlSession = URLSession(configuration: .default)

    func getProducts(for userId: String, completion: @escaping ([Product]) -&gt; Void) {
        guard let url = URL(string: &quot;baseURL/products/user/\(userId)&quot;) else {
            completion([])
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = &quot;GET&quot;

        urlSession.dataTask(with: request) { (data, response, error) in
            DispatchQueue.main.async {
                completion([Product(name: &quot;Just an example&quot;, cost: 1000, image: UIImage())])
            }
        }
    }
}</code></pre>
<pre><code class="language-swift">final class ExampleScreenViewController: UIViewController {
    private let network: Network
    private var products: [Product]
    private let userId: String = “user-id&quot;

    required init?(coder: NSCoder) {
        fatalError()
    }

    init(network: Network, products: [Product]) {
        self.network = network
        self.products = products
        super.init(nibName: nil, bundle: nil)
    }

    override func loadView() {
        view = UIView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        getProducts()
    }

    private func getProducts() {
        network.getProducts(for: userId) { [weak self] products in
            self?.products = products
        }
    }
}</code></pre>
<h3 id="dip를-따르지-않았을-때-생기는-문제">DIP를 따르지 않았을 때 생기는 문제</h3>
<blockquote>
<p><strong><code>Rigidity &amp; Fragility</code></strong></p>
</blockquote>
<p>어떤 이유에서든 <code>Network를 바꿔야 한다면</code>, ExampleViewController에 있는 Network도 변경해야 함
이런 의도치 않은 변경으로 인해, <code>ExampleViewController는 rebuild &amp; retest가 필요하게 됨</code></p>
<blockquote>
<p><code>**Immobility &amp; Coupling**</code></p>
</blockquote>
<p>다른 곳에서 ExampleViewController을 다시 사용해야 할 때, <code>동일한 것을 가져다 쓴다면</code>,
Network도 함께 가져다가 사용해야하고, 이 Network가 굉장히 복잡한 구조라면 <code>동일하게 가져다 사용하는게 비효율적임</code></p>
<p>차라리 동일한 ExampleViewController를 가져다 쓰는 것 보다
새로운 ViewController를 만드는게 더 좋을수도 ..!</p>
<h3 id="dip를-따르게-된다면">DIP를 따르게 된다면</h3>
<p>상위, 하위 계층 모두 <code>‘추상’</code>을 의존하게 만들자</p>
<pre><code class="language-swift">// Abstraction
protocol ProductProtocol {
    var name: String { get }
    var cost: Int { get }
    var image: UIImage { get }
}</code></pre>
<pre><code class="language-swift">// Abstraction
protocol NetworkProtocol {
    func getProducts(for userId: String, completion: @escaping ([ProductProtocol]) -&gt; Void)
}
</code></pre>
<pre><code class="language-swift">struct Product: ProductProtocol {
    let name: String
    let cost: Int
    let image: UIImage
}</code></pre>
<pre><code class="language-swift">final class Network: NetworkProtocol {
    private let urlSession = URLSession(configuration: .default)

    func getProducts(for userId: String, completion: @escaping ([ProductProtocol]) -&gt; Void) {
        guard let url = URL(string: &quot;baseURL/products/user/\(userId)&quot;) else {
            completion([])
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = &quot;GET&quot;

        urlSession.dataTask(with: request) { (data, response, error) in
            completion([Product(name: &quot;Just an example&quot;, cost: 1000, image: UIImage())])
        }
    }
}</code></pre>
<pre><code class="language-swift">final class ExampleScreenViewController: UIViewController {
    private let network: NetworkProtocol // Abstraction dependency
    private var products: [ProductProtocol] // Abstraction dependency
    private let userId: String = &quot;user-id&quot;

    required init?(coder: NSCoder) {
        fatalError()
    }

    init(network: NetworkProtocol, products: [ProductProtocol]) { // Abstraction dependency
        self.network = network
        self.products = products
        super.init(nibName: nil, bundle: nil)
    }

    override func loadView() {
        view = UIView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        getProducts()
    }

    private func getProducts() {
        network.getProducts(for: userId) { [weak self] products in
            self?.products = products
        }
    }
}</code></pre>
<br>

<h2 id="추상화의-또-다른-이점">추상화의 또 다른 이점</h2>
<p>예전 레거시를 새로운 레거시로 손쉽게 변경할 수 있음</p>
<ul>
<li>현재 Network 프로토콜을 따르는 새로운 구초를 만들고 싶을 때,
프로토콜을 따르는 NewNetwork를 만들면 됨 !</li>
<li>테스트 코드를 작성하기 더 쉬워짐</li>
</ul>
<hr>
<p>[출처] <a href="https://medium.com/movile-tech/dependency-inversion-principle-in-swift-18ef482284f5">Dependency Inversion Principle in Swift</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기본에 집중하자] SOLID - Liskov Substitution Principle]]></title>
            <link>https://velog.io/@id_entity/%EA%B8%B0%EB%B3%B8%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EC%9E%90-SOLID-Liskov-Substitution-Principle</link>
            <guid>https://velog.io/@id_entity/%EA%B8%B0%EB%B3%B8%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EC%9E%90-SOLID-Liskov-Substitution-Principle</guid>
            <pubDate>Tue, 16 Jan 2024 13:09:17 GMT</pubDate>
            <description><![CDATA[<h2 id="definition">Definition</h2>
<blockquote>
<p>Programs that references an object from a base class 
must be able to use an object of a derived class without behavior differences and without knowing about its existence.</p>
<p>Base와 Base를 상속받는 객체가 있을 때, 
특정 프로그램에서 Base를 받아와 사용한다면, 
Base를 사용하든, 상속받은 객체를 사용하든, 차이점이 없어야 하고, 차이점이 보여서도 안된다.</p>
</blockquote>
<br>

<h2 id="예시1---unexpected-behaviors">예시1 - Unexpected Behaviors</h2>
<pre><code class="language-swift">class Rectangle {
    var width: Int
    var height: Int

    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }

    func area() -&gt; Int {
        return width * height
    }
}

class Square: Rectangle {
    override var width: Int {
        didSet {
            super.height = width
        }
    }

    override var height: Int {
        didSet {
            super.width = height
        }
    }
}</code></pre>
<pre><code class="language-swift">func main() {
    let square = Square(width: 10, height: 10)

    let rectangle: Rectangle = square

    rectangle.height = 7
    rectangle.width = 5

    print(rectangle.area()) 
    // As a rectangle we should expect the area as 7 x 5 = 35, but we got 5 x 5 = 25
}</code></pre>
<p>main()에서 Rectangle 타입으로 두고 rectangle 변수에 Square 타입 값을 할당하면
최종적으로 print 되는 값은 25가 됨</p>
<p>이 상황에서는, Square를 Rectangle 타입에 할당했지만, <code>rectangle.height = 7</code> 과 같은 코드는
Square에서 동작하는 것과 동일하게 동작</p>
<p><code>즉, Rectangle 타입으로 적어뒀고, 그렇게 알고 있는데, Square로 동작한다는 점에서 LSP를 위반함</code></p>
<h3 id="lsp를-따르지-않았을-때-생기는-문제">LSP를 따르지 않았을 때 생기는 문제</h3>
<p>추상화를 하기 위해 보통 <code>Polymorphism</code>(다형성)에 도움을 받음
(e.g. 마켓 앱에서 살 수 있는 모든 제품을 API로 받아올 때 다양한 아이템들을 추상화해서 받기)</p>
<p>위 예시에서 <code>rectangle</code> 이라는 변수가 어떤 타입이 될 수 있는지 모름
정사각형인지, 직사각형인지 등등 …</p>
<p>그렇기 때문에 우리는 <code>rectangle</code> 처럼 동작할 것이라고 예상할 수 있음
하지만, 위 예시에서 실상은 <code>rectangle</code> 로 동작하지 않고, <code>square</code> 로 동작함</p>
<h3 id="lsp를-따르게-된다면">LSP를 따르게 된다면</h3>
<pre><code class="language-swift">protocol Geometrics {
    func area() -&gt; Int
}

class Rectangle: Geometrics {
    var width: Int
    var height: Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }

    func area() -&gt; Int {
        return width * height
    }
}

class Square: Geometrics {
    var edge: Int
    init(edge: Int) {
        self.edge = edge
    }

    func area() -&gt; Int {
        return edge * edge
    }
}</code></pre>
<pre><code class="language-swift">func main() {
    let rectangle: Geometrics = Rectangle(width: 10, height: 10)
    print(rectangle.area())

    let rectangle2: Geometrics = Square(edge: 5)
    print(rectangle2.area())
}</code></pre>
<p>만약 상속 받으면서 내부 내용물을 정할 수 있다면, 손쉽게 따를 수 있을 것임
그래서 <code>Protocol</code>을 사용 !</p>
<br>

<h2 id="예시2---lsp--ocp">예시2 - LSP &amp; OCP</h2>
<pre><code class="language-swift">class Shape {
    func doSomething() {
        // do something relate to shape that is irrelevant to this example, actually
    }
}

class Square: Shape {
    func drawSquare() {
        // draw the square
    }
}

class Circle: Shape {
    func drawCircle() {
        // draw the circle
    }
}</code></pre>
<pre><code class="language-swift">func draw(shape: Shape) {
    if let square = shape as? Square {
        square.drawSquare()
    } else if let circle = shape as? Circle {
        circle.drawCircle()
    }
}</code></pre>
<p>코드가 이런 형식으로 되어 있으면, draw(shape:) 메소드가 실행될 때,
<code>Square 타입이 들어오거나, Circle 타입이 들어오거나, Shape 타입이 들어올 때 다른 방식으로 실행됨</code></p>
<p>추가로, 이 예시는 OCP를 위반하기도 하는데,
Triangle이라는 Shape을 상속받는 새로운 타입을 만들 때, 
draw(shape:) 메소드에 Triangle인 경우에도 추가해야 하기 때문</p>
<h3 id="lsp를-따르게-된다면-1">LSP를 따르게 된다면</h3>
<pre><code class="language-swift">protocol Shape {
    func draw()
}

class Square: Shape {
    func draw() {
        // draw the square
    }
}

class Circle: Shape {
    func draw() {
        // draw the circle
    }
}</code></pre>
<pre><code class="language-swift">func draw(shape: Shape) {
    shape.draw()
}</code></pre>
<p>프로토콜로 Shape 타입을 draw() 메소드와 함께 만들어 둔다면,
<code>각 타입을 만들 때, 타입별로 필요한 메소드를 내부에 적어둘 수 있고,</code>
<code>draw(shape:)에서도 어떤 Shape이건 동일하게 동작함을 볼 수 있음</code></p>
<p>추가적으로, Triangle 타입을 추가한다 하더라도, draw(shape:)에 변화를 줄 필요가 없기 때문에,
<code>OCP를 만족한다고도 볼 수 있음</code></p>
<hr>
<p>[출처] <a href="https://medium.com/movile-tech/liskov-substitution-principle-96f15559e363">Liskov Substitution Principle in Swift</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기본에 집중하자] SOLID - Open Closed Principle]]></title>
            <link>https://velog.io/@id_entity/%EA%B8%B0%EB%B3%B8%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EC%9E%90-SOLID-Open-Closed-Principle</link>
            <guid>https://velog.io/@id_entity/%EA%B8%B0%EB%B3%B8%EC%97%90-%EC%A7%91%EC%A4%91%ED%95%98%EC%9E%90-SOLID-Open-Closed-Principle</guid>
            <pubDate>Tue, 16 Jan 2024 11:48:22 GMT</pubDate>
            <description><![CDATA[<h2 id="definition">Definition</h2>
<blockquote>
<p>The <strong>Open Closed Principle</strong> says that “Software Entities (classes, modules, functions, etc) should be open for extension, but closed for modification”.</p>
<p>OCP에 따르면, <code>Software Entities</code> 는 확장할 수 있어야 하지만, 변경할 수는 없어야 한다.</p>
</blockquote>
<Br>

<h2 id="예시1---abstraction">예시1 - Abstraction</h2>
<pre><code class="language-swift">class Person {
    private let name: String
    private let age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

class House {
    private var residents: [Person]

    init(residents: [Person]) {
        self.residents = residents
    }

    func add(_ resident: Person) {
        residents.append(resident)
    }
}</code></pre>
<pre><code class="language-swift">protocol Resident {}

class Person: Resident {
        // ...
}

class House {
    private var residents: [Resident]

    init(residents: [Resident]) {
        self.residents = residents
    }

    func add(_ resident: Resident) {
        residents.append(resident)
    }
}</code></pre>
<h3 id="ocp를-따르지-않을-때-생기는-문제">OCP를 따르지 않을 때 생기는 문제</h3>
<p>왼쪽 예시를 보면, Person이라는 타입과는 다른 타입이 필요해서 <code>NewPerson 타입을 만든다면</code>,
<code>House에서는 내부에 있는 Person 타입들을 모두 NewPerson 타입으로 바꾸어야 함</code></p>
<p>즉, NewPerson으로 확장하려 하는데, House 에서는 변동이 생기기 때문에 OCP를 만족하지 못한다</p>
<p>만약, 그냥 Person 타입의 내부를 바꾼다면, 이 또한 Person 타입에 변동이 생기는 것이기 때문에 OCP를 만족하지 못한다</p>
<p>따라서, OCP를 따르지 않으면, 한 가지를 확장하려 할 때, 변동을 줘야 하는 요소가 생기게 된다</p>
<h3 id="ocp를-따르게-된다면">OCP를 따르게 된다면</h3>
<p>House 타입은 <code>Resident라는 프로토콜을 의존</code>하고 있고,
Person도 <code>Resident라는 프로토콜을 받아와 사용</code>하기 때문에,
<code>NewPerson이라는 타입이 Resident를 따르도록 형성</code>된다면, House에는 아무 변화를 주지 않아도 된다</p>
<Br>


<h2 id="예시2---enum">예시2 - Enum</h2>
<pre><code class="language-swift">enum DeeplinkType {
    case home
    case profile
}

protocol Deeplink {
    var type: DeeplinkType { get }
}

class HomeDeeplink: Deeplink {
    let type: DeeplinkType = .home
    func executeHome() {
        // Presents the main screen
    }
}

class ProfileDeeplink: Deeplink {
    let type: DeeplinkType = .profile
    func executeProfile() {
        // Presents the profile screen
    }
}</code></pre>
<pre><code class="language-swift">class Router {
    func execute(_ deeplink: Deeplink) {
        switch deeplink.type {
        case .home:
            (deeplink as? HomeDeeplink)?.executeHome()
        case .profile:
            (deeplink as? ProfileDeeplink)?.executeProfile()
        }
    }
}</code></pre>
<p>위 예시는 OCP를 따르지 않음</p>
<p>DeeplinkType에 <code>새로운 case</code>를 추가하게 되면
Router의 <code>execute()에도 새로운 case를 넣어줘야 하기 때문</code> !</p>
<h3 id="ocp를-따르지-않을-때-생기는-문제-1">OCP를 따르지 않을 때 생기는 문제</h3>
<p>나는 그저 <code>DeeplinkType를 확장</code>했을 뿐인데, <code>Router 클래스에도 변화</code>를 줘야한다고 ..?!</p>
<p>많은 경우에 enum의 사용은 이렇게 다른 곳에서의 변동을 발생시킨다 ㅠㅠ
간단하게 case만 추가해주면 되는 때도 있겠지만, 완전 복잡한 로직이 들어가면 사고 …</p>
<h3 id="ocp를-따르게-된다면-1">OCP를 따르게 된다면</h3>
<pre><code class="language-swift">protocol Deeplink {
    func execute()
}

class HomeDeeplink: Deeplink {
    func execute() {
        // Presents the main screen
    }
}

class ProfileDeeplink: Deeplink {
    func execute() {
        // Presents the Profile screen
    }
}</code></pre>
<pre><code class="language-swift">class Router {
    func execute(_ deeplink: Deeplink) {
        deeplink.execute()
    }
}</code></pre>
<p>이런 모습으로 바뀌게 됨 !</p>
<pre><code class="language-swift">class SettingsDeeplink: Deeplink {
    func execute() {
        // Present the Settings Screen
    }
}</code></pre>
<p>새로운 Deeplink 타입을 추가하게 되어도,
Router에는 아무 변동이 생기지 않음</p>
<hr>
<p>[출처] <a href="https://medium.com/movile-tech/open-closed-principle-in-swift-6d666270953d">Open Closed Principle in Swift</a></p>
]]></description>
        </item>
    </channel>
</rss>