<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>TheUglyDuckling.log</title>
        <link>https://velog.io/</link>
        <description>시행착오, 문제해결 그 어디 즈음에.</description>
        <lastBuildDate>Sat, 02 Apr 2022 07:56:31 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>TheUglyDuckling.log</title>
            <url>https://images.velog.io/images/y_dragonrise/profile/877e22cb-1e1f-4de6-b4ea-0c20af19b251/title_v02.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. TheUglyDuckling.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/y_dragonrise" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[스터디 블로그 연동 - giscus, GA]]></title>
            <link>https://velog.io/@y_dragonrise/%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%97%B0%EB%8F%99-giscus-GA</link>
            <guid>https://velog.io/@y_dragonrise/%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%97%B0%EB%8F%99-giscus-GA</guid>
            <pubDate>Sat, 02 Apr 2022 07:56:31 GMT</pubDate>
            <description><![CDATA[<p>저번에 이어서 스터디 블로그를 netlify로 정적 웹페이지를 작업하는 것까지 마무리하고,
analytics(GA), giscus(github discussions open source) 연동하는 작업만이 남았다.</p>
<h1 id="analytics">Analytics</h1>
<p>보통 벨로그 같은 블로그 서비스에서는 자체 분석 기능을 제공하지만, 분석 기능을 제공하지 않는 커스텀 블로그의 경우에는 Analytics를 따로 setup 해줘야된다.
anlytics platform은 다양하게 있다. (가격 정책 조심해야 함)</p>
<ul>
<li><a href="https://simpleanalytics.com/">simpleAnalytics</a></li>
<li><a href="https://umami.is/">umami</a></li>
<li><a href="https://analytics.withgoogle.com">googleAnalytics</a></li>
<li><a href="https://plausible.io/">plausible</a></li>
</ul>
<p>GA는 funnel 분석에 사용한 경험이 있어서, 가능한 빠르게 연동 가능한 것을 선정했다.</p>
<p>많은 기능은 필요 없어서 단순하게 1페이지만 보고 싶은데, GA는 너무 많은 분석 정보를 제공하는게 그렇게 필요한가 싶었다. 또 GA는 확실히 대시보드가 열리기까지 뭔가 페이지가 너무 느린 느낌(무거움)에 다른걸로 바꾸는게 좋을 듯하다.</p>
<p><del>일단 GA는 연동했고, 빠른 시일 내에 측정 도구를 바꿔 볼 예정이다.</del></p>
<h2 id="google-analytics">Google Analytics</h2>
<p><a href="https://analytics.google.com/">Google Analytics</a>에 접속 후 측정시작을 누르고, 설정을 해준다.</p>
<ol>
<li><p>계정 설정</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/89d08b9b-ff9b-464a-932a-56bf49d4d3ad/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.46.25.png" alt="계정 설정"></li>
<li>계정 이름 - 사용할 계정 이름을 기입해준다.</li>
<li>계정 데이터 공유 설정 - google에 데이터를 공유하는 설정인데, 원하는 항목에 체크한다.</li>
</ul>
</li>
<li><p>속성 설정</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/d4a02fb0-e147-4319-877a-1cd168d8b53c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.46.59.png" alt="속성 설정"></li>
<li>측정할 애플리케이션의 속성을 추가한다.</li>
<li>위의 계정 설정과 마찬가지로 추후에 수정이 가능하다.</li>
</ul>
</li>
<li><p>비즈니스 설정</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/6ca6e5d1-bdf9-4f22-a10a-104953f3ac0b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.47.18.png" alt="비즈니스 설정"></li>
<li>분석에 필요한 측정 규모를 지정한다.</li>
</ul>
</li>
<li><p>데이터 스트림 선택</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/681fd5df-cf81-466e-a14f-464fdc217fc4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.48.05.png" alt="데이터 스트림 선택"></li>
<li>분석 측정을 하기 위한 플랫폼을 설정해준다.</li>
<li>본인은 웹 환경을 측정하기 위해서 웹을 선택했다.</li>
</ul>
</li>
<li><p>데이터 스트림 환경 설정</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/f60a504e-97f5-4388-84e8-67e6c9faa0d8/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.48.21.png" alt="데이터 스트림 환경 설정"></li>
<li>본인이 측정하고자 하는 서비스의 URL을 설정해준다.</li>
</ul>
</li>
<li><p>환경 설정 확인</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/5c841645-b9bf-4b62-8847-033ca7f326ee/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.49.21.png" alt="확인"></li>
<li>최종적으로 설정된 스트림과, 측정 ID 값을 확인한다.</li>
<li>측정 ID 값을 확인(UA-000000-2 or G-XXXXXXX)하고, 연결하고자 하는 플랫폼과 연동해준다.</li>
</ul>
</li>
<li><p>분석 측정 방법 선택하기</p>
<ul>
<li><img src="https://media.vlpt.us/images/y_dragonrise/post/673b9426-fa48-42fa-874d-3cfefc007527/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.49.32.png" alt="분석 측정 1"></li>
<li>해당 script를 본인 애플리케이션에 삽입한다.</li>
<li>이외에 플랫폼에 따라 SDK를 설치해서 세밀한 분석을 하는 방법도 있다.<ul>
<li>기본적으로 analytics에서 측정해주는 항목도 있고, logEvent를 통한 세밀한 측정이 가능하다.</li>
<li>이탈율, 페이지 전환률 측정, 리텐션 측정, 퍼널 분석 등</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="참고-자료">참고 자료</h3>
<ul>
<li>보통 google analytics에서 제공하는 공식 문서를 참고하면서 setup을 진행했지만, google에서 기본 가이드를 강의 형태도 제공하는데 참고하면 좋을 것 같다.<ul>
<li>[Analytics Academy] <a href="https://analytics.google.com/analytics/academy">https://analytics.google.com/analytics/academy</a></li>
</ul>
</li>
</ul>
<h1 id="giscus">giscus</h1>
<p>utterances, disqus도 있지만, github discussions 기반의 giscus를 연동하는게 나을 것 같아서 giscus를 선택했다.
연동하는데는 크게 어렵지 않아서 analytics와 마찬가지로 본인이 선택한 옵션대로 script generator를 지원해서 giscus를 활성화 할 수 있다. </p>
<ul>
<li><a href="https://giscus.app/ko">giscus 공식 사이트</a></li>
</ul>
<h1 id="기타-설정csp-env-setting">기타 설정(CSP, env setting)</h1>
<h2 id="csp">CSP</h2>
<p>이외에도 야크털을 좀 깎았는데 giscus를 설정할 때, CSP(<code>Conetent-Security-Policy</code>) 설정이 필요하다는 경고창을 보고 header를 설정해줬다.
<img src="https://media.vlpt.us/images/y_dragonrise/post/b58187ad-657e-4a49-9319-41f8b944da9a/giphy.gif" alt="cat"></p>
<p>CSP는 대충 <code>XSS</code>, <code>Data injection</code> 등의 보안 취약점을 완화시키기 위해 설정할 수 있는 meta tag인데 털릴 정보는 없으나 설정함.. <del>(특 쫄보임)</del></p>
<p>mdn 문서를 참고해보자면,</p>
<pre><code class="language-html">&lt;meta http-equiv=&quot;Content-Security-Policy&quot;
      content=&quot;default-src &#39;self&#39;; img-src https://*; child-src &#39;none&#39;;&quot;&gt;</code></pre>
<p>위와 같이 <code>&lt;meta&gt;</code> 요소를 사용하여 정책을 설정할 수 있다.</p>
<p>Content value에는 다양한 옵션이 존재한다.</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy">CSP value 참고 자료</a></li>
</ul>
<p>최종적으로 Example usecase를 참고하여 <code>default-src</code>에 GA와 giscus app, localhost를 화이트리스트로 추가했다.</p>
<h2 id="envenvironment-variable">env(environment variable)</h2>
<p>API Key나, ID, PW 등 외부에 노출되지 말아야하는 key pair들의 정보는 env 파일로 따로 관리해야하는데, 작성 후에 외부 노출을 방지하기 위해 .gitignore에서 블랙 리스트를 추가해서 관리하는 편이다.</p>
<ul>
<li>env prefix, postfix를 통해서 이름 규칙을 정해주고 gihub에 push 되지 않도록 설정</li>
<li>정 올리고 싶으면, env.example 파일 생성해서 key 값만 설정하고 참고 형태로 관리해도 됨</li>
</ul>
<p>웬만하면 react project나 기타 프레임워크에서 프로젝트 init시에 gitignore에 설정되어 있느니, env.production, env.development와 같이 cross-env plugin을 쓰거나, react dot env를 쓸때에는 build script 등 따로 설정해야할 부분은 꼭 체크하고 넘어가자!</p>
<blockquote>
<p>build process 를 제공하는 vercel이나 netlify 등 env를 따로 쉽게 서비스 상에서 설정할 수 있으니, 해당 공식 사이트 문서를 참고하면 좋음.
gitignore를 설정했다면 github repo에는 env 파일이 push 되지 않습니다.</p>
</blockquote>
<h1 id="닫는-말-🚪">닫는 말 🚪</h1>
<p><img src="https://media.vlpt.us/images/y_dragonrise/post/d09826b2-1eeb-4431-9e66-8f5e1e0c587c/giphy.gif" alt=""></p>
<ul>
<li>본인이 연동하고자 하는 서비스의 방향이 어떠냐에 따라서 도구를 잘 선택해 쓰는 것도 중요하다.</li>
<li>공식문서에 답이 나와있다, 간과하지 말자!</li>
<li>umami로 분석 측정도구 바꿔야지... 😃 <code>simple is best</code>가 최고임...</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[스터디용 블로그 띠용 분리 👀]]></title>
            <link>https://velog.io/@y_dragonrise/%EC%8A%A4%ED%84%B0%EB%94%94%EC%9A%A9-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EB%94%B0%EB%A1%9C-%EB%B6%84%EB%A6%AC</link>
            <guid>https://velog.io/@y_dragonrise/%EC%8A%A4%ED%84%B0%EB%94%94%EC%9A%A9-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EB%94%B0%EB%A1%9C-%EB%B6%84%EB%A6%AC</guid>
            <pubDate>Wed, 30 Mar 2022 14:55:11 GMT</pubDate>
            <description><![CDATA[<h1 id="선정">선정</h1>
<img src="https://images.velog.io/images/y_dragonrise/post/949e1906-6a52-4343-933a-8574ce2fff92/giphy.gif" style="width: 40%" alt="right"/>

<p><a href="https://velog.io/@y_dragonrise/%EA%B3%84%ED%9A%8D%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B3%84%ED%9A%8D-%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8">이전 게시글</a>에서 봤듯이, 스터디용 블로그를 위해서 최대한 빠르게 만들 수 있는 정적 웹 블로그가 필요했다. 
공부하고 -&gt; 정리하고 올리고 하는 용도의 Note처럼 쓰기 위한 블로그라서 &quot;시간을 잡아먹는(야크털 깎기) 요소들을 줄이고 집중하자.&quot;라고 생각했지만 예상외로 초입부터 야크털을 좀 깎았다.</p>
<h2 id="템플릿">템플릿</h2>
<p>Jekyll + github page 조합은 썩 맘에 들지 않아서, <a href="https://jamstackthemes.dev/">JamStack</a> 참고해서 TailwindCSS + Next.js 조합의 <a href="https://github.com/timlrx/tailwind-nextjs-starter-blog">템플릿</a>을 발견했다. 바로 새 git repo 새로 파고 몇가지 커스텀을 진행했다.</p>
<h3 id="커스텀">커스텀</h3>
<ul>
<li>JS Official 버전으로 진행<ul>
<li>local project path에서 <code>npx degit https://github.com/timlrx/tailwind-nextjs-starter-blog.git</code> 명령어를 실행해 clone함</li>
</ul>
</li>
<li>Sitemetadata.js custom<ul>
<li>웹에서 사용하는 메타데이터 구성 요소들 수정</li>
</ul>
</li>
<li>favicon 등 Assets 수정<ul>
<li>fivicon 및 Asset들 수정</li>
</ul>
</li>
<li>기타 레이아웃 수정<ul>
<li>쓰지 않을 라우터 및 페이지 삭제</li>
</ul>
</li>
</ul>
<p>내가 사용하고 싶은 부분만 수정해서 진행했다. 
템플릿 자체가 다른 서드파티 플랫폼 연동을 위한 소스코드가 잘 정리되어 있어서 수정하는데 큰 어려움은 없었다. </p>
<h3 id="netlify-연결">Netlify 연결</h3>
<p>설정 방법은 아주 간편하다.</p>
<img src="https://images.velog.io/images/y_dragonrise/post/9dd354d2-ce9a-4fbe-b310-63efb1f47a03/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.12.36.png" style="width: 80%" alt="setup"/>

<img src="https://images.velog.io/images/y_dragonrise/post/a8cac395-c8b5-4bdc-a8b6-45d2a6e416ed/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.12.45.png" style="width: 80%" alt="setup2"/>

<ul>
<li>내가 hosting 하고 싶은 github repository(project)와 연결한다.</li>
<li>install을 진행하고 deploy setting을 진행한다.<ul>
<li>main branch or master branch를 지정해주고, build command를 setup 해준다.</li>
<li>내가 선정한 템플릿은 next.js(SSR)를 사용하므로 자동으로 form field에 build command가 채워졌다.</li>
<li>이외의 템플릿을 진행한다면 netlify가 굉장히 친절하게 설명해주고 있으니 <a href="https://docs.netlify.com/configure-builds/common-configurations/">공식 사이트</a>를 참고한다.</li>
</ul>
</li>
</ul>
<img src="https://images.velog.io/images/y_dragonrise/post/628983a9-3d01-45e6-8386-12a8b8c98a1a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.03.02.png" style="width: 80%" alt="setup3"/>

<ul>
<li>Setup이 완료되면 deploy scripting을 netlify가 진행하고, domain 설정을 진행하면 된다.</li>
</ul>
<img src="https://images.velog.io/images/y_dragonrise/post/b4fdaa47-d844-4f53-96d7-494165a29df8/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-29%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.30.28.png" style="width: 80%" alt="setup4"/>

<ul>
<li>나는 위의 절차대로만 진행하고 따로 domain settings 옵션에서 custom domain 설정을 해주었다. </li>
</ul>
<img src="https://images.velog.io/images/y_dragonrise/post/c1e7bcaa-7f20-4aa0-b7e3-748cf90ec607/FireShot%20Capture%20004%20-%20Deploys%20-%20duckstudy%20-%20app.netlify.com.png" style="width: 80%" alt="setup6"/>

<ul>
<li>netlify에서 내가 설정한 master branch에 소스 코드 변동 사항이 감지되면 Deploys 탭에서 확인할 수 있듯이 building -&gt; published 과정을 진행하는 것을 볼 수 있다.</li>
<li>Building 중의 오류 사항, 진행 사항을 상세히 볼 수 있다. 또 published 상태에서도 Log를 확인할 수 있다.</li>
<li>아직 확실하지는 않지만 Vercel과는 다르게 이전에 배포한 버전으로 쉽게 rollback 할 수 있는 옵션은 제공하지 않는 듯 하다.</li>
</ul>
<h4 id="시행착오">시행착오</h4>
<img src="https://images.velog.io/images/y_dragonrise/post/3fb5a338-fce1-4a8e-98fc-77fe43905f06/giphy.gif" style="width: 30%" alt="wakeup" />

<blockquote>
<p>정신차리자 진짜 👎 ...</p>
</blockquote>
<p>위에 보았듯, build script 초기 세팅이 꼬여버려서 에러를 내고 
두번째 에러는 분명.. official document를 봤는데도 guide대로 하지 않았기 때문이다.
next.js에서 server-side rendering은 build command를 <code>next build</code>로 지정하고 
public directory는 <code>.next</code>가 맞는 것인데.. 
static html export build command를 지정해서 image optimized api setting을 하고... 
먼길을 돌아서 왔다... </p>
<h1 id="닫는-말-🚪">닫는 말 🚪</h1>
<p>남은 Task</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> giscus 연동</li>
<li><input checked="" disabled="" type="checkbox"> analytics 연동</li>
</ul>
<p>뭔가 알맹이 없이 끝내는 것 같지만, 이제 꾸준히 정리하고 또 정리하고 ... 
미친듯이 달려갈 일만 남았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[협업에 필요한 5 Why]]></title>
            <link>https://velog.io/@y_dragonrise/%ED%98%91%EC%97%85%EC%97%90-%ED%95%84%EC%9A%94%ED%95%9C-5-Why-%EA%B8%B0%EB%B2%95</link>
            <guid>https://velog.io/@y_dragonrise/%ED%98%91%EC%97%85%EC%97%90-%ED%95%84%EC%9A%94%ED%95%9C-5-Why-%EA%B8%B0%EB%B2%95</guid>
            <pubDate>Wed, 30 Mar 2022 01:29:52 GMT</pubDate>
            <description><![CDATA[<h1 id="5-why">5 why</h1>
<h1 id="질문">질문</h1>
<blockquote>
<p>정보를 요청하는 데 쓰이는 언어학적 표현이거나, 그러한 표현을 스스로 하는 요청을 가리킨다. 이러한 정보는 답변과 함께 제공될 수 있다.</p>
</blockquote>
<h1 id="왜-질문하는가">왜 질문하는가?</h1>
<img src="https://images.velog.io/images/y_dragonrise/post/81477d9a-ee3e-482a-9550-9e78dc84793a/_2021-03-14__3.20.15.png" alt="점심 뭐먹지" style="width: 50%; margin: 0 auto;"/>

<blockquote>
<p>점심 뭐먹지? (<del>흔히 겪는 직장인들의 질문 딜레마</del>)</p>
</blockquote>
<ul>
<li>고민</li>
<li>본인이 해석할 수 없는 경계에 직면했을 때</li>
<li>단순 호기심</li>
<li>문제 해결</li>
</ul>
<h2 id="질문을-통해서-얻는-이점">질문을 통해서 얻는 이점</h2>
<ul>
<li>탐구</li>
<li>새로운 정보 수집, 분류</li>
<li>새로운 이해와 통찰</li>
</ul>
<h2 id="best-question---왜why">Best question - 왜(Why)</h2>
<ul>
<li>기존의 어떤 프레임과 가정, 가설에 대해 의문을 제기<ul>
<li>더 좋은 프레임 획득</li>
</ul>
</li>
</ul>
<h1 id="왜why라는-질문이-왜-필요할까">왜(Why)라는 질문이 왜 필요할까?</h1>
<p><img src="https://images.velog.io/images/y_dragonrise/post/27a99b5e-28e0-4323-83ec-5d7fbb8cc36a/_2021-03-14__3.29.09.png" alt="why"></p>
<ul>
<li>누구나 어렸을 때부터 질문을 해왔음</li>
<li>취학 전 아이들이 부모에게 하루 평균 100가지의 질문을 함<del>(거의 물음표 살인마...)</del></li>
<li>나이를 먹기 시작하면서 <code>묻기를 멈춤</code></li>
</ul>
<h2 id="왜-라는-질문을-통해-얻는-이점">&#39;왜&#39; 라는 질문을 통해 얻는 이점</h2>
<ul>
<li><code>더 깊은 이해</code>를 할 수 있음</li>
<li>어떤 주장의 <code>근거를 파악</code>할 수 있음</li>
<li>파악된 결과를 통해 <code>어떤 일들이 일어날지 미리 생각</code>해 볼 수 있음</li>
<li>다른 사람의 입장을 <code>공감</code>할 수 있음</li>
<li><code>더 좋은 해법</code>을 찾을 수 있음</li>
<li><code>집중할 곳</code>이 어디인지 <code>명확</code>해짐</li>
</ul>
<h1 id="왜why를-효과적으로-사용하기">왜(Why)를 효과적으로 사용하기</h1>
<h2 id="5-why-1">5 Why</h2>
<ul>
<li>1970&#39;s Toyota에서 시작</li>
<li>올바른 문제 찾기<ul>
<li>눈에 띄는 현상 바라보기</li>
<li>왜 발생했는지 물어보기</li>
<li>문제의 근본 원인 찾기</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>해결책이 아닌 대응책 사용</li>
<li>문제의 <code>근본 원인</code>을 찾는 방법</li>
</ul>
<h2 id="how-to-use-5-why">How to use 5 Why?</h2>
<ol>
<li><p>문제 정의하기</p>
<ul>
<li>실행 중인 문제 관찰</li>
<li>간단하고 명확한 문제 진술 작성</li>
</ul>
</li>
<li><p>처음으로 &quot;왜?&quot;라고 질문하기</p>
<ul>
<li>문제가 발생하는 이유 묻기</li>
<li>질문을 받으면 대답은 최대한 진중하게</li>
<li>실제 일어났던 일에 대한 사실적으로 근거 있는 답 찾기</li>
</ul>
</li>
<li><p>&quot;왜?&quot;를 네 번 더 묻기</p>
<ul>
<li>2단계에서 생성한 각 답변에 대해 4개의 &quot;이유를&quot; 연속적으로 질문</li>
<li>한 질문에서 다음 질문으로 빠르게 이동하여 결론을 내리기 전에 전체 그림을 그리기<ul>
<li>예시 (단순한 형태의 5 why, 복잡한 형태의 5 why)<ul>
<li><code>단순한 형태의 5 why</code><img src="https://images.velog.io/images/y_dragonrise/post/64cbc016-6282-44a6-8332-c2f4dd014cd1/insight_share_(1).png" style="width: 50%"/></li>
<li><code>복잡한 형태의 5 why</code><img src="https://images.velog.io/images/y_dragonrise/post/bba1cc4b-1c8e-49c1-921f-266dcc503028/insight_share.png" style="width: 90%"/>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>언제 멈출지 인지하기</p>
<ul>
<li>유의미한 응답 확인<ul>
<li>더 이상 문제를 해결할 수 없는지 검증
→ 적절한 대응책이나 프로세스의 변화가 분명해짐</li>
</ul>
</li>
</ul>
<blockquote>
<p>💡 Tip 1️⃣</p>
</blockquote>
<ul>
<li>어떤 경우에는 문제의 근원에 도달하기 전에 &quot;왜?&quot;를 몇 번 더 물어봐야 할 수도 있음</li>
<li>다른 경우에는 다섯 번째 &quot;왜?&quot;를 묻기 전에 이 지점에 도달할 수도 있음</li>
<li>만약 그렇다면, 너무 빨리 멈추지 않았는지 그리고 대답할 시간을 충분히 주지 않았는지 확인
→ 중요한 점은 유용한 응답을 하지 않을 때, &quot;왜?&quot;라는 질문을 <code>중단</code></li>
</ul>
<blockquote>
<p>💡 Tip 2️⃣</p>
</blockquote>
<ul>
<li>일련의 질문들을 해보다 보면, 누군가가 <code>필요한 조치를 취하지 못했다</code>는 것을 발견함
→ 5 Why의 가장 좋은 점은 책임을 전가하는 것보다 더 나아가서 <code>왜 그런 일이 일어났는지</code> 물어봐야 함</li>
</ul>
</li>
<li><p>근본 원인을 해결하기</p>
<ul>
<li>확인된 근본 원인에 대해 문제가 반복되지 않도록 하는 대응책을 논의 및 합의</li>
</ul>
</li>
<li><p>측정값을 모니터링하기</p>
<ul>
<li>대응 조치가 초기 문제를 얼마나 효과적으로 제거하거나 최소화하는지 예의 주시</li>
<li>수정 및 교체의 상황이 발생했을 경우 5가지 이유 프로세스를 반복하여 올바른 근본 원인을 확인</li>
</ul>
</li>
</ol>
<h2 id="정리">정리</h2>
<blockquote>
</blockquote>
<p>💡 5 Why 전략 → 문제의 근원을 밝히기 위한 간단하고 효과적인 도구</p>
<ul>
<li>문제부터 시작해서 왜 그런일이 일어나는지 물어봐야 함</li>
<li>대답이 사실인지 확인</li>
<li>문제의 근본 원인 도달할때까지 프로세스 반복</li>
<li>단순하거나 다소 어려운 문제에 적합한 프로세스<ul>
<li>복잡한 문제 → 상세한 접근 방식 권장</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[계획을 위한 계획, 블로그를 위한 블로그]]></title>
            <link>https://velog.io/@y_dragonrise/%EA%B3%84%ED%9A%8D%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B3%84%ED%9A%8D-%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8</link>
            <guid>https://velog.io/@y_dragonrise/%EA%B3%84%ED%9A%8D%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B3%84%ED%9A%8D-%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8</guid>
            <pubDate>Tue, 29 Mar 2022 08:38:22 GMT</pubDate>
            <description><![CDATA[<img src="https://images.velog.io/images/y_dragonrise/post/f1521fad-2fef-4cc4-a197-3451a41556fd/20200924_5f6c0425d3c1f.gif" style="width: 30%" alt="대충 지금부터 개소리"/>

<blockquote>
<p>주의: 대충 지금 부터 <code>개소리</code> 일수도 있고 아닐 수도 있다라는 뜻입니다.</p>
</blockquote>
<h1 id="내-블로그-연대기">내 블로그 연대기</h1>
<h2 id="tistory---velog">Tistory -&gt; Velog</h2>
<p>원래는 Tistory를 이용하다가 잔버그, 느린 속도로 인해서 블로그를 찾기 시작했고 Velog를 알게됐다. 
확실히 Velog가 깔끔하고 잔버그도 많지 않고 무엇보다도 WYSIWYG기반의 에디터 보다는 Markdown 기반의 사용성이 더 좋다. </p>
<h2 id="velog---notion">Velog -&gt; Notion</h2>
<p>Velog에 게시글을 꾸준히 쌓다가, 이미 공부 정리용으로 사용하고 있는 개인 공간 Notion 집중되어 
이도저도 아닌 상황이 되었다. 
아마 Velog보다 Notion이 사용성이 더 좋았다고 생각했을지도 모른다. 
그러다가 요즘에 드는 생각 Velog 이외의 <code>Blog를 나눠서 운영</code>하고 싶은 생각이 문득 들었다.
기존의 게시글들은 개념적인 부분도 있고, 그게 아닌 부분도 있어서 분리해서 관리하는 게
낫다고 생각했다. </p>
<h1 id="계획">계획</h1>
<img src="https://images.velog.io/images/y_dragonrise/post/cd73f1d0-7b40-49cf-80fc-0d0158901675/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.17.42.png" style="width: 70%" alt="푸우 사진"/>

<p>계획을 위한 계획을 좋아하는 나는, 세가지의 유형으로 나눠서 관리하려고 마음 먹었다.</p>
<ol>
<li>아카이빙(개발 팁, ex) &#39;Gist&#39; Or &#39;Code Snippet&#39;)</li>
<li>시행착오 Or 문제 해결 위주의 블로그(재밌거나 혹은 재미없거나)</li>
<li>공부 정리용 블로그(노잼)<h2 id="아카이빙achiving용-블로그-🗄">아카이빙(Achiving)용 블로그 🗄</h2>
<h3 id="플랫폼-선정---노션notion">플랫폼 선정 - 노션(Notion)</h3>
</li>
</ol>
<ul>
<li>개발 과정에서 이전에 해결했던 문제를 또 다시 반복하는 <code>야크털 깎기</code>의 상황을 마주하고 싶지 않아서, 아카이빙해야 겠다는 생각이 많이 들었다.</li>
<li>이미 노션으로 개인 공부(인강, 클론 코딩 등...) 내용들을 따로 정리하고 있었지만, Notion이 점점 여러 포맷들로 인해서 중구 난방되는 것을 보고 더욱 더 분리해서 관리해야 된다고 생각했다.</li>
<li><code>답정 Notion</code>이다. Notion은 필요에 의해서 외부에 웹 링크 형태로 공유할 수 있고, 무엇보다 공개하기 이전의 Private한 내 개인 공간으로 이용중이라서 <code>마음이 너~무 편한 플랫폼</code>이다. 민감한 내용들도 한 곳에서 관리할 수 있기 때문에 당연히 <code>Notion</code>을 안할 이유는 없다. <img src="https://images.velog.io/images/y_dragonrise/post/4a048ed8-8d44-4a3a-b127-b16da913ca5e/20180731_5b600fa10cf1f.jpg" style="width: 50%" alt="쿨 소화"/></li>
<li>진행중인 프로젝트들 혹은 전 회사에서 마주했던 <code>문제 상황들을 모아서 관리</code>하고, <code>공개할 부분은 Velog로 노출</code>한다.. 이게 내 계획이다.</li>
<li>하지만 리소스 좀 먹는 듯, 사용하기 쾌적한 정도는 아니다<blockquote>
<p>다양한 export 지원(타 플랫폼과의 이식성), 다양한 포맷 지원, <code>쉽고 편한 페이지 공유</code>(강려크함)
<code>내 작고 소중한 공간</code>(내작소공)</p>
</blockquote>
</li>
</ul>
<h2 id="경험-야크털-깎는-블로그-🤷🏻♂️">경험, 야크털 깎는 블로그 🤷🏻‍♂️</h2>
<h3 id="플랫폼-선정---벨로그velog">플랫폼 선정 - 벨로그(Velog)</h3>
<ul>
<li>국내에서 제일 쾌적하고, 쾌적함... <code>Simple Is Best</code>의 우위를 선점하고 있다.</li>
<li>나는 &#39;게시글로 수익창출을 한다&#39;에는 전혀 동의하는 바가 없기 때문에 당연히 꾸준히 쓸 수 있어야되는 정도의 쾌적함을 가지고 있어야 된다고 생각했다.</li>
<li>딱히 단점은 보이지 않는다.
<img src="https://images.velog.io/images/y_dragonrise/post/9f75a6ef-53cb-4d70-8200-468c3aef70e4/20180111_5a56cfbc2b410.gif" alt="wow"><blockquote>
<p><code>Simple Is Best</code>의 표본, <code>꾸준히</code> 할 수 있는 것, 게시글 수익 창출에 동의하지 않고 <code>자주</code> 쓸 수 있는 곳을 선택한다면 단연 Velog가 아닌가 싶음</p>
</blockquote>
</li>
</ul>
<h2 id="스터디용-블로그-🧑💻">스터디용 블로그 🧑‍💻</h2>
<h3 id="플랫폼-선정---github-page-or-netlify">플랫폼 선정 - <del>Github Page</del> OR Netlify</h3>
<ul>
<li>1 부터 10까지 개발해서 블로깅하는 것을 원하지는 않는다.</li>
<li>딱히 SEO도 중요하지 않았다. 내가 공부한 것들을 정리하고 노트처럼 저장할 수 있는 <code>&#39;나만의 블로그&#39;</code>가 필요했다.</li>
<li>Hosting의 이점과 Free Tier의 기능, 추후의 커스텀을 고려해서, <del>Github Page</del>와  Netlify를 고민하던 중 <code>Netlify</code>로 정했다.</li>
<li>템플릿을 직접 만드는 시간은 나중에 투자하기로 하고, <a href="https://jamstackthemes.dev/">여기</a>를 참고해서 Filter 중 내가 경험했던 스펙인 Next.js + TailswindCSS 템플릿을 선정했다.</li>
<li>mdx, md 기반의 에디터를 지원하고 블로깅은 Hugo Standard로 더 빠르게 페이지를 generate 할 수 있어야 했다.</li>
<li>완성된 템플릿인 만큼, 여러 가능성을 열어두고 서드 파티 플랫폼 설정을 바로 할 수 있게 코드가 짜여져 있어서 사용자는 <code>Custom을 어느 정도 할 수 있는가?</code> 혹은 <code>어디까지 할 수 있는가</code> 정도가 분명해야 한다.<img src="https://images.velog.io/images/y_dragonrise/post/4f7a207a-3cba-4d4d-9578-6aa30d4380e0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.32.54.png" style="width: 30%" alt="짱구"/>
>`템플릿이라고만 했지, 커스텀은 직접 관리해야한단다...` 
좋은 도구를 가져다 쓰는 것도 능력인 듯 하다. 
하.. 능력키우기 어렵다...
# 닫는 말 🚪</li>
<li>이렇게 푸념인지, 정보성 글인지 어쩌란 건지 모르겠는 글을 작성하는 것이 내 <code>Velog</code>의 취지이다.
<img src="https://images.velog.io/images/y_dragonrise/post/46b89525-562e-4617-8521-2859e280c663/giphy.gif" alt="nod"></li>
<li>결론, <code>쓰고 싶은 거 잘 알아보고 쓰자</code></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ALL OF SOFTWARE PROJECT 中]]></title>
            <link>https://velog.io/@y_dragonrise/ALL-OF-SOFTWARE-PROJECT-%E4%B8%AD</link>
            <guid>https://velog.io/@y_dragonrise/ALL-OF-SOFTWARE-PROJECT-%E4%B8%AD</guid>
            <pubDate>Sat, 26 Mar 2022 11:00:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>[소프트웨어 개발의 모든 것] 중, 
Part 2. 소프트웨어 개발을 성공으로 이끄는 법</p>
</blockquote>
<h1 id="소프트웨어-프로젝트--생명체">소프트웨어 프로젝트 = 생명체</h1>
<ul>
<li>생명체와 같이 유기적으로 움직임</li>
<li>프로젝트 규모가 작다<ul>
<li><code>전문 지식 경험 없이 수행 가능</code></li>
<li>but. 규모가 커질수록 체계적인 관리 요구! <code>개발 방법론 도입</code></li>
</ul>
</li>
</ul>
<p>CASE1. 개발 방법론을 그냥 따라하면?</p>
<ul>
<li>너무 복잡함</li>
<li>문서를 많이 만들어야 함</li>
<li>방향성을 잃어버림</li>
<li>제대로 도입하지 않으면 방해가 됨</li>
</ul>
<p>CASE2. 세계적으로 검증된 유명한 개발 방법론을 도입했더니?</p>
<ul>
<li>프로젝트 소요시간 증가</li>
<li>개발자의 불만 증가</li>
<li>제품의 품질 감소</li>
<li>작성해야 할 문서 증가</li>
<li>문서 내용 중복</li>
<li>형식적인 문서 작성</li>
<li>실제 개발에 도움 안됨</li>
<li>승인 절차로 인해 너무 지연됨</li>
</ul>
  <img src="https://images.velog.io/images/y_dragonrise/post/1f2e6238-53ef-4340-811d-8f3eb3f009ef/giphy.gif" width="300" alt="nope" style="display: block; margin: 0 auto"/>

<blockquote>
<p>지쳐서 방법론 따위는 ...</p>
</blockquote>
<h2 id="효율적인-개발-방법론-도입">효율적인 개발 방법론 도입</h2>
<ul>
<li><p><code>SRS</code> → 프로젝트의 기둥으로서의 역할</p>
<blockquote>
<p>SRS(Software Requirement Specification)
  소프트웨어 요구 명세, 기능 명세    </p>
</blockquote>
  <img src="https://images.velog.io/images/y_dragonrise/post/7ce6626d-cd16-4a02-9ad1-7671473fe618/ppt.png" width="500" alt="tree" style="display: block; margin: 0 auto"/>


</li>
</ul>
<ul>
<li><p>도입한 개발방법론을 고집하지 않고 <code>무엇이 문제인지 다시 생각</code></p>
</li>
<li><p>이론의 문제보다는 <code>경험자의 지혜</code>를 빌려야 함</p>
</li>
<li><p>코딩부터 시작 → <code>무엇을 만들어야 하는지 정확하게 모르는 상태</code>에서 뭔가를 만든다.</p>
</li>
<li><p>불충분한 요구사항으로 인한 재작업은 재앙의 시작.</p>
<h1 id="생애주기-모델을-제대로-선택하라">생애주기 모델을 제대로 선택하라</h1>
<h2 id="생애주기life-cycle-모델">생애주기(Life Cycle) 모델</h2>
</li>
<li><p>소프트웨어 탄생 ~ 소멸</p>
</li>
<li><p>생애주기에 대한 고민 ?!</p>
</li>
<li><p>일단 <code>짜보고 고치기(Code-and-fix)</code>의 딜레마</p>
<ul>
<li>문서도 없이 코딩하고 고치기를 반복</li>
<li>빠른 시간안에 가시적인 결과물이 나온다<ul>
<li>but. 많은 위험 잠재, 일정 산정, 진행 상황 체크하기 어려움</li>
</ul>
</li>
<li>생애 주기 모델의 범주에 조차 들어가지 않음.</li>
</ul>
</li>
<li><p>적합한 생애주기 모델 선정의 어려움</p>
<h2 id="폭포수-모델">폭포수 모델</h2>
<p><img src="https://images.velog.io/images/y_dragonrise/post/92cd3dd5-996e-4b58-bf7d-da4ed18b0b73/ALL%20OF%20SOF%20f5e21.png" alt="waterfall"></p>
</li>
<li><p>모든 생애주기 모델의 근본</p>
</li>
<li><p><code>순차적인 단계 발전</code>의 모델</p>
<ul>
<li>전 단계가 <code>완벽하게</code> 끝나야 하고 모든 결과 문서화</li>
</ul>
</li>
<li><p>제품의 스펙이 거의 바뀌지 않거나 <code>안정성이 아주 중요한 프로젝트</code></p>
<ul>
<li>ex) 10년동안 개발하고 실제 환경에서의 테스트가 불가능한 화성탐사선<h3 id="장점">장점</h3>
</li>
</ul>
</li>
<li><p><code>소프트웨어 개발 공정을 이해</code>하는데 도움</p>
</li>
<li><p><code>단계 별 작업 진행</code>으로 각 단계의 진척 관리 용이</p>
</li>
<li><p>각 공정마다 명확하게 정의된 산출물 존재</p>
</li>
<li><p><code>일정관리 용이</code></p>
</li>
<li><p><code>스펙이 명확</code>하여 산출물의 품질의 명확한 정의</p>
</li>
<li><p>이미 유사 제품의 경험이 있는 경우에 효과를 보임</p>
<h3 id="단점">단점</h3>
</li>
<li><p>폭포는 거슬러 올라갈 수 없듯이, <code>앞 공정으로 되돌아갈 수 없음</code></p>
<ul>
<li>유연하지 못함</li>
</ul>
</li>
<li><p>작성해야할 문서가 지나치게 많음</p>
</li>
<li><p><code>전체적 일정 지연</code></p>
</li>
<li><p>정확한 <code>요구사항 파악 어려움</code></p>
</li>
<li><p>비즈니스 상황에 유연한 대처 X</p>
</li>
<li><p>프로젝트가 끝나기 전까지 진행상황을 거의 보여주지 못함</p>
<ul>
<li>사용자는 자신의 요구대로 만족스러운 제품이 나왔는지를 프로젝트가 끝난 뒤에야 알 수 있음<h2 id="이외의-모델">이외의 모델</h2>
<h3 id="반복-모델">반복 모델</h3>
<img src="https://images.velog.io/images/y_dragonrise/post/be93fc7e-c93e-4a9a-bd8d-10890057eee9/ppt_(2).png" alt="repeat"></li>
</ul>
</li>
<li><p>소프트웨어 프로젝트를 원활하게 진행하기 위해 여러 번에 걸쳐 개발 공정을 반복하여 수행</p>
</li>
<li><p>각 공정을 <code>반복적이고 점진적</code>으로 진행</p>
</li>
<li><p><code>요구사항이 명확</code>함</p>
</li>
<li><p>개발팀이 기술 및 <code>요구사항에 익숙</code>해짐</p>
<ul>
<li><code>우수한 소프트웨어를 개발</code>하는데 도움이 됨</li>
</ul>
</li>
<li><p><code>작은 폭포수 모델</code>을 반복</p>
<ul>
<li>반복 주기마다 <code>시연 가능한 제품을 릴리즈</code>하는 과정을 반복하면서 <code>점진적 향상</code>에 도움<h4 id="장점-1">장점</h4>
</li>
</ul>
</li>
<li><p>반복 릴리즈</p>
<ul>
<li>통합 및 테스트 단계에서 발생할 수 있는 위험요소 분산</li>
</ul>
</li>
<li><p>각 단계 <code>제품 시연</code></p>
<ul>
<li>피드백을 제품에 반영할 수 있음</li>
</ul>
</li>
<li><p><code>비즈니스 상황 변화</code>에 대처 용이</p>
</li>
<li><p><code>요구사항 파악에 용이</code></p>
<h4 id="단점-1">단점</h4>
</li>
<li><p>여러 차례 릴리즈에 들어가는 부수적 비용 부담</p>
</li>
<li><p>사양이 정확하게 정해진 프로젝트에 비효율</p>
<h3 id="xpextreme-programming-모델">XP(eXtreme Programming) 모델</h3>
</li>
<li><p>애자일 소프트웨어 개발 방법론의 하나</p>
</li>
<li><p>고객에게 <code>최고의 가치를 가장 빨리 전달</code>하는 목적</p>
</li>
<li><p><code>요구사항 변화가 자주 일어날 때</code> 효율적임</p>
</li>
<li><p>같은 공간에서 <code>소규모 개발자</code>들이 같이 일할 때 효율적임</p>
</li>
<li><p><code>Simple Is Best</code> 요구</p>
</li>
<li><p>필요할때마다 방향을 바꾸기 위해 </p>
<h4 id="장점-2">장점</h4>
</li>
<li><p>요구사항이 변해도 일정에 영향이 적음</p>
</li>
<li><p><code>작은 프로젝트</code>에 효율적임</p>
</li>
<li><p><code>작은 개발팀</code> 규모에 적합</p>
</li>
<li><p>문서를 최소화</p>
</li>
<li><p>지식공유 용이</p>
<h4 id="단점-2">단점</h4>
</li>
<li><p><code>큰 프로젝트에 부적합</code></p>
</li>
<li><p><code>테스트가 어려운 프로젝트에 사용 불가능</code></p>
</li>
<li><p>빌드 과정이 자동화 되지 않으면 사용이 어려움</p>
</li>
<li><p>테스트가 자동화 되지 않으면 사용하기 어려움</p>
<h3 id="사시미-모델">사시미 모델</h3>
<p><img src="https://images.velog.io/images/y_dragonrise/post/029979e2-8d37-4580-9225-0861632a9226/ALL%20OF%20SOF%20f5e21%201.png" alt="sasimi"></p>
</li>
<li><p><code>폭포수 모델의 변형</code></p>
</li>
<li><p>각 단계의 상당 부분을 <code>중첩하여 진행</code></p>
</li>
<li><p>요구사항 분석 완료 전에 설계 → <code>설계가 완료되기 전에 구현</code></p>
</li>
<li><p>작은 프로젝트를 진행할 때 효과적</p>
<h4 id="장점-3">장점</h4>
</li>
<li><p>문서의 양을 줄일 수 있음</p>
</li>
<li><p>앞 단계의 오류를 빨리 찾을 수 있음</p>
</li>
<li><p><code>위험 요소를 빨리 발견</code>할 수 있음    </p>
<h4 id="단점-3">단점</h4>
</li>
<li><p>각 단계가 애매해져 프로젝트 관리가 어려움</p>
</li>
<li><p>일정이 모호해서 <code>진행사항 파악에 난관</code>을 겪음</p>
</li>
<li><p>여러가지 활동을 동시에 수행 → 프로젝트 진행 혼란, <code>비효율성 초래</code></p>
<h3 id="발전적-프로토타이핑-모델">발전적 프로토타이핑 모델</h3>
</li>
<li><p>프로젝트를 진행하면서 점점 <code>제품의 개념을 잡아감</code></p>
</li>
<li><p>주요 부분 프로토타입 제작 → <code>사용자의 피드백을 반영</code>하면서 점진적으로 제품 발전</p>
</li>
<li><p>요구사항이 분명하지 않거나, <code>변할 가능성이 클 때</code> 용이</p>
</li>
<li><p>고객과 개발자 모두가 <code>익숙하지 않은 분야를 개발</code>하고 있을 때
<img src="https://images.velog.io/images/y_dragonrise/post/187a0536-4ecc-4bfc-9a49-4832115b984c/ALL%20OF%20SOF%20f5e21%202.png" alt="prototype"></p>
<h4 id="장점-4">장점</h4>
</li>
<li><p>요구사항 오류로 인한 <code>문제 감소</code></p>
</li>
<li><p>프로젝트의 위험을 초기에, <code>진행 여부를 조기에 판단 용이</code></p>
</li>
<li><p>작업 진척이 가시적으로 보이므로 <code>고객을 안심</code>시킬 수 있음    </p>
<h4 id="단점-4">단점</h4>
</li>
<li><p>프로젝트 초반에 일정 수립이 어렵고 <code>일정 지연</code>의 위험이 높음</p>
</li>
<li><p>체계적인 설계 부족으로 제품의 <code>아키텍처가 깔끔하지 못함</code></p>
<ul>
<li>이식성이 떨어짐</li>
</ul>
</li>
<li><p>설계에 대한 미비</p>
<ul>
<li><code>성능의 저하</code></li>
</ul>
</li>
<li><p>&#39;<code>일단 짜보고 고치기</code>&#39; 모델의 위험성</p>
<h1 id="개발-단계별-계획을-수립해라">개발 단계별 계획을 수립해라</h1>
</li>
<li><p>모든 개발은 여러 단계를 거쳐 진행</p>
</li>
<li><p><code>빅뱅 테스트(Big bang)</code>
  <img src="https://images.velog.io/images/y_dragonrise/post/94e2e3d5-fab3-4a2a-b0d3-5d5c2aabf491/ALL%20OF%20SOF%20f5e21%203.png" alt="bigbang"></p>
<ul>
<li>개발을 단계적으로 진행하지 않는 회사는 업무와 일정에 대한 정교한 구분없이 일을 진행하다가 적당한 시점에서 <code>한 번의 테스트를 통해 제품을 완성</code>하는 것</li>
<li>운 좋게 개발 기간을 단축시켜 줄지도 모른다는 근거없는 생각과 기대감으로 <code>중구난방 일을 진행</code></li>
<li><code>테스트가 언제 끝날지 예측 불가</code></li>
<li>일정 기간 내에 품질의 향상 추측 불가</li>
<li><code>버그 파악 불가능</code></li>
</ul>
</li>
<li><p>프로젝트를 단계별로 진행 및 관리</p>
<ul>
<li><code>각 단계가 명확</code>해짐</li>
<li><code>프로젝트 진행 상황이 가시적</code>임</li>
<li>혼란으로 인한 재작업 감소, <code>비용 절약</code></li>
</ul>
</li>
<li><p>높은 품질의 제품을 출시하기 위해서?!</p>
<ul>
<li><code>단계별 릴리즈 실행</code></li>
<li>알파, 베타, RC(Release Candidate)<h2 id="개발의-각-단계">개발의 각 단계</h2>
</li>
</ul>
</li>
<li><p>프로젝트 단계는 크게 <code>요구분석</code>, <code>설계</code>, <code>구현</code>, <code>테스트</code>로 나뉨</p>
<h3 id="요구분석-단계">요구분석 단계</h3>
</li>
<li><p>개발에 관련된 모든 내용 검토 및 분석</p>
<ul>
<li>SRS 작성, 프로젝트 계획서 작성, 리스크 분석, 일정 산정 등의 개발 계획 수립</li>
</ul>
</li>
<li><p>프로젝트의 범위와 일정, 진행상의 이유를 명확하게 알 수 있음</p>
<h3 id="설계-단계">설계 단계</h3>
</li>
<li><p>제품의 <code>아키텍처를 의논과 설계</code>를 통해 정하는 단계</p>
</li>
<li><p>제품을 이해하고 구현하는데 있어서 필요한 것들을 표현</p>
<ul>
<li><code>많은 규칙 강요 회피</code></li>
</ul>
</li>
<li><p>바람직한 설계</p>
<ul>
<li>설계를 보고 코딩이 가능한 수준</li>
<li>훌륭한 회사와 보통 회사를 가르는 경계</li>
<li>상세하고 정확한 일정의 수립과 일일빌드가 시작</li>
</ul>
</li>
<li><p>요구분석 단계와 설계단계 사이에 애매모한 겹침 발생</p>
<h3 id="구현-단계">구현 단계</h3>
</li>
<li><p><code>설계에 따른 소스코드 작성</code></p>
</li>
<li><p><code>잘 설계된 제품</code> → 임시계약 직원이라 할지라도 구현할 수 있음</p>
</li>
<li><p><code>일일 소스코드 빌드</code> → 테스트 케이스의 작성 완성</p>
</li>
<li><p>구현단계의 마지막(릴리즈)</p>
<ul>
<li>일반적인 경우 → 알파 버전</li>
<li>규모 혹은 복잡성에 따라서 베타버전 혹은 RC버전 릴리즈<h3 id="테스트-단계">테스트 단계</h3>
</li>
</ul>
</li>
<li><p>제품을 테스트하고 수정을 반복하여 출시 가능한 제품을 만드는 단계
<img src="https://images.velog.io/images/y_dragonrise/post/afd903bd-bf63-4cd5-a1dc-7246ea1d0208/_.png" alt="devel-step"></p>
<ul>
<li><code>프리 알파</code><ul>
<li>알파 이전에 벌어지는 엔지니어링 빌드나 일일빌드</li>
</ul>
</li>
<li><code>알파</code><ul>
<li>기능이 모두 구현됬으나, 버그가 많은 상태</li>
<li>일부 작동이 안되는 기능이 있음</li>
<li>공식적인 버그 등록, 통계</li>
</ul>
</li>
<li><code>베타</code><ul>
<li>중요한 버그는 거의 수정이 되어서 작은 버그들만 남음</li>
<li>사용자 평가 및 외부 테스트를 위해서 외부에 배포하는 단계</li>
<li>베타테스터 선정</li>
</ul>
</li>
<li><code>RC(Relese Candidate)</code><ul>
<li>출시를 위해 만들어진 버전</li>
<li>FCS, 감마 또는 델타라고도 부름</li>
</ul>
</li>
<li><code>GA(General availability)</code><ul>
<li>RTM(Release to Manufacturing)이라고 부름</li>
<li>RC 중에서 테스트를 통과하여 출시 할 수 있는 버전</li>
</ul>
</li>
</ul>
</li>
<li><p>모든 소프트웨어를 개발할 때마다 이 같은 단계를 전부 거쳐야 하는 것은 아님</p>
</li>
<li><p>규모, 난이도, 성격에 따라 다르게 정해야 함</p>
<h1 id="프로젝트-활동을-확실하게-관리하라">프로젝트 활동을 확실하게 관리하라</h1>
<h2 id="프로젝트-성공-기준-마련">프로젝트 성공 기준 마련</h2>
</li>
<li><p>소프트웨어 프로젝트를 성공하기 위해서는 <code>성공의 기준이 무엇인지</code>를 파악
<img src="https://images.velog.io/images/y_dragonrise/post/553cddd3-ca80-4a61-b3ef-49c1781d75ea/ALL%20OF%20SOF%20f5e21%204.png" alt="success"></p>
</li>
<li><p>성공 기준?!</p>
<ul>
<li>자신의 관심사에 따라 다름</li>
<li><code>PM</code> → <code>일정에 맞추어</code> 프로젝트를 완료</li>
<li><code>개발자</code> → 일정이 지연되더라도 <code>기술적으로 보람이 있고 완성도가 높아야 함</code></li>
<li><code>영업자</code> → 고객의 요구사항이 <code>프로젝트에 제대로 반영되었는지</code>의 여부</li>
</ul>
</li>
<li><p>프로젝트 성공 기준의 사전적인 의미?</p>
<ul>
<li>10개월을 예상한 프로젝트가 8개월에 끝났다고 해서 성공적인 프로젝트는 아니다</li>
<li>정해진 기능 이외에 다양하고 화려한 부가 기능을 추가했다고 성공적인 프로젝트는 아니다</li>
<li>스펙대로 만들었다고해도 <code>고객이 만족하지 못한다면 프로젝트가 성공했다 할 수 없다</code>.</li>
</ul>
</li>
</ul>
<blockquote>
<p><code>정해진 일정</code> 안에 <code>정해진 비용</code>으로 <code>정해진 품질</code>의 제품을 만들어서 <code>고객을 만족</code>시킨다</p>
</blockquote>
<ul>
<li>프로젝트에 알맞게 <code>성공 기준</code>을 만들어 개발 계획서에 포함시킨 뒤, 프로젝트 참여자 모두가 알 수 있도록 해야함<ul>
<li>프로젝트 참여자들이 일정이 중요한지, 기술이 중요한지, 고객 만족이 더 중요한지에 대해 생각을 하게 되고, 프로젝트 팀이 더 효율적으로 움직이게 된다.</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>Referenced</strong></p>
</blockquote>
<ul>
<li>[소프트웨어 개발의 모든 것] 중, Chapter 2. 소프트웨어 개발을 성공으로 이끄는 법</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rails - Scaffold ]]></title>
            <link>https://velog.io/@y_dragonrise/Rails-Scaffold</link>
            <guid>https://velog.io/@y_dragonrise/Rails-Scaffold</guid>
            <pubDate>Sat, 26 Mar 2022 07:59:22 GMT</pubDate>
            <description><![CDATA[<h1 id="scaffold-기초">scaffold 기초</h1>
<h2 id="정의">정의</h2>
<ul>
<li>Rails에서 제공하는 CRUD 구현 명령어 방식</li>
<li>뼈대, 기반이라는 뜻을 가지고 있으며, 이 뜻에 걸맞게 CRUD와 더불어 CRUD와 연관된 기본 기능들을 갖춘 프로젝트의 뼈대를 만들어 줌</li>
<li>기존에 작성했던 CRUD 코드보다 더 다양한 기능을 사용할 수 있는 코드를 완성할 수 있음</li>
</ul>
<h1 id="scaffold-실행하기">scaffold 실행하기</h1>
<pre><code class="language-bash">rails new scaffold_app
cd scaffold_app
rails g scaffold Post title:string content:text
rake db:migrate</code></pre>
<ul>
<li>scaffold는 모델을 생성하는 명령어와 다르게 CRUD 기능을 하는 view와, controller, routes도 자동 생성하는 점에서 차이가 있음</li>
</ul>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  root &quot;posts#index&quot;
  resources :posts
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<h1 id="scaffold-이해하기1-restful과-resources">scaffold 이해하기1: RESTful과 resources</h1>
<h2 id="scaffold-자동-생성">scaffold 자동 생성</h2>
<ul>
<li><code>rails g scaffold Post title:string content:text</code> 와 같은 명령어를 실행하면 해당하는 파일을 자동 생성해주며 명령어 하나로 <code>active_record</code>, <code>경로</code>, <code>컨트롤러</code>, <code>뷰파일</code>, <code>helper</code>, <code>jbuilder</code>, <code>assets</code> 등이 자동으로 생성됨</li>
</ul>
<p><code>active_record</code></p>
<ul>
<li>scaffold로 인해 생성한 Post 모델에 관한 부분</li>
</ul>
<p><code>resource_route</code></p>
<ul>
<li>/config/routes.rb 파일에 추가된 경로</li>
</ul>
<p><code>scaffold_controller</code></p>
<ul>
<li>scaffold controller 파일</li>
</ul>
<p><code>erb</code></p>
<ul>
<li>생성되는 뷰 파일들</li>
</ul>
<p><code>jbuilder</code></p>
<ul>
<li>html 형태가 아닌 json 형태로 출력하기 위한 부분</li>
</ul>
<p><code>assets</code></p>
<ul>
<li>scaffold에 필요한 scss나 script 요소들</li>
</ul>
<blockquote>
<p>이와 같이 Model, Controller, View 뿐만 아니라 디자인 요소까지 함께 만들어짐</p>
</blockquote>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  root &quot;posts#index&quot;
  resources :posts
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<ul>
<li><code>resources :posts</code>코드로 8개의 주소가 설정됨.</li>
<li>resources 메서드는 RESTful한 라우트를 생성</li>
<li><code>REST</code><ul>
<li>Representational State Transfer의 약어로 주소(리소스)와 HTTP 메서드를 통해 그 동작의 의미를 표현하는 방법</li>
<li>HTTP 메서드의 조합으로 리소스를 어떻게 할 지 표현하는 방법</li>
</ul>
</li>
</ul>
<h2 id="리소스의-제약조건">리소스의 제약조건</h2>
<ol>
<li>리소스는 동사를 사용하지 않고 명사로 작성<ul>
<li>행위를 표현하지 않고 행위의 주체, 즉 자원만 표현</li>
<li>행위 부분은 HTTP 메서드로 대신</li>
</ul>
</li>
<li>리소스는 콜렉션과 도큐멘트로 이루어짐<ul>
<li>콜렉션을 표현할 땐 복수형으로, 도큐먼트를 표현할 땐 단수형 또는 콜렉션 뒤에 id 값을 입력하여 표현</li>
</ul>
</li>
</ol>
<h1 id="scaffold-이해하기2-controller">scaffold 이해하기2: controller</h1>
<p><code>app/controllers/posts_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

    [...]

  # GET /posts/1
  # GET /posts/1.json
  def show
  end

    [...]

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    [...]
end</code></pre>
<h2 id="before_action">before_action</h2>
<ul>
<li>최상단의 before_action :set_post, only: [:show, :edit, :update, :destroy] 부분을 통해 filter 메서드인 것을 예상할 수 있음</li>
<li><code>filter method</code><ul>
<li>특정 메서드를 액션 직전(before), 직후(after) 또는 모두(arround)에 실행시키는 메서드</li>
</ul>
</li>
<li>액션 직전에 <code>:set_post</code> 실행</li>
<li><code>:set_post</code> 선언부</li>
</ul>
<pre><code class="language-ruby">private
# Use callbacks to share common setup or constraints between actions.
def set_post
    @post = Post.find(params[:id])
end</code></pre>
<ul>
<li>라우트 파라미터를 통해 넘어오는 post의 id 값으로 특정 게시글을 찾아주는 역할 수행</li>
<li>Rails의 controller에서 메소드를 만들면 <code>action method</code>로 생성</li>
<li>action method는 액션의 이름과 동일하게 자동 생성된 view와 연결</li>
<li>view와 연결을 원하지 않을 경우 최상단 블럭에 <code>private</code> 혹은 <code>protected</code> 선언</li>
</ul>
<p><code>only: [:show, :edit, :update, :destroy]</code></p>
<pre><code class="language-ruby">before_action :set_post, only: [:show, :edit, :update, :destroy]
after_action :set_post
before_action :set_post, except: [:show, :edit, :update, :destroy]</code></pre>
<ul>
<li>지정한 action에서만 before_filter를 설정</li>
<li><code>only</code> 설정이 없으면 모든 action에서 filter 적용, <code>except</code>는 지정한 action 이외에 filter 적용</li>
</ul>
<h2 id="respond_to">respond_to</h2>
<pre><code class="language-ruby">def create
    @post = Post.new(post_params)

    respond_to do |format|
        if @post.save
            format.html { redirect_to @post, notice: &#39;Post was successfully created.&#39; }
            format.json { render :show, status: :created, location: @post }
        else
            format.html { render :new }
            format.json { render json: @post.errors, status: :unprocessable_entity }
        end
    end
end</code></pre>
<ul>
<li>서버에서 응답의 종류를 분기하고 싶을 때 사용</li>
<li><code>respond_to do | format |</code> 내부 블록에서 <code>format.type</code> 형식으로 원하는 형식 지정</li>
</ul>
<h2 id="strong-parameter">Strong Parameter</h2>
<pre><code class="language-ruby">def create
    @post = Post.new(post_params)

    [...]
end

[...]

def post_params
    params.require(:post).permit(:title, :content)
end</code></pre>
<ul>
<li><p><code>params.require(:post).permit(:title, :content)</code></p>
<ul>
<li>화이트리스트 방식으로 보안을 설정하는 코드</li>
<li>모델 코드에서 사용자가 입력 가능한 속성을 명시</li>
<li>사용자의 레벨 등 보안 이슈로 인해 입력하면 안 되는 정보들이 클라이언트 측에서 넘어오더라도 컨트롤러에서 그 속성을 명시하지 않았기 때문에 모델의 해당 컬럼은 변경되지 않음</li>
</ul>
</li>
<li><p>설정 방법</p>
<ol>
<li><code>params.require(:모델명)</code>으로 먼저 필터링할 모델 설정</li>
<li><code>.permit(:허용할 컬럼 리스트)</code>들을 작성</li>
</ol>
</li>
<li><p>동작 방식</p>
<ol>
<li><p>서버가 파라미터를 전달 받은 이후 <code>params.require(:post).permit(:title, :content)</code> 코드로 인해 전달 받은 파라미터 형식 </p>
</li>
<li><p><code>{title: &quot;안녕&quot;, content: &quot;하세요&quot;}</code>로 변경</p>
</li>
<li><p>create action에서 아래와 같이 동작</p>
<pre><code class="language-ruby">def create
 @post = Post.new(title: &quot;안녕&quot;, content: &quot;하세요&quot;)

 [...]
end</code></pre>
</li>
</ol>
</li>
</ul>
<h1 id="scaffold-이해하기3-view">scaffold 이해하기3: view</h1>
<h2 id="render">render</h2>
<p><code>app/views/posts/new.html.erb</code></p>
<pre><code class="language-ruby">    &lt;h1&gt;New Post&lt;/h1&gt;

    &lt;%= render &#39;form&#39;, post: @post %&gt;

    &lt;%= link_to &#39;Back&#39;, posts_path %&gt;
    ```
</code></pre>
<p><code>app/views/posts/edit.html.erb</code></p>
<pre><code class="language-ruby">    &lt;h1&gt;Editing Post&lt;/h1&gt;

    &lt;%= render &#39;form&#39;, post: @post %&gt;

    &lt;%= link_to &#39;Show&#39;, @post %&gt; |
    &lt;%= link_to &#39;Back&#39;, posts_path %&gt;
    ```

    - `&lt;=% render &#39;form&#39;, post: @post %&gt;`는 뷰 헬퍼 코드로, 뷰에서 반복되는 부분이 존재할 때 반복되는 부분을 재사용하기 위해 사용
    - 반복되는 부분을 조각 템플릿(partial)로 만든 뒤 이를 메인 템플릿에서 호출하는 방식을 사용
    - prefix → &#39;_&#39;
    - 조각 템플릿 호출 → render 메서드 사용
    `&lt;%= render &quot;조각 파일명&quot; %&gt;`
    - 조각 파일 호출 및 변수 전달
    `&lt;%= render &quot;form&quot;, post: @post %&gt;`와 같이 작성
        - post라는 변수에 @post의 값을 담아 _form 조각 파일에 전달</code></pre>
<h2 id="link_to">link_to</h2>
<ul>
<li>link_to는 a tag의 뷰 헬퍼</li>
<li><code>&lt;%= link_to &#39;Back&#39;, posts_path %&gt;</code></li>
<li><code>&lt;a href=&quot;/posts&quot;&gt;Back&lt;/a&gt;</code><ul>
<li><code>Back</code> a tag 감싸질 요소</li>
<li><code>posts_path</code> 클릭 시 이동하는 주소</li>
</ul>
</li>
<li>Rails는 route에서 생성한 주소를 메서드화 하는데 사용 → 라우트 헬퍼</li>
</ul>
<blockquote>
</blockquote>
<p>💡 라우트 헬퍼 확인하는 법</p>
<ul>
<li>[Terminal]로 확인하기<ol>
<li><code>rake routes</code> 명령어 실행</li>
<li>Prefix 데이터 → 라우트 헬퍼 확인</li>
<li>Rails에서 사용하고 싶다면 끝에 <code>_path</code> 붙여 사용</li>
</ol>
</li>
<li>[브라우저]로 확인<ol>
<li>주소/rails/info/routes로 접속</li>
</ol>
</li>
</ul>
<p><code>app/views/posts/index.html.erb</code></p>
<pre><code class="language-html">    &lt;% @posts.each do |post| %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= post.title %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.content %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= link_to &#39;Show&#39;, post %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= link_to &#39;Edit&#39;, edit_post_path(post) %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= link_to &#39;Destroy&#39;, post, method: :delete, data: { confirm: &#39;Are you sure?&#39; } %&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;% end %&gt;</code></pre>
<p><code>&lt;td&gt;&lt;%= link_to &#39;Show&#39;, post %&gt;&lt;/td&gt;</code></p>
<ul>
<li><code>post</code><ul>
<li>link_to 메서드에 모델 객체를 그대로 사용하면, Rails는 코드를 작성했다는 가정을 하고 그 모델의 특정 데이터를 바라보는 멤버 주소를 호출</li>
<li><code>/posts/:id</code> 주소로 이동</li>
</ul>
</li>
</ul>
<p><code>&lt;td&gt;&lt;%= link_to &#39;Edit&#39;, edit_post_path(post) %&gt;&lt;/td&gt;</code></p>
<ul>
<li><code>edit_post_path(post)</code>는 edit_post_path에서 :id 라우트 파라미터르 받아옴</li>
<li><code>edit_post_path(post.id)</code>로 작성 가능</li>
</ul>
<h2 id="form_with">form_with</h2>
<ul>
<li>form의 뷰헬퍼<br><code>app/views/posts/_form.html.erb</code></li>
</ul>
<pre><code class="language-html">    &lt;%= form_with(model: post, local: true) do |form| %&gt;
      &lt;% if post.errors.any? %&gt;
        &lt;div id=&quot;error_explanation&quot;&gt;
          &lt;h2&gt;&lt;%= pluralize(post.errors.count, &quot;error&quot;) %&gt; prohibited this post from being saved:&lt;/h2&gt;

          &lt;ul&gt;
          &lt;% post.errors.full_messages.each do |message| %&gt;
            &lt;li&gt;&lt;%= message %&gt;&lt;/li&gt;
          &lt;% end %&gt;
          &lt;/ul&gt;
        &lt;/div&gt;
      &lt;% end %&gt;

      &lt;div class=&quot;field&quot;&gt;
        &lt;%= form.label :title %&gt;
        &lt;%= form.text_field :title %&gt;
      &lt;/div&gt;

      &lt;div class=&quot;field&quot;&gt;
        &lt;%= form.label :content %&gt;
        &lt;%= form.text_area :content %&gt;
      &lt;/div&gt;

      &lt;div class=&quot;actions&quot;&gt;
        &lt;%= form.submit %&gt;
      &lt;/div&gt;
    &lt;% end %&gt;</code></pre>
<p><code>form_with</code></p>
<ul>
<li><code>form_authenticate_token</code>과 같이 Rails에서 form을 사용할 때 필요한 설정을 자동 설정</li>
<li>Model 속성에 모델 객체의 값으로 action과 method를 설정</li>
</ul>
<p><code>form_with(model: post, local: true)</code></p>
<ul>
<li>form 요소인 action과 method를 설정</li>
<li>post는 new 액션 → <code>Post.new</code>, edit 액션 → <code>Post.find(params[:id])</code></li>
</ul>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li><a href="https://edu.goorm.io/learn/lecture/16335/%ED%95%9C-%EB%88%88%EC%97%90-%EC%9D%BD%EB%8A%94-%EB%A3%A8%EB%B9%84-%EC%98%A8-%EB%A0%88%EC%9D%BC%EC%A6%88">groomEdu 한 눈에 읽는 루비 온 레일즈</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rails - CRUD]]></title>
            <link>https://velog.io/@y_dragonrise/Rails-CRUD</link>
            <guid>https://velog.io/@y_dragonrise/Rails-CRUD</guid>
            <pubDate>Sat, 26 Mar 2022 07:37:43 GMT</pubDate>
            <description><![CDATA[<h1 id="모델-생성하기">모델 생성하기</h1>
<hr>
<h3 id="crud">CRUD</h3>
<ul>
<li>Create, Read, Update, Destroy의 약자</li>
<li>생성, 읽기, 수정, 삭제 기능을 담당</li>
</ul>
<h3 id="orm">ORM</h3>
<ul>
<li>Object Relational Mapping의 약어</li>
<li>DB 테이블의 관계형 데이터와 객체형 데이터를 연결</li>
<li>DB에 있는 테이블을 클래스화하고 데이터 조작 및 SQL 명령어들을 메서드화</li>
</ul>
<h2 id="1단계-model-class-생성">1단계: Model class 생성</h2>
<pre><code class="language-bash">$ rails g model Post</code></pre>
<ul>
<li><code>rails g model [모델명]</code>으로 작성된 명령어</li>
<li>모델명 → 단수형의 CamelCase</li>
</ul>
<ol>
<li><code>db/migrate/xxx_create_posts.rb</code><ul>
<li>데이터베이스 테이블 필드 등의 정보를 정의할 수 있는 마이그레이션 파일</li>
</ul>
</li>
<li><code>app/model/post.rb</code><ul>
<li>Rails에서 사용할 model</li>
<li>1번 마이그레이션을 통해 생성된 posts 테이블과 연결해서 사용</li>
</ul>
</li>
</ol>
<h3 id="coc-naming-rules">CoC Naming Rules</h3>
<ol>
<li>모델 클래스의 규칙은 단수형의 CamelCas<ul>
<li>첫 글자는 대문자로, 띄어쓰기는 생략하고 그 다음에 오는 문자는 대문자로 설정</li>
<li>ex) <code>POST</code>, <code>PostComment</code></li>
</ul>
</li>
<li>모델 클래스의 파일 이름은 단수형의 snake__case를 사용<ul>
<li>첫 글자는 소문자로, 띄어쓰기 대신 &#39;_&#39;를 사용</li>
<li>ex) <code>post.rb</code>, <code>post_comment.rb</code></li>
</ul>
</li>
<li>테이블의 복수형은 snake_case임<ul>
<li>복수형이라해서 단순하게 모든 단수형에 s만 붙이지 않음</li>
<li>Person이라는 모델을 만들면 table명은 people로 변환</li>
<li>ex) <code>posts</code>, <code>post_comments</code></li>
</ul>
</li>
</ol>
<h2 id="2단계-마이그레이션-파일에서-테이블-정보-작성">2단계: 마이그레이션 파일에서 테이블 정보 작성</h2>
<ul>
<li>Post 모델에 글 제목을 저장할 title 컬럼과 글 내용을 저장할 content 컬럼 생성</li>
</ul>
<pre><code>db/migrate/&amp;&amp;&amp;&amp;&amp;&amp;&amp;_create_posts.rb</code></pre><pre><code class="language-ruby">class CreatePosts &lt; ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
            t.string :title
            t.text :content

      t.timestamps
    end
  end
end</code></pre>
<h2 id="3단계-마이그레이션-파일로-테이블-생성">3단계: 마이그레이션 파일로 테이블 생성</h2>
<pre><code class="language-bash">$ rake db:migrate</code></pre>
<p><code>db/schema.rb</code></p>
<pre><code class="language-ruby">ActiveRecord::Schema.define(version: 2019_09_30_170541) do

  create_table &quot;posts&quot;, force: :cascade do |t|
    t.string &quot;title&quot;
    t.text &quot;content&quot;
    t.datetime &quot;created_at&quot;, null: false
    t.datetime &quot;updated_at&quot;, null: false
  end

end</code></pre>
<ul>
<li><code>ActiveRecord::Schema.define(version: 2019_09_30_170541) do</code>를 통해 version을 확인하면 timestamp가 보이는데 이 부분은 현재 실행된 마이그레이션 파일의 timestamp임</li>
</ul>
<h1 id="create-read-하기">create, read 하기</h1>
<hr>
<ul>
<li>생성할 페이지 안내<ol>
<li>모든 글을 보는 페이지 → index</li>
<li>글 작성 form 페이지 → new</li>
<li>상세 페이지 → show</li>
</ol>
</li>
<li>생성할 action<ol>
<li>index</li>
<li>new</li>
<li>create (글 작성 액션)</li>
<li>show</li>
</ol>
</li>
</ul>
<h2 id="1단계-cr을-할-controller-action-생성">1단계: CR을 할 controller, action 생성</h2>
<pre><code class="language-bash">$ rails g controller posts index new create show</code></pre>
<ul>
<li>자동으로 routesm controller, view 설정</li>
<li><code>create</code>는 view가 필요하지 않으므로 <code>app/views/posts/create.html.erb</code> 삭제</li>
</ul>
<h2 id="2단계-index-만들기-route-action-view-설정">2단계: index 만들기 (route, action, view 설정)</h2>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  # root 주소 추가
  root &#39;posts#index&#39;
  get &#39;posts/index&#39;
  get &#39;posts/new&#39;
  get &#39;posts/create&#39;
  get &#39;posts/show&#39;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<ul>
<li><code>root &#39;posts#index&#39;</code>로 초기 주소 설정</li>
</ul>
<p><code>app/controllers/post_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
  def index
        @posts = Post.all
  end

    [...]
end</code></pre>
<ul>
<li><code>@posts = Post.all</code> 코드로 모든 Post 모델의 데이터를  @posts로 대입</li>
<li>all 메서드 → <code>SELECT * FROM [테이블명]</code>을 실행 후 테이블의 모든 값들을 모델 객체의 배열(ActiveRecord_Replation)로 리턴</li>
</ul>
<p><code>app/views/posts/index.html.erb</code></p>
<pre><code class="language-html">&lt;a href=&quot;/posts/new&quot;&gt;새 글 작성&lt;/a&gt;
&lt;hr/&gt;
&lt;table border=&quot;1&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;제목&lt;/th&gt;
        &lt;th&gt;내용&lt;/th&gt;
        &lt;th&gt;생성일&lt;/th&gt;
        &lt;th&gt;수정일&lt;/th&gt;
    &lt;/tr&gt;
    &lt;% @posts.each do |post| %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= post.id %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.title %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.content %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.created_at %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.updated_at %&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;% end %&gt;
&lt;/table&gt;</code></pre>
<ul>
<li><code>@posts</code> 객체 배열의 내용을 순서대로 출력하기 위해 → each 메서드 사용</li>
<li><code>&lt;%= %&gt;</code> erb 파일에서 Ruby 코드를 실행하지만 출력하지 않을 때 사용 (조건문, 반복문, 변수 할당 등)</li>
</ul>
<h2 id="3단계-new-만들기-route-action-view-설정">3단계: new 만들기 (route, action, view 설정)</h2>
<p><code>app/views/posts/new.html.erb</code></p>
<pre><code class="language-html">&lt;h4&gt;
    새 글 작성
&lt;/h4&gt;
&lt;form action=&quot;/posts/create&quot; method=&quot;POST&quot;&gt;
    &lt;input name=&quot;authenticity_token&quot; value=&quot;&lt;%= form_authenticity_token %&gt;&quot; type=&quot;hidden&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;title&quot;&gt;
    &lt;br/&gt;
    &lt;textarea name=&quot;content&quot;&gt;&lt;/textarea&gt;
    &lt;button&gt;
        제출
    &lt;/button&gt;
&lt;/form&gt;</code></pre>
<ul>
<li><code>&lt;input name=&quot;authenticity_token&quot; value=&quot;&lt;%= form_authenticity_token %&gt;&quot; type=&quot;hidden&quot;&gt;</code> 코드는 CSRF 공격을 대응하는 코드<ul>
<li><code>CSRF</code><ul>
<li>크로스 사이트 요청 위초, 웹사이트 취약점 공격</li>
<li>사용자의 권한 이용, 사용자의 의지와 무관하게 공격자가 의도한 행위를 특정 웹사이트에 요청하게 하는 공격</li>
</ul>
</li>
</ul>
</li>
<li>POST, PUT, DELETE 등의 HTTP 메서드로 요청보낼 때 자동으로 난수화된 토큰을 생성하여 함께 전송</li>
<li>토큰 일치여부에 따른 요청 처리 방식</li>
</ul>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  get &#39;posts/index&#39;
  get &#39;posts/new&#39;
  post &#39;posts/create&#39;
  get &#39;posts/show&#39;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<ul>
<li><code>get &#39;posts/create&#39;</code> 코드를 <code>post &#39;posts/create&#39;</code>로 변경</li>
<li>데이터 저장 요청은 HTTP post 메서드 사용에 더 적합</li>
</ul>
<h2 id="4단계--create-만들기">4단계:  create 만들기</h2>
<p><code>app/controllers/posts_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
  [...]

  def create
      Post.create(title: params[:title], content: params[:content])
      redirect_to &quot;/posts/index&quot;
  end

  [...]
end</code></pre>
<ul>
<li><code>Post.create(title: params[:title], content: params[:content])</code> 코드를 통해서 입력 받은  title과 content의 게시글(Post 모델의 데이터) 생성</li>
<li><code>redirect_to &quot;/posts/index&quot;</code>로 데이터 생성 후 페이지 이동</li>
</ul>
<h2 id="5단계-show-만들기">5단계: show 만들기</h2>
<p><code>app/views/posts/index.html.erb</code></p>
<pre><code class="language-html">&lt;a href=&quot;/posts/new&quot;&gt;새 글 작성&lt;/a&gt;
&lt;hr/&gt;
&lt;table border=&quot;1&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;제목&lt;/th&gt;
        &lt;th&gt;내용&lt;/th&gt;
        &lt;th&gt;생성일&lt;/th&gt;
        &lt;th&gt;수정일&lt;/th&gt;
        &lt;!-- 추가 --&gt;
        &lt;th&gt;링크&lt;/th&gt;
        &lt;!-- 추가 끝 --&gt;
    &lt;/tr&gt;
    &lt;% @posts.each do |post| %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= post.id %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.title %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.content %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.created_at %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.updated_at %&gt;&lt;/td&gt;
            &lt;!-- 추가 --&gt;
            &lt;td&gt;&lt;a href=&quot;/posts/show/&lt;%= post.id %&gt;&quot;&gt;보기&lt;/a&gt;&lt;/td&gt;
            &lt;!-- 추가 끝 --&gt;
        &lt;/tr&gt;
    &lt;% end %&gt;
&lt;/table&gt;</code></pre>
<ul>
<li><code>&lt;a href=&quot;/posts/show/&lt;%= [post.id](http://post.id) %&gt;&quot;&gt;보기&lt;/a&gt;</code>주소를 /posts/show/&lt;%= post.id %&gt;로 설정한 이유<ul>
<li>상세페이지는 라우트 파라미터 방식으로 특정 데이터의 id를 보내기 때문에 이와 같이 작성함</li>
</ul>
</li>
</ul>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  get &#39;posts/index&#39;
  get &#39;posts/new&#39;
  post &#39;posts/create&#39;
    # 추가
  get &#39;posts/show/:id&#39; =&gt; &quot;posts#show&quot;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<ul>
<li><code>get &#39;posts/show/:id&#39; =&gt; &quot;posts#show&quot;</code> 코드로 라우트 파리미터 정의</li>
<li>posts/show/ 뒤에 따라오는 문자는 id에 대입된 뒤 컨트롤러에 전달</li>
<li>라우트 파라미터 정의하는 방식<ul>
<li><code>routes.rb</code>에서 주소 정의 부분에 &#39;:변수명&#39; 규칙을 지켜 작성</li>
<li><code>posts/:post_id/comments/:comment_id</code> 방식처럼 라우트 파라미터 변수를 여러개 추가하는 것이 가능함</li>
</ul>
</li>
</ul>
<p><code>app/controllers/posts_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
    [...]

  def show
      @post = Post.find(params[:id])
  end
end</code></pre>
<ul>
<li><code>@post = Post.find(param[:id])</code> 라이트 파라미터 방식으로 넘어온 <strong>:id</strong> 값을 <strong>param[:id]</strong>로 추출</li>
<li>ex) &quot;/posts/show/1&quot; → <code>params[:id]</code> 는 1이됨</li>
<li>:id  값을 추출한 뒤 모델의 find 메서드로 넘어온 id값을 Post 모델에서 검색, 결과를 <code>@post</code>에 저장<ul>
<li><code>find(val)</code> 메서드<ul>
<li><code>SELECT * FROM [테이블명] WHERE id=val;</code>을 실행</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><code>app/views/posts/show.html.erb</code></p>
<pre><code class="language-html">&lt;p&gt;
    title : &lt;%= @post.title %&gt;
&lt;/p&gt;

&lt;p&gt;
    content : &lt;%= @post.content %&gt;
&lt;/p&gt;

&lt;a href=&quot;/posts/index&quot;&gt;Back&lt;/a&gt;</code></pre>
<h1 id="update-destroy-하기">update, destroy 하기</h1>
<hr>
<ul>
<li>생성할 action 안내<ol>
<li>edit</li>
<li>update (글 수정 액션)</li>
<li>destroy (글 삭제 액션)</li>
</ol>
</li>
</ul>
<h2 id="1단계-edit-만들기">1단계: edit 만들기</h2>
<p><code>app/views/posts/index.html.erb</code></p>
<pre><code class="language-html">&lt;a href=&quot;/posts/new&quot;&gt;새 글 작성&lt;/a&gt;
&lt;hr/&gt;
&lt;table border=&quot;1&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;제목&lt;/th&gt;
        &lt;th&gt;내용&lt;/th&gt;
        &lt;th&gt;생성일&lt;/th&gt;
        &lt;th&gt;수정일&lt;/th&gt;
        &lt;th&gt;링크&lt;/th&gt;
    &lt;/tr&gt;
    &lt;% @posts.each do |post| %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= post.id %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.title %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.content %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.created_at %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.updated_at %&gt;&lt;/td&gt;
            &lt;td&gt;
                &lt;a href=&quot;/posts/show/&lt;%= post.id %&gt;&quot;&gt;보기&lt;/a&gt; 
                &lt;a href=&quot;/posts/edit/&lt;%= post.id %&gt;&quot;&gt;수정&lt;/a&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;% end %&gt;
&lt;/table&gt;</code></pre>
<ul>
<li>글을 수정하는 form을 만들기 위해 글의 정보가 필요하니 edit의 route 주소에 id 값이 필요함</li>
</ul>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  get &#39;posts/index&#39;
  get &#39;posts/new&#39;
  post &#39;posts/create&#39;
  get &#39;posts/show/:id&#39; =&gt; &quot;posts#show&quot;
    # 추가
  get &#39;posts/edit/:id&#39; =&gt; &quot;posts#edit&quot;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<p><code>app/controllers/posts_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
  [...]

  def edit
      @post = Post.find(params[:id])
  end

end</code></pre>
<ul>
<li><code>@post = Post.find(params[:id])</code>를 통해 특정 게시글을 가져옴</li>
</ul>
<p><code>app/views/posts/edit.html.rb</code></p>
<pre><code class="language-html">&lt;h4&gt;
    기존 글 수정
&lt;/h4&gt;
&lt;form action=&quot;/posts/update/&lt;%= @post.id %&gt;&quot; method=&quot;POST&quot;&gt;
    &lt;input name=&quot;authenticity_token&quot; value=&quot;&lt;%= form_authenticity_token %&gt;&quot; type=&quot;hidden&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;&lt;%= @post.title %&gt;&quot;&gt;
    &lt;br/&gt;
    &lt;textarea name=&quot;content&quot;&gt;&lt;%= @post.content %&gt;&lt;/textarea&gt;
    &lt;button&gt;
        수정
    &lt;/button&gt;
&lt;/form&gt;</code></pre>
<ul>
<li><code>&lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;&lt;%= @post.title %&gt;&quot;&gt;</code> 기존 title 값 추가</li>
<li><code>&lt;textarea name=&quot;content&quot;&gt;&lt;%= @post.content %&gt;&lt;/textarea&gt;</code> 기존 content 글 → input과 textarea에 추가</li>
</ul>
<h2 id="2단계-update-하기">2단계: update 하기</h2>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
  [...]
  post &#39;posts/update/:id&#39; =&gt; &quot;posts#update&quot;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<p><code>app/controllers/post_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
  [...]
  def update
      @post = Post.find(params[:id]) #기존 글 검색        
      @post.update(title: params[:title], content: params[:content]) #글 수정
      redirect_to &quot;/posts/show/#{@post.id}&quot; #수정된 게시글 확인을 위해 이동
  end
end</code></pre>
<ul>
<li>큰 따옴표(&quot;&quot;)로 감싼 문자열 안에 변수값을 포함할 수 있음</li>
<li>코드 중간에 등장한 #{} 안에 변수명을 입력하면 문자열 안에 값이 포함됨</li>
</ul>
<h2 id="3단계-destroy-만들기">3단계: destroy 만들기</h2>
<p><code>config/routes.rb</code></p>
<pre><code class="language-ruby">Rails.application.routes.draw do
    [...]
  get &#39;posts/destroy/:id&#39; =&gt; &quot;posts#destroy&quot;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<p><code>app/views/index.html.erb</code></p>
<pre><code class="language-html">&lt;a href=&quot;/posts/new&quot;&gt;새 글 작성&lt;/a&gt;
&lt;hr/&gt;
&lt;table border=&quot;1&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;제목&lt;/th&gt;
        &lt;th&gt;내용&lt;/th&gt;
        &lt;th&gt;생성일&lt;/th&gt;
        &lt;th&gt;수정일&lt;/th&gt;
        &lt;th&gt;링크&lt;/th&gt;
    &lt;/tr&gt;
    &lt;% @posts.each do |post| %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= post.id %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.title %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.content %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.created_at %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= post.updated_at %&gt;&lt;/td&gt;
            &lt;td&gt;
                &lt;a href=&quot;/posts/show/&lt;%= post.id %&gt;&quot;&gt;보기&lt;/a&gt; 
                &lt;a href=&quot;/posts/edit/&lt;%= post.id %&gt;&quot;&gt;수정&lt;/a&gt;
                &lt;!-- 코드 추가 --&gt;
                &lt;a href=&quot;/posts/destroy/&lt;%= post.id %&gt;&quot;&gt;삭제&lt;/a&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;% end %&gt;
&lt;/table&gt;</code></pre>
<ul>
<li>destroy 메서드를 실행하면 id로 검색했던 <code>@post</code>의 데이터를 Post 모델에서 삭제</li>
</ul>
<p><code>app/controllers/post_controller.rb</code></p>
<pre><code class="language-ruby">class PostsController &lt; ApplicationController
  [...]
  def destroy
      @post = Post.find(params[:id])
      @post.destroy
      redirect_to &quot;/posts/index&quot;
  end
end</code></pre>
<ul>
<li>destroy는 SQL에서 <code>DELETE FROM [테이블명] WHERE 조건;</code> 쿼리를 실행하는 것과 같음</li>
</ul>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li><a href="https://edu.goorm.io/learn/lecture/16335/%ED%95%9C-%EB%88%88%EC%97%90-%EC%9D%BD%EB%8A%94-%EB%A3%A8%EB%B9%84-%EC%98%A8-%EB%A0%88%EC%9D%BC%EC%A6%88">groomEdu 한 눈에 읽는 루비 온 레일즈</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rails - concept]]></title>
            <link>https://velog.io/@y_dragonrise/Rails-concept</link>
            <guid>https://velog.io/@y_dragonrise/Rails-concept</guid>
            <pubDate>Sat, 26 Mar 2022 07:35:30 GMT</pubDate>
            <description><![CDATA[<h1 id="rails-app-구조">Rails App 구조</h1>
<h2 id="파일-구조가-복잡한-이유-🙋">파일 구조가 복잡한 이유? 🙋</h2>
<ul>
<li>COC(Convention over Configuration)의 특징을 가지고 있기 때문에 구조를 이루는 요소 각각은 저마다 알맞는 역할을 수행하기 위해 준비됨</li>
</ul>
<h2 id="구조-설명">구조 설명</h2>
<h3 id="1-appcontrollers">1. <code>app/controllers</code></h3>
<ul>
<li>app 디렉토리의 하위 디렉토리인 controllers 안에 생성되는 파일은 Rails의 MVC 패턴에서 controller에 해당하는 코드가 담겨있음</li>
</ul>
<h3 id="2-appviews">2. <code>app/views</code></h3>
<ul>
<li>app 디렉토리의 하위 디렉토리인 view에는 MVC 패턴에서 view에 해당하는 코드가 들어감. Rails에서는 view는 controller 내부의 action과 일대일 매칭되어 설정됨</li>
</ul>
<h3 id="3-appmodels">3. <code>app/models</code></h3>
<ul>
<li>app 디렉토리의 하위 디렉토리인 models는 Rails MVC 패턴에서 model 역할을 수행함. 내부적으로 설정된 데이터베이스와 연동되어서 관련 테이블을 class화 시킨 것이 model이라고 생각하면 됨</li>
</ul>
<h3 id="4-configroutesrb">4. <code>config/routes.rb</code></h3>
<ul>
<li>config 디렉토리에 포함되어 있는 routes.rb 파일은 클라이언트에서 요청하는 URL을 특정 controller의 action과 매칭함</li>
</ul>
<h3 id="5-dbmigrate">5. <code>db/migrate</code></h3>
<ul>
<li>사용자가 model을 사용하려면 Rails 프로젝트와 연결된 데이터베이스에 실제로 테이블을 생성해야 함. 실제 테이블을 만들기 위한 코드들은 db 디렉토리의 하위 디렉토리인 migrate에 파일 형태로 생성.</li>
</ul>
<h3 id="6-dbschemarb">6. <code>db/schema.rb</code></h3>
<ul>
<li>실제로 데이터베이스에 테이블이 생성되면 Rails 프로젝트의 db 디렉토리 하위에 생성되는 파일</li>
</ul>
<h3 id="7-vendorgemfile">7. <code>vendor/Gemfile</code></h3>
<ul>
<li>Ruby에서 라이브러리를 Gem이라고 부르는데 vendor 디렉토리 하위에 포함되는 Gemfile에 작성하여 Rails 프로젝트에 추가할 수 있음.</li>
</ul>
<h1 id="첫-페이지-만들기">첫 페이지 만들기</h1>
<hr>
<h2 id="1단계--controller-생성">1단계 : Controller 생성</h2>
<pre><code class="language-bash"># 터미널 실행 후
&amp; rails generate controller home</code></pre>
<ul>
<li>여기서 generate는 g로 축약 가능함</li>
</ul>
<ol>
<li><p>명령어를 실행 → <code>app/controllers/home_controller.rb</code> 가 생성</p>
</li>
<li><p>index action과 연결할 view 생성</p>
<ul>
<li><code>app/views/home</code> 디렉토리에서 위에서 생성한 index action과 동일한 이름을 가진 <code>index.html.erd</code> 파일 생성</li>
</ul>
<blockquote>
<p>📌 <code>html.erb</code> 파일은 일반 html에 ruby 문법을 사용할 수 있도록 루비를 임베드함
 view 디렉토리의 하위 디렉토리는 controller 이름과 동일하게하고 디렉토리 안에 포함된 파일 이름은 action 이름과 동일하게 맞추면 자동으로 연결됨</p>
</blockquote>
</li>
</ol>
<h2 id="2단계--controller-코드-작성">2단계 : Controller 코드 작성</h2>
<h3 id="home_controllerrb"><code>home_controller.rb</code></h3>
<pre><code class="language-ruby">class HomeController &lt; ApplicationController
    # 코드 추가 시작
  def index
  end
    # 코드 추가 끝
end</code></pre>
<ul>
<li><code>def</code> 와 <code>end</code> 사이에 있는 내용을 <code>action</code>이라고 부르며 이름이 동일한 view와 자동 매칭함</li>
<li>Rails에서 <code>action</code>은 <strong>서비스에서 동작할 수 있는 행동</strong>으로, 행동은 사용자가 볼 수 있는 페이지 또는 동작하는 하나의 로직이 될 수 있음</li>
</ul>
<h2 id="3단계--view-코드-작성">3단계 : View 코드 작성</h2>
<h3 id="indexhtmlerb"><code>index.html.erb</code></h3>
<pre><code class="language-html">&lt;h1&gt;
    hello rails world!!
&lt;/h1&gt;</code></pre>
<h2 id="4단계--route-설정">4단계 : Route 설정</h2>
<h3 id="configroutesrb"><code>config/routes.rb</code></h3>
<pre><code class="language-ruby">Rails.application.routes.draw do
    # 코드 시작
  get &quot;home/index&quot; =&gt; &quot;home#index&quot;
    # 코드 끝
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<ul>
<li>위 코드에서 <code>get &quot;home/index&quot; =&gt; &quot;home#index&quot;</code> 는 아래의 규칙을 기반으로 작성됨</li>
<li>[HTTP method] &quot;uri&quot; ⇒ &quot;controller#action&quot;</li>
</ul>
<blockquote>
<p>👄 &quot;주어진 규칙을 통해 &quot;home/index&quot; 주소에 get 방식으로 요청하면 home 컨트롤러의 index action으로 연결하라&quot;고 해석할 수 있음</p>
</blockquote>
<h2 id="-root-주소로-접근">&quot;/&quot; root 주소로 접근</h2>
<h3 id="configroutesrb-1"><code>config/routes.rb</code></h3>
<pre><code class="language-ruby">Rails.application.routes.draw do
    # 코드 시작
  root &quot;home#index&quot;
    # 코드 끝
  get &quot;home/index&quot; =&gt; &quot;home#index&quot;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<ul>
<li>위 코드에서 root &quot;home#index&quot;는 다음과 같은 규칙을 기반으로 작성됨</li>
<li>[root 주소] controller#action</li>
</ul>
<blockquote>
<p>👄 &quot;root 주소, 즉 &quot;/&quot; 이 주소로 요청하면 home controller의 index action으로 보내라&quot;는 의미</p>
</blockquote>
<h1 id="페이지-이동하기">페이지 이동하기</h1>
<hr>
<h2 id="페이지-이동-선행-설정">페이지 이동 선행 설정</h2>
<ol>
<li>route에서 두개의 다른 주소를 요청 받을 수 있도록 설정</li>
<li>controller에서 두 개의 페이지를 만들 수 있도록 action 두 개 생성</li>
<li>view에서 페이지를 서로 이동할 수 있게 <code>a tag</code>로 연결하기</li>
</ol>
<h2 id="2단계-controller에서-두-개의-페이지를-만들-수-있도록-action-두-개-생성">2단계: controller에서 두 개의 페이지를 만들 수 있도록 action 두 개 생성</h2>
<hr>
<pre><code class="language-ruby">$ rails g controller home index next</code></pre>
<ul>
<li><p><code>rails g controller</code>에 이어 controller 이름을 작성한 뒤 뒤이어 추가 이름 작성하면 그 이름들은 action 이름으로 지정됨</p>
</li>
<li><p><code>app/controllers/home_controller.rb</code> 파일 생성</p>
<pre><code class="language-ruby">  class HomeController &lt; ApplicationController
    # 자동 생성
    def index
    end

    def next
    end
  end    </code></pre>
</li>
<li><p>controller와 action이 연결될 route 주소를 자동으로 설정</p>
</li>
</ul>
<pre><code class="language-ruby">Rails.application.routes.draw do
  get &#39;home/index&#39;
  get &#39;home/next&#39;
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre>
<h2 id="3단계-view에서-페이지를-서로-이동할-수-있게-a-tag로-연결하기">3단계: view에서 페이지를 서로 이동할 수 있게 <code>a tag</code>로 연결하기</h2>
<hr>
<ul>
<li>route와 마찬가지로 controller를 만들 때 action을 함께 생성하면 해당 action과 매칭되는 view 또한 자동 생성됨</li>
</ul>
<h3 id="appviewshomeindexhtmlerb"><code>app/views/home/index.html.erb</code></h3>
<pre><code class="language-html">&lt;h1&gt;Home#index&lt;/h1&gt;
&lt;p&gt;Find me in app/views/home/index.html.erb&lt;/p&gt;

&lt;a href=&quot;/home/next&quot;&gt;home/next로 이동&lt;/a&gt;</code></pre>
<h3 id="appviewshomenexthtmlerb"><code>app/views/home/next.html.erb</code></h3>
<pre><code class="language-html">&lt;h1&gt;Home#next&lt;/h1&gt;
&lt;p&gt;Find me in app/views/home/next.html.erb&lt;/p&gt;

&lt;a href=&quot;/home/index&quot;&gt;home/index로 이동&lt;/a&gt;</code></pre>
<ul>
<li>페이지의 이동 링크의 각각의 주소는 우리가 <code>route.rb</code>에서 자동으로 생성한 주소로 만듦</li>
<li><code>config/routes.rb</code> 파일 수정을 통해 root 설정</li>
</ul>
<pre><code class="language-ruby">    Rails.application.routes.draw do
        root &#39;home#index&#39;
      get &#39;home/index&#39;
      get &#39;home/next&#39;
    end</code></pre>
<h1 id="서버로-데이터-전달">서버로 데이터 전달</h1>
<hr>
<ol>
<li>form을 통해 서버(controller#action)로 데이터 전송</li>
<li>action에 있는 데이터를 연결된 뷰로 전달하여 출력</li>
</ol>
<h2 id="1단계-두개의-페이지form-next-생성">1단계: 두개의 페이지(form, next) 생성</h2>
<pre><code class="language-bash">$ rails g controller home form next</code></pre>
<ul>
<li>터미널을 실행하면 자동으로 routes, controller, view에서 form, next 설정이 완료</li>
</ul>
<h2 id="2단계-form--view에서-next-action으로-데이터-전송">2단계: form  view에서 next action으로 데이터 전송</h2>
<h3 id="appviewshomeformhtmlerb"><code>app/views/home/form.html.erb</code></h3>
<pre><code class="language-html">&lt;h3&gt;
    데이터 전송하기
&lt;/h3&gt;

&lt;form action=&quot;/home/next&quot; method=&quot;GET&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;data_1&quot;&gt;
    &lt;button&gt;
        제출
    &lt;/button&gt;
&lt;/form&gt;</code></pre>
<ul>
<li><code>config/routes.rb</code>에 있는 <code>get &#39;home/next&#39;</code> 코드로 인해 form에서 작성한 데이터는 home controller의 next action으로 전달됨</li>
</ul>
<h2 id="3단계-form에서-보낸-데이터를-next-action에서-view로-전달">3단계: form에서 보낸 데이터를 next action에서 view로 전달</h2>
<h3 id="appcontrollershome_controllerrb"><code>app/controllers/home_controller.rb</code></h3>
<pre><code class="language-ruby">class HomeController &lt; ApplicationController
  def form
  end

  def next
     @data = params[:data_1]
  end
end</code></pre>
<ul>
<li><p><code>@data = params[:data_1]</code>를 통해 form에서 보낸 데이터 수신</p>
</li>
<li><p>params는 클라이언트에서 보낸 요청 정보를 확인하는 메서드</p>
</li>
<li><p>params로 추출할 수 있는 데이터</p>
<p>  <a href="https://www.notion.so/9effc71f88cd419a8be3d3f16454dd19">params로 추출할 수 있는 데이터</a></p>
<ul>
<li><strong>쿼리 파라미터</strong>의 경우 params를 통해 data를 추출함</li>
<li><code>@data</code> 형태의 인스턴스 변수로 생성</li>
</ul>
</li>
</ul>
<h2 id="4단계-next-action에서-보낸-데이터-출력">4단계: next action에서 보낸 데이터 출력</h2>
<h3 id="appviewshomenexthtmlerb-1"><code>app/views/home/next.html.erb</code></h3>
<pre><code class="language-html">&lt;h3&gt;
    받은 데이터
&lt;/h3&gt;

&lt;p&gt;
    &lt;%= @data %&gt;
&lt;/p&gt;</code></pre>
<ul>
<li><code>&lt;%= @data %&gt;</code><ul>
<li><code>&lt;%= %&gt;</code> erb 파일에서 사용할 수 있는 문법으로 화면 출력이 가능함</li>
</ul>
</li>
<li>next action에서 정의했던 <code>@data</code>는 next action과 view를 연결함으로써 view에서 사용할 수 있음</li>
</ul>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>groomEdu 한 눈에 읽는 루비 온 레일즈</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ruby on rails]]></title>
            <link>https://velog.io/@y_dragonrise/Ruby-on-rails</link>
            <guid>https://velog.io/@y_dragonrise/Ruby-on-rails</guid>
            <pubDate>Sat, 26 Mar 2022 07:26:00 GMT</pubDate>
            <description><![CDATA[<h1 id="프레임워크란">프레임워크란?</h1>
<h2 id="라이브러리">라이브러리</h2>
<ul>
<li>개발 생산성을 높이기 위해 사용</li>
<li>반복적으로 사용할 로직을 보편적으로 사용할 수 있도록 라이브러리에 묶어 놓고 필요할 때마다 꺼내어 사용</li>
</ul>
<h2 id="프레임워크">프레임워크</h2>
<ul>
<li>정형화 되어있는 뼈대, 구조</li>
<li>소프트웨어의 구체적인 부분에 해당하는 설계와 구현을 재사용할 수 있게끔 일련의 협업화된 형태로 클래스를 제공하는 것</li>
<li>프로그램의 뼈대가 되는 기반 코드와 설정이 이미 존재하여 그 기반을 토대로 개발자가 원하는 기능을 추가할 수 있는 라이브러리가 통합됨</li>
<li>프로그램이 정상적으로 동작하기 위해 존재하는 가이드라인</li>
</ul>
<h1 id="ruby-on-rails란">Ruby on Rails란?</h1>
<ul>
<li>Ruby로 개발된 오픈소스 웹 프레임워크</li>
</ul>
<h2 id="ruby-on-rails의-특징">Ruby on Rails의 특징</h2>
<ol>
<li>Convention Over Configuration(설정 보다는 규칙)<ul>
<li>개발자가 설정해야 할 요소는 줄이고, 규칙을 제공하여 빠른 개발을 가능하게 함</li>
<li>Rails에서 미리 제공하는 규칙을 지키며 개발하면, 개발자는 정말 필요한 개발 작업에만 집중할 수 있음</li>
<li>초기 Rails의 규칙에 대해 이해해야 하므로 초기 진입 장벽이 높다고 느낄 수 있음</li>
</ul>
</li>
<li>Don&#39;t Repeat Yourself (DRY)<ul>
<li>같은 코드를 반복하지 마라!</li>
<li>사용자가 코드 작성 또는 설정 세팅을 반복하지 않도록 다양한 자동화 옵션을 제공</li>
</ul>
</li>
</ol>
<h1 id="rails-mvc">Rails MVC</h1>
<p><img src="https://images.velog.io/images/y_dragonrise/post/b1da821a-f44f-404b-b40d-9410c5f6cdcf/f472d15e070e9ca2f3456f8a97b9b1a55ee5ce6b5f29025627c900bc69d958a2.jpeg" alt="rails"></p>
<ol>
<li>Model<ul>
<li>모델은 어플리케이션의 정보, 데이터 및 정보와 데이터를 가공하는 규칙까지를 지칭</li>
<li>데이터베이스 테이블과 상호 작용하는 규칙을 관리</li>
</ul>
</li>
<li>View<ul>
<li>View(뷰)는 사용자가 보는 화면, 즉 인터페이스 부분을 지칭</li>
</ul>
</li>
<li>Controller<ul>
<li>Controller(컨트롤러)는 Model과 View를 연결</li>
<li>View에서 사용자가 보낸 요청을 처리, 비즈니스 로직이 필요할 때 Model에서 호출하는 방식으로 사용</li>
</ul>
</li>
</ol>
<blockquote>
<p>MVC 패턴은 유저 인터페이스와 비즈니스 로직을 분리하여 가각의 요소를 수정할 때 서로 영향을 끼치지 않는 장점을 가지고 있고, DRY를 유지하고 코드를 관리하는 데 있어서 편이성을 지니고 있음</p>
</blockquote>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li><a href="https://edu.goorm.io/learn/lecture/16335/%ED%95%9C-%EB%88%88%EC%97%90-%EC%9D%BD%EB%8A%94-%EB%A3%A8%EB%B9%84-%EC%98%A8-%EB%A0%88%EC%9D%BC%EC%A6%88">groomEdu 한 눈에 읽는 루비 온 레일즈</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Gather Town(게더타운) - 맵 내가 만들어 봄]]></title>
            <link>https://velog.io/@y_dragonrise/Gather-Town%EA%B2%8C%EB%8D%94%ED%83%80%EC%9A%B4-%EB%A7%B5-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B4%A4%EB%8B%A4</link>
            <guid>https://velog.io/@y_dragonrise/Gather-Town%EA%B2%8C%EB%8D%94%ED%83%80%EC%9A%B4-%EB%A7%B5-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B4%A4%EB%8B%A4</guid>
            <pubDate>Mon, 21 Mar 2022 13:33:37 GMT</pubDate>
            <description><![CDATA[<h1 id="맵-만들기-완료-🎊">맵 만들기 완료 🎊</h1>
<p>드디어 2<del>3일정도의 기간으로 스터디룸용 맵을 만들었다..
그래서 에너지를 아끼기 위해 맵 만드는 과정은 과감히 생략하고</del> 결과만 올리겠다. </p>
<p><del>대충 아래 링크에서 보고 진행했다.</del>
공식 게더 타운 가이드 링크 참고하기 -&gt; <a href="https://support.gather.town/help">https://support.gather.town/help</a></p>
<p>최대한 게더타운에서 제공하는 기존 템플릿으로 작업하려 했는데, 
하다보니 도저히 기본 샘플로 만들 수 없어서 몇몇 맵은 커스텀으로 제작했다.
직장 동료 디자이너랑 협업하는 과정에서 어깨넘어로 봤던 피그마툴로...</p>
<h2 id="일단-맵-이름-🤷🏻♂️">일단 맵 이름 🤷🏻‍♂️</h2>
<p>영국의 공리주의 제레미 벤담이 고안한 감옥 건축 양식 이름이 문득 생각났다.
너의 이름은.. Panopticon
내부 구조는 파놉티콘이 아니지만 그냥 네이밍 그렇게 정하기로함...
<img src="https://images.velog.io/images/y_dragonrise/post/3a7fd198-580f-4bd2-ad24-e35429cdd02d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.58.39.png" alt="panopticon"></p>
<h2 id="그-다음-공간-분리하기">그 다음 공간 분리하기</h2>
<ul>
<li>공간은 크게 4개 공간으로 나누었다!!<ol>
<li>입장</li>
<li>로비</li>
<li>Fast Zone(오롯히 집중을 하기 위한 사람들만 모인 곳)</li>
<li>Slow Zone(Fast zone보다 덜 숨막히고 유함 - 대충 디자인만 자연 🤔..)</li>
</ol>
</li>
</ul>
<p>자자 선수 입장 ~!
<img src="https://images.velog.io/images/y_dragonrise/post/bf3b166d-1089-493e-850d-5bf4f4201d95/go.gif" width="300" alt="cows" style="display: block; margin: 0 auto"/></p>
<h3 id="입장-했을-때최초-방-입장">입장 했을 때(최초 방 입장)</h3>
<p><img src="https://images.velog.io/images/y_dragonrise/post/2f74ef7b-4ec6-4c4f-aa3e-529a2c2b64f7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.02.51.png" alt="go"></p>
<ul>
<li>정말 순수하게 게더 타운 기본 템플릿으로 만들었다. 아래로 쭈욱 내려가면 본 건물 등장하는데, 입장하는 사람을 위한 별도의 안내서를 만들어야 할 지 고민이다..<h3 id="로비">로비</h3>
<h4 id="작업-전">작업 전</h4>
<img src="https://images.velog.io/images/y_dragonrise/post/2226b120-2264-493b-9877-9c193fb0db06/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.43.17.png" alt="loby-before"></li>
</ul>
<p><del>지금봐도 숨막히는 기본 템플릿, 후우... 기존 템플릿으로 하다가 욕심이 났음... 🥴</del></p>
<h4 id="작업-후">작업 후</h4>
<p><img src="https://images.velog.io/images/y_dragonrise/post/d2d925a4-92cf-483e-ab11-f86f847edcd5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.11.35.png" alt="loby"></p>
<p>그래서 싹 갈아줬다... 😮 이게 되네?</p>
<img src="https://images.velog.io/images/y_dragonrise/post/2ffe6085-5bd0-40f5-8af6-b8d796abc8ec/wow.gif" width="300" alt="wow" style="display: block; margin: 0 auto"/>

<ul>
<li>게더 타운에서는 기본 맵 리소스 이외의 백그라운드 작업을 할 수 있다.</li>
<li>Background image를 내려받아 Figma에서 불러오고 작업을 진행했다.</li>
<li>그 다음 map maker에서 upload image하면 지금 맵에서 덮어 씌어진다.</li>
<li>참고 문서 링크 -&gt; <a href="https://support.gather.town/help/custom-map-overview">https://support.gather.town/help/custom-map-overview</a></li>
</ul>
<p>제일 많이 손이 갔던 공간이었다..
맨 위의 나무 바닥 제외하고 벽면, 바닥을 차도처럼 작업해봤다.</p>
<p>Fast zone, Slow zone 고퀄 벽지는 다운로드 받은 이미지이다.
<img src="https://images.velog.io/images/y_dragonrise/post/8f951ccf-8047-485f-b660-3bb0e8131ff2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.02.32.png" alt="no-more"></p>
<p><del>벽지... 앤티크 인테리어 참고했고, 맨 아래 외부 벽면은 나름 그래피티 넉낌 주려고 한건 의도처럼 보였는지 모르겠다...</del></p>
<h3 id="fast-zone-🏃♀️">Fast Zone 🏃‍♀️</h3>
<p>로비에 너무 힘을 쓴 탓에, 여기서 부터 넉아웃 된 것 같다 🤣
오브젝트 배치, 일부 배경 수정을 진행했다.
바닥 패턴도 벽지도 Figma로 그렸다</p>
<p><img src="https://images.velog.io/images/y_dragonrise/post/c8277f54-cf5c-4fb7-8f82-3ad1425f1421/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.06.38.png" alt="fast-zone"></p>
<p>그래도 막상 캐릭터로 탐방해보니, 한쪽 벽면은 통 유리창 느낌으로 작업해 봤는데 나름 느낌이 괜찮아서 다행이다.. (외부 이미지는 다운로드 이미지임)
<img src="https://images.velog.io/images/y_dragonrise/post/6fc80222-2b2d-41ed-b847-9de38cc6b9cf/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.08.48.png" alt="omg"></p>
<p><img src="https://images.velog.io/images/y_dragonrise/post/e0ba21f3-5345-43cd-a127-0aa0e057b744/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.11.16.png" alt="omg2"></p>
<h3 id="slow-zone-🌿">Slow Zone 🌿</h3>
<p>이 공간은 시간을 너무 지연하면 안 될것 같다는 압박감(?)에 gather town github에서 이미지를 구해서 object 배치만 진행했다.</p>
<ul>
<li>참고 링크 -&gt; <a href="https://github.com/gathertown/mapmaking">https://github.com/gathertown/mapmaking</a></li>
</ul>
<p><img src="https://images.velog.io/images/y_dragonrise/post/4176f9c0-c325-4c56-8190-3fb091f5c818/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.13.55.png" alt="map1"></p>
<p><img src="https://images.velog.io/images/y_dragonrise/post/89b961d9-c821-4c96-b2f4-6f9e8f14bb53/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.14.08.png" alt="map2"></p>
<p><img src="https://images.velog.io/images/y_dragonrise/post/c783278d-b8d6-4173-b7f6-e96bc89100b9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.14.18.png" alt="map3"></p>
<p>개인적으로 너무 맘에 들었던 템플릿이었다.. 
위에 그림 짤렸는데 더 이쁘다..
맵 이름은 &quot;allhandsPosters&quot;로 이 역시도 다운 받아서 게더 타운 맵 메이커에 upload하는 방식으로 진행했다.</p>
<p>혹시나 하는 마음에 돌 노가다를 통해서 &#39;나 길이야&#39;를 표시해뒀다. </p>
<img src="https://images.velog.io/images/y_dragonrise/post/68c7494a-17b8-40ce-b251-28db0b74f514/clap.gif" width="300" alt="wow" style="display: block; margin: 0 auto"/>


<h2 id="결론🚪">결론🚪</h2>
<ul>
<li>웬만하면 기본 템플릿 잘 찾아서 쓰기...<del>(니들은 이런거 하지마라)</del></li>
<li>맵 만들었으니까 운영 계획 확립, 출석체크 기능, 노션 페이지 만들어서 스터디 모집 인원에 대한 안내 작성하기.. 할거 많네 ㅠㅠ</li>
<li>나름 불안함을 극복하고자, 시작했던 작업들.. 부디 유의미한 작업이었길... 🙏</li>
<li>스터디 인원 빨리 모으자...!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Gather Town(게더타운) - 경험담]]></title>
            <link>https://velog.io/@y_dragonrise/Gather-Town%EA%B2%8C%EB%8D%94%ED%83%80%EC%9A%B4-%EA%B2%BD%ED%97%98%EB%8B%B4</link>
            <guid>https://velog.io/@y_dragonrise/Gather-Town%EA%B2%8C%EB%8D%94%ED%83%80%EC%9A%B4-%EA%B2%BD%ED%97%98%EB%8B%B4</guid>
            <pubDate>Sat, 19 Mar 2022 09:49:49 GMT</pubDate>
            <description><![CDATA[<h1 id="렛미인트로듀스-게더타운-🏡">렛미인트로듀스 게더타운 🏡</h1>
<p>스타트업 다니면서 재택근무를 할 때, 
문득 게더타운이라는 플랫폼을 동료에게 소개받았다.
그때 당시에는 픽셀 그래픽으로 게임처럼 캐릭터 커스터마이징도 가능하고 엄청 참신하다고 생각했다.(😃 그냥 개취였음)</p>
<p>수치적으로 봤을 때 게더타운은 311억원의 투자를 유치하면서도 1년도 안되서 170배가 넘는 투자금을 유치했다고 한다. 
진심 어마어마함..</p>
<blockquote>
<p>이렇게 게더타운은 흔히 말하는 <code>메타버스</code>의 역사에 한 획을 긋는 플랫폼이 되는데...</p>
</blockquote>
<p>각설하고 그 이후로, 가끔 회사에서 코로나 이슈때문에 재택근무를 권할 때 종종 사용하곤 했음
이게 뭐라고 진짜 집중 잘됨..</p>
<img src="https://images.velog.io/images/y_dragonrise/post/839bf139-9031-4136-8603-da8a9c40bb9d/giphy.gif" width="300" alt="wow" style="display: block; margin: 0 auto"/>

<h2 id="이렇게-활용을-한다고-한다">이렇게 활용을 한다고 한다...</h2>
<p>각종 커뮤니티 글을 보면 지금처럼 코시국에서는 재택 근무 뿐만 아니라 공부를 하는 사람들도 모여서, 
마치 유튜브의 스터디 위드미 혹은 공스타그램처럼 소규모 인원을 모집하고 손 인증 화면 공유를 킨다고 들었다.</p>
<h2 id="메타버스-코인-타기">메타버스 코인 타기</h2>
<p>그래서 !! 나도 공부를 더 효과적으로 진행하기 위해서, 
취업을 준비하거나 혹은 자기 계발을 위한 분들을 위해서 방을 만들고 운영하는 계획을 진행하고자 한다.
개인적으로 모각코를 장기적으로 경험도 했고, 활용할 게 많은 것 같다고 생각해서 ㄱㄱ</p>
<img src="https://images.velog.io/images/y_dragonrise/post/dd13f84a-5cc8-4a02-a443-442b3f2454f8/giphy%20(1).gif" width="300" alt="come" style="display: block; margin: 0 auto"/>

<h3 id="계획">계획</h3>
<ol>
<li>맵 만들기</li>
<li>기능 추가<ul>
<li>출석체크</li>
<li>방명록</li>
</ul>
</li>
<li>인원 타겟층 설정 - 미확정</li>
<li>인원 모집 및 운영 규정 확립 - 노션 홍보 만들기<h4 id="인원-타겟층-설정-고민-포인트">인원 타겟층 설정 고민 포인트</h4>
인원 타겟층 설정(모각코, 독서실)</li>
</ol>
<ul>
<li>공통 니즈 가설<ul>
<li>혼자하는 것이 싫어서 메타버스를 통해 같이하는 분위기 형성</li>
<li>동기부여 및 자극을 얻는다.</li>
</ul>
</li>
</ul>
<ol>
<li>모각코라면, 서로 TIL 발표를 통해서 인사이트, 동기부여, 자극 느낌<ul>
<li>발표를 꺼려하는 사람이 있을 수 있다</li>
<li>인사이트 공유를 한다면, 특정 취준생에게는 이외의 시간(이력서 작성, 개인 브랜딩)이 없을 수 있다</li>
</ul>
</li>
<li>독서실이라면, 진짜 스터디룸 처럼 설계<ul>
<li>여타 오프라인 스터디룸 참고<ul>
<li>Slow, Fast zone 분류해서 운영</li>
</ul>
</li>
<li>인사이트를 얻고 싶은 같은 분야의 사람들은 slow zone으로, 아닌 사람들은 fast zone으로 분류</li>
<li><strong>이게 낫겠다 싶다</strong></li>
</ul>
</li>
</ol>
<h4 id="실행">실행</h4>
<p>글로 정리하니까 결정이 됨...
실행하자 바로 지금...</p>
<p>PS. 오조 오억년 만에 블로그를 쓰는 데, 게더타운이 복귀 첫 글이 될 줄이야...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🐣 미운 오리 새끼]]></title>
            <link>https://velog.io/@y_dragonrise/%EB%AF%B8%EC%9A%B4-%EC%98%A4%EB%A6%AC-%EC%83%88%EB%81%BC</link>
            <guid>https://velog.io/@y_dragonrise/%EB%AF%B8%EC%9A%B4-%EC%98%A4%EB%A6%AC-%EC%83%88%EB%81%BC</guid>
            <pubDate>Mon, 11 Jan 2021 16:32:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>생각해보니 나의 역경은 정말 축복이었다.
가난했기에 &#39;성냥팔이 소녀&#39;를 쓸 수 있었고,
못생겼다고 놀림을 받았기에 &#39;미운 오리 새끼&#39;를 쓸 수 있었다. 
<strong>동화작가 안데르센</strong></p>
</blockquote>
<h2 id="📭-여는-말">📭 여는 말</h2>
<p>웹 개발자로 인턴 시작 후, 블로그를 오랜만에 작성해본다.
<code>노션</code>이라는 플랫폼을 접하고 블로그에 너무 소홀하지 않았나 싶지만
나의 블로그, 나의 공간에 나의 이야기를 쓰는 것이 맞다고 생각했다.
이 글을 시작으로 매년 회고록을 작성해 볼 계획이다.</p>
<h3 id="💼-첫-직장">💼 첫 직장</h3>
<p>대학 졸업 후, 교수님의 추천을 받아 B2B 기반 전자 교육 컨텐츠(e-learning)를 제작하는 것으로 직장 생활을 시작했다. 
이제는 브라우저에서도 지원하지 않는 어도비 툴로 콘텐츠를 제작해서 제작물을 영상으로 변환하여 납품을 하거나, .swf 확장자의 파일을 import해서 웹 환경에서 제공하는 일을 했다. 
그 당시 빠른 트렌드를 반영하는 B2B 온라인 교육 업계에서는 HTML5, CSS3와 javascript(ECMA5) 혹은 완전한 영상물로 전환을 하는 시기였으므로 내부 회사에서는 마크업을 개인적으로라도 관심을 가져라라는 분위기였다. 
직원들과의 관계는 너무 좋았기 때문에 정상 근무 후에도 스터디 그룹을 가져서 과제를 내주고 돌아가면서 발표하기로 했다.</p>
<p>그때쯤 내가 &#39;웹&#39;이라는 영역 자체를 좋아하기 시작했다.
주말에 시간 쪼개어가며 html과 css 기초 과목을 등록했고, 웹 개발자 도구를 처음 사용하면서 관심에 극에 달했다.</p>
<p>이 시기에 회사가 많이 어려워져 버티지 못하는 상황이 왔고, 웹에 관심이 많아하던 나를 눈여겨본 퇴직한 직장 상사는 웹 영역에 근접하는 다른 회사를 추천해줬다.</p>
<h3 id="🏋️-첫-이직">🏋️‍ 첫 이직</h3>
<p>첫 회사보다는 안정을 찾기를 바랬고, 원하는 분야에 더 근접하는 실무 환경을 가질 수 있다는 기대를 가지고 이직을 했다. 
이직한 회사는 디지털 교과서 컨텐츠를 제작하는 회사로, 첫 회사보다는 거래하는 주 고객사가 안정적이고 나의 실무 경험도 좋게 쌓을 수 있을 듯 했다.
물론 이 회사도 CD로 납품하는 콘텐츠는 플래시였으므로 메인 장기 프로젝트는 혼자서 맡고 서브 단기 프로젝트는 웹 퍼블리싱 업무를 맡았다.</p>
<p>퍼블리싱 업무를 진행하는 도중, 특정 사용자의 데이터를 고객사 DB에 전달하고 API를 호출하는 부분이 있었고, 그때부터 업무 진행 중에 보여지는 화면 말고도 formdata가 어디로 전달되며, 무언가 호출해서 화면에 다시 보여지는 과정이 뭘까? 화면 뒷단에서는 어떤 요청과 응답을 주고 받는 걸까?</p>
<p>&#39;왜? 왜 그렇게 될까?&#39; 지적인 호기심이 가득차 MDN 공식 문서를 들여다 볼 때, 디지털 교과서 사업 지원금이 부족해서 고객사뿐만 아니라 회사도 어려워지는 상황이 되었고 2년간의 커리어는 막을 내렸다.  </p>
<h3 id="🧐-관심-흥미에서-진로까지">🧐 관심, 흥미에서 진로까지</h3>
<p>내가 여태까지 직장생활을 하면서 스스로에게 내뱉었던 질문들은 행동으로 이어지지 않았다. </p>
<p><code>절실하지 않았을까? 정말하고 싶던게 아니였을까?</code></p>
<p>그 동안 회사에 쏟았던 에너지와 나의 지난 날을 돌아보고 답을 얻기까지는 그리 오래 걸리지 않았다.</p>
<p>누구는 말한다. <code>진로 선택에 있어서 &#39;도피처&#39;가 되어서는 안된다고.</code>
누구는 말했다. <code>내가 선택한 이 길이 쉽지 않을거라고.</code></p>
<p>물론 이 길이 기초부터 탄탄하지 않으면, 걸음마조차 내딛을 수 없다고 생각했다.
나 자신에게 증명해보이고 싶은 목표(개발)를 선정했다. </p>
<h3 id="💪-첫-번째-도전">💪 첫 번째 도전</h3>
<p>이 역시, 전 직장에서 개발자 출신의 임원에게 자문을 구했다.
나의 첫번째 목표는 막연하게 자격증 취득으로 정했다고 말했으나(지금 생각하면 너무나도 막연함😳), 
돌아오는 답은 개발 커리어로 큰 이점은 아니고 공무원을 지원하지 않는 이상 도움이 되지 않을거라고 답했다.
지금도 생각하지만, 첫 번째 도전은 결코 조금이나마 진로에 도움이 되는 것을 기대하지도 않았다. 물론 취득하면 좋긴 하지만 우선순위는 아니였다.</p>
<p>결론은 첫 걸음 도전 목표는 달성했다.</p>
<p>필기에 비해 실기가 많이 걱정됐지만 결과는 필기에 비해 실기에서 높은 점수를 받았다.
자격증에는 CS 기초 지식 문제도 있었기에, 교육 기관(학원) 등록 후 시험에 출제되는 언어 기초와 병행하여 공부를 했다.</p>
<h3 id="🏬-교육-기관-선정">🏬 교육 기관 선정</h3>
<h4 id="😭-아쉬움">😭 아쉬움</h4>
<ul>
<li>커리큘럼<ul>
<li>흠... 좀 오래된 표준을 배웠다. 이미 발 빠른 기업에서는 사용하지 않는 표준, 관례고 업무 효율성, 성능으로 따져봤을 때에도 좋지 않은 표준이였다.</li>
</ul>
</li>
<li>사이드 프로젝트<ul>
<li>오늘 배운 내용을 &#39;정리&#39;에 관점을 두지 않고 배운 내용을 &#39;응용&#39;하여 사이드 프로젝트를 뭐든 시작했다면, 자문 구할 사람도 있고 내가 프로젝트를 진행하다가 &#39;도저히 안되겠다.&#39; 싶은 건 바로 자문을 구할 수 있었을 텐데.. 아쉬웠다.</li>
</ul>
</li>
<li>기억보다는 기록을<ul>
<li>TODO list, TIL등 전략적인 계획의 부재가 아쉬움<h4 id="😮💨-그래도-얻은-것">😮‍💨 그래도 얻은 것</h4>
</li>
</ul>
</li>
<li>규칙적인 학습 패턴<ul>
<li>혼자 독학으로 공부를 했다면, 나처럼 생활패턴이 불규칙적인 사람은 마이너스인 요소지만 일정한 생활패턴을 가져올 수 있다는 것은 무시할 수 없는 장점이다.</li>
</ul>
</li>
<li>무엇보다 &#39;다 같이&#39;<ul>
<li>혼자가 아닌 여럿이 같이 집중하고, 같이 무언가를 한다는 건 분야를 막론하고 큰 시너지 효과를 얻을 수 있다. </li>
</ul>
</li>
<li>열정적인 담당자<ul>
<li>오래된 표준을 배웠긴 했으나, 강사님이 귀찮아하는 기색없이 개인적인 질의응답에도 잘 알려주셨다. 이외에 동기부여, 자존감도 많이 push 해주셨다.<h3 id="👥-첫-팀별-프로젝트">👥 첫 팀별 프로젝트</h3>
2020년 첫 해가 막 시작했을 무렵에 교육 기관내 팀을 꾸려 첫 프로젝트를 진행했다. <h4 id="info">INFO</h4>
기간: 2주
주제: 도시락 판매 쇼핑몰
협업: github
스펙: Java, Spring framework, MyBatis, Oracle<h4 id="co-work">CO-WORK</h4>
팀원 내 개개인이 어떤 역할을 맡고 있는지, 데드라인이 언제까지인지 시각적으로 각인시켜줬으며 구글 스프레드시트로 타임 테이블을 만들고 매일 아침에는 Task 및 Issue 위주의 회의를 진행했다.
소스코드 형상관리 툴은 Git으로 협업했으나, 미숙한 Git 실력에 초반에는 자리돌아다니면서 setting 해주느라 바빴다. 후반에는 다른 조에 비해 Task만 집중할 수 있었다. 
<del>다른 팀에서는 USB로 .war 파일을 취합하는 대환장 파티를 볼 수 있었다.</del>
첫 프로젝트를 위해 시간에 구애받지 않고 주말에도 모여서 빈 강의실 찾아 각자 개발을 했고, PT 전날에는 스터디룸을 잡아서 다같이 완성도를 위해 밤샘 작업도 할 정도로 열정있게 진행했다.<h4 id="아쉬움">아쉬움</h4>
</li>
</ul>
</li>
<li>Github 활용 미숙지<ul>
<li>git-flow를 알았다면 더 효율적으로 branch, issue 및 bug, conflict 관리를 할 수 있었을텐데 지금보면 너무 아쉬웠다. </li>
</ul>
</li>
<li>비효율적인 시간 분배<ul>
<li>내 기능은 빨리 끝났지만 조장의 역할을 맡아, 조원의 개발상 오류 및 프론트를 전부 맡다보니 정작 내 기능을 테스트할 시간이 많이 부족했다.</li>
<li>또, 팀 구성상 1명의 부재로 남은 1명은 디버그 또는 발표용 자료 제작을 로테이션으로 진행했다면 많이 촉박하지 않았을 듯하다. </li>
</ul>
</li>
<li>비현실적인 목표<ul>
<li>자료 수집, 벤치 마킹 할 때 완성도 및 난이도 높은 웹 사이트를 목표로 잡다보니 현실과 목표를 구분하지 못했다.<h3 id="💀-시련">💀 시련</h3>
교육 기간을 끝마친 후, 생각에 잠겼다.
나는 분명히 지난 날들을 열정적으로 배움에 자세에 임했고, 강의를 열심히 따라갔으며 시험도 잘 치루고 첫 팀프로젝트도 잘 끝냈다고 생각했다. <blockquote>
<p><strong>그럼에도 불구하고,</strong> 내가 한 선택에는 대답을 쉽게 할 수 있었지만 </p>
</blockquote>
</li>
</ul>
</li>
<li><em>왜*</em> 이렇게 동작하고 <strong>왜</strong> 이렇게 사용하는가 <strong>왜</strong> 쓰이는가? 대답을 할 수 없었다.</li>
</ul>
<p>내가 해왔던 것은 &#39;이렇게, 저렇게 사용하면 돼, 이럴 땐 이렇게 써 저럴 땐 저렇게 써.&#39;</p>
<p>진도를 따라가고 정리한 것에만 급급했다.</p>
<blockquote>
<p>궁극적으로 중요한 것은 <strong>How</strong>가 아니라 <strong>Why?</strong>였다.</p>
</blockquote>
<p>또, 배우면서 왜 시행착오를 겪었는지, 어떻게 해결했는지 전부 어딘가에는 기록하고 정리했어야 했다. 
축적한 데이터가 하나도 없이 &#39;그냥 해결하면 된거지&#39;, &#39;잘 따라가면 돼&#39;에만 치우쳐져 있으니 동일한 문제에 직면했을 때, 기억력에만 의존한 사고방식을 가지고 있던 것이다.
전략적으로 접근해야 한다는 것을 뼈저리게 느끼는 순간이었다.
생각에서만 그칠게 아니라, 내가 직접 서비스를 만들고 나만의 데이터를 구축하는 적극적인 액션이 필요하고 생각했다.</p>
<h3 id="👊-모각코-소모임">👊 모각코, 소모임</h3>
<p>적극적인 액션과 동기부여, 자극을 잡기 위해 모각코 모임에 참여했다.
단기적인 모각코에 그치지 않고, 집중과 몰입을 위해 &#39;소호 사무실&#39;도 따로 두었다.</p>
<h4 id="모각코를-하면서-얻었던-이점">모각코를 하면서 얻었던 이점</h4>
<ol>
<li>개발과 관련된 지식과 인사이트 공유</li>
<li>개개인의 TIL 내용 발표를 통한 자극 및 동기부여</li>
<li>각자의 목표를 달성하기 위한 시너지를 얻음</li>
<li>방향성 및 목표 의식 함양<h4 id="do-action">Do, Action</h4>
</li>
</ol>
<ul>
<li>일주일을 쪼개서 요일 단위로 공부</li>
<li>개인 프로젝트(포트 폴리오) 진행</li>
</ul>
<p>3~4개월의 기간동안, 방향성도 바로 잡게되고 목표 의식도 뚜렷한 시간이었다. </p>
<h3 id="🤠-인턴으로서의-개발-커리어의-시작">🤠 인턴으로서의 개발 커리어의 시작</h3>
<p>청소년을 위한 플랫폼을 개발하는 스타트업이 눈에 들어왔다.
그때 당시, 결과와는 상관없이 개인적으로 좋은 모토를 가진 회사의 대표와 인터뷰 해보고 싶은 마음이 더 커서 편한 마음으로 인터뷰 약속을 주고 받았다. 
회사는 오프라인으로 콘텐츠를 이미 제공하고 있었지만, 장기화된 코로나로 인해 주춤한 상태에서 온라인으로 서비스를 전환 및 확장하기 위해 B2C 기반 서비스를 준비하는 상태였다. 
면접 질문에서는 여태 동안 겪은 수 많은 시행착오와 얻은 것, 준비한 것, 마인드 등 많은 질문이 오갔고, 덩달아 나도 &#39;교육&#39;이라는 공통 분모와 관심이 많이 갔던 포인트, 전략적인 부분 이외에도 회사에 궁금한 점을 많이 물어봤다.
결과는 긍정적인 반응이었고 개발분야의 커리어로써 첫 발걸음을 내딛는다.</p>
<p><strong>Work in progress</strong>
모바일 환경의 어플리케이션을 목표로 예정된 두 개의 서비스 중 한 개의 서비스를 3~4주 정도 개발에 혼자 투입됬으나, 결국 한 개의 서비스에 집중을 하자는 의견으로 모아져서 능력 있는 사수와 함께 개발을 진행중이다.</p>
<p><strong>흐름</strong>
선호하는 언어, 프레임워크는 다르지만 전체적인 흐름은 객체 중심의 개발 방식인 ORM 표준을 채택하고 API 서버를 별도로 두어 호출 응답하는 개발하는 흐름이다.</p>
<p><strong>좋은 것들</strong>
또, 코드 리뷰, 환경 설정, 이슈 공유, 목표 상기, 자극, 동기 부여, 개발 지식 등 이외에도 &#39;같이&#39; 해결하는 협업, 인사이트 등 얻는 것이 많다.</p>
<p><strong>적응</strong>
걱정과는 달리, 스타트업 특유의 자유롭고 개방적인 회사 분위기에 더 빠르게 적응할 수 있었고, 서비스의 공동 목표를 위해 모두가 아이디어를 제시하고 &#39;나&#39;보다는 &#39;팀&#39;의 개념이 인상적이었다.
비로소 &#39;진정한 <code>팀 플레이</code>는 이런 것이구나&#39;라고 느껴졌다. </p>
<h2 id="📫-닫는-말">📫 닫는 말</h2>
<p>회고록을 진행하니, 단순히 기억으로써 지난 날에 그치는게 아니라 아쉬웠던 점이나 준비를 하면서 느끼고 봤던 점 등 조금 더 객관적인 시야가 트이는 계기가 되었고 막연하게 기억되는 게 글로써 정리되니 가치있는 시도를 많이 했다는 생각이 들었다.
도전과 시련을 반복하니, 자존감도 많이 낮아진 상태에서 문득 나는 누군가에게는 <code>미운 오리 새끼</code>가 아니었을까?하는 생각이 많이 들었다.
그런 생각을 할수록 자기 자신을 갉아먹는 느낌이었다.
누가 어떤 생각으로 나를 바라보든, 내가 진짜 하고 싶은 것을 찾고 행복하다면 더 이상 미운 오리 새끼가 아니라는 마음이 들었다.</p>
<p>확고하고 탄탄한 시도를 통해 성공에 가까운 가치를 얻어가는 것.
나는 지금의 팀원들과 같이 걸어가는 길이 결코 가치가 없다고 생각하지 않는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Part03 - control_statement]]></title>
            <link>https://velog.io/@y_dragonrise/JAVA-Part03-controlstatement-ty65h7nw</link>
            <guid>https://velog.io/@y_dragonrise/JAVA-Part03-controlstatement-ty65h7nw</guid>
            <pubDate>Tue, 29 Sep 2020 15:05:03 GMT</pubDate>
            <description><![CDATA[<h2 id="ex01_if">Ex01_if</h2>
<pre><code class="language-java">package com.mywork.ex;
import javax.swing.JOptionPane;

public class Ex01_if {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    if(조건식){
         *      실행문;
         *    }else if(조건식){
         *      실행문;
         *    }else{
         *      실행문;
         *    }
         * 2. 특징
         *   1) else if 문은 없어도 되고, 여러 개가 있을 수 있다.
         *   2) else 문은 없어도 되고, 한 개가 있을 수 있다.
         *   3) 실행문이 하나라면 실행 블록의 중괄호({})는 생략할 수 있다.
         */

        int num = Integer.parseInt(JOptionPane.showInputDialog(&quot;정수를 입력하세요&quot;));

        if(num &gt; 0) {
            JOptionPane.showMessageDialog(null, &quot;양수&quot;);
        }else if(num == 0) {
            JOptionPane.showMessageDialog(null, &quot;ZERO&quot;);
        }else{
            JOptionPane.showMessageDialog(null, &quot;음수&quot;);
        }
    }
}
</code></pre>
<h2 id="ex02_switch">Ex02_switch</h2>
<pre><code class="language-java">package com.mywork.ex;
import javax.swing.JOptionPane;

public class Ex02_switch {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    switch(표현식){
         *      case 값1 : 실행문; break;
         *      case 값2 : 실행문; break;
         *      default : 실행문;
         *    }
         * 2. 특징
         *    1) 표현식의 결과는 정수, 문자, 문자열만 가능하다, 실수는 불가능하다.
         *    2) 실제 사용 예시
         *       switch(var){
         *         case &gt;= 10:     // 불가능!(X)
         *         case 10:        // 가능! (정수)   // 정수만 들어올 수 있다.
         *         case 1.5:        // 불가능!(실수)
         *         case &#39;남&#39;        // 가능! (문자)
         *         case &quot;admin&quot;    // 가능! (문자열)
         *       }
         */

        int age = Integer.parseInt(JOptionPane.showInputDialog(&quot;정수를 입력하세요&quot;));

        switch(age / 10) {   // 필요한 계산식 가능
        case 0:              // break 찾아서 case를 진행해라.
        case 1: JOptionPane.showMessageDialog(null, &quot;미성년자&quot;);
                break;            
        default : JOptionPane.showMessageDialog(null, &quot;성인&quot;);
        }
    }
}
</code></pre>
<h2 id="ex03_while">Ex03_while</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Ex03_while {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    while (조건식){
         *      반복실행문;
         *    }
         * 2. 특징
         *    1) 조건식을 만족하지 않으면 한 번도 실행이 안 될 수 있다.
         *    2) 반복실행문이 없는 경우엔 while(조건식);과 같은 형식으로 사용한다
         *       -&gt; 코드 블럭이 필요 없음.
         *    3) 무한루프는 while (true) { } 과 같은 형식으로 사용한다.
         */

        int num = 0;            // 초기문

        while(num &lt; 10) {         // 조건문 (종료문)
            System.out.println(num);
            num++;                // 초기 -&gt; 종료 (증감)
        }
    }
}
</code></pre>
<h2 id="ex04_do_while">Ex04_do_while</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Ex04_do_while {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    do{
         *      반복실행문;
         *    } while (조건식);
         * 2. 특징
         *    1) 조건식과 관계없이 반드시 한 번은 실행되는 반복문이다.
         *    2) 나머지 특징은 while 문이다.
         */

        int num = 0;
        do {
            System.out.println(num);
            num++;
        }while(num &lt; 10);
    }
}
</code></pre>
<h2 id="ex05_for">Ex05_for</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Ex05_for {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    for (초기문; 조건문; 반복 실행문 후 실행;){
         *      반복실행문;
         *    }
         * 2. 특징
         *  1) 반복의 횟수 또는 범위가 명확한 경우에 사용하는 반복문이다.
         *  2) 주로 배열과 함께 사용된다.
         *  3) 무한루프 for( ; ;) { } 과 같은 형식으로 사용한다.
         *  4) 반복실행문이 없는 경우엔 for(초기문; 조건문; 반복실행문 후 실행);과 같은 형식으로 사용한다
         */

        for(int num = 0; num &lt; 10; num++) {
            System.out.println(num);
        }   // num이 소멸되는 시점

        //System.out.println(num); --&gt; 오류 (main 스코프에서 선언된 num이 없으므로 에러)

        for(int i = 0; i &lt; 10; i++) {
            System.out.println(i);
        }

        for(int i = 0; i &lt; 10; i++) {
            System.out.println(i);
        }
    }
}
</code></pre>
<h2 id="ex06_break">Ex06_break</h2>
<pre><code class="language-java">package com.mywork.ex;
import javax.swing.JOptionPane;

public class Ex06_break {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    while(true){
         *        if(조건식){
         *          break;
         *        }
         *    }
         * 2. 특징
         *    1) 반복문을 곧바로 종료한다.
         *    2) switch 문을 곧바로 종료한다.
         */

        String id;
        while(true) {
            id = JOptionPane.showInputDialog(&quot;ID 입력하세요&quot;);
            if(id.equals(&quot;admin&quot;)) {
                JOptionPane.showConfirmDialog(null, &quot;아이디 일치!&quot;);
                break;
            } else {
                JOptionPane.showConfirmDialog(null, &quot;다시 입력하세요!&quot;);
            }
        }
    }
}
</code></pre>
<h2 id="ex07_continue">Ex07_continue</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Ex07_continue {
    public static void main(String[] args) {
        /*
         * 1. 형식
         *    while(조건식){
         *        반복실행문;
         *        if(조건식){
         *            continue;  // while(조건식) &lt;- 이동!
         *        }
         *        반복실행문;  // continue 가 동작하면 실행되지 않는 영역
         *    }
         *         
         *    for(초기문; 조건식; 반복실행문 후 실행){
         *        반복실행문;
         *        if (조건식){
         *            continue; // for 문의 반복실행문 후 실행 &lt;- 이동!
         *        }
         *        반복실행문;
         *    }
         * 
         *    while(다 먹을때까지){
         *        반찬을 집어라!
         *        if (반찬 == 굴){
         *            continue;
         *        }
         *        반찬을 먹는다!
         *    }
         * 2. 특징
         *  1) 반복에서 제외하고 싶은 데이터를 조건식으로 만들고 continue로 처리한다.
         *  2) while 문과 for 문 계열에 약간의 차이가 있다.
         *
         */

        // 1 ~ 10 출력 (3의 배수는 제외)
        int num = 0;
        while (num &lt;= 10) {
            num++;
            if (num % 3 == 0) {
                continue;
            }
            System.out.println(num);
        }

        // 2. 1 ~ 10출력 (3의 배수는 제외)
        for(num = 1; num &lt;= 10; num ++) {
            if(num % 3 == 0) {
                continue;
            }
            System.out.println(num);
        }
    }
}



</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Part07 - constructor]]></title>
            <link>https://velog.io/@y_dragonrise/JAVA-Part07-constructor-5fg3ubpt</link>
            <guid>https://velog.io/@y_dragonrise/JAVA-Part07-constructor-5fg3ubpt</guid>
            <pubDate>Tue, 29 Sep 2020 15:02:53 GMT</pubDate>
            <description><![CDATA[<h2 id="book">Book</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Book {
    // Field
    String title;
    String writer;
    int price;
    int salesVolume;       // 판매량
    boolean isBestSeller;  // 판매량이 1000 이상이면 true, 아니면 false

    // Constructor
    Book(){    }    // Deafult 
    Book(String _s, int _p){
        title = _s;
        writer = &quot;작가미상&quot;;
        price = _p;
    }
    Book(String _s, String _w, int _p){
        title = _s;
        writer = _w;
        price = _p;
    }

    // Method
    void setSaleVolume(int sales) {
        salesVolume = sales;
        isBestSeller = sales &gt;= 1000 ? true : false;
    }
    void output() {
        System.out.println(&quot;제목 : &quot; + title);
        System.out.println(&quot;저자 : &quot; + writer);
        System.out.println(&quot;가격 : &quot; + price);
        System.out.println(&quot;판매량 : &quot; + salesVolume);
        System.out.println(isBestSeller ? &quot;베스트셀러&quot; : &quot;일반서적&quot;);
    }

}
</code></pre>
<h2 id="bookmain">BookMain</h2>
<pre><code class="language-java">package com.mywork.ex;

public class BookMain {
    public static void main(String[] args) {
        Book book1 = new Book();
        Book book2 = new Book(&quot;콩쥐팥쥐&quot;, 10000);
        Book book3 = new Book(&quot;도전 자바 200문제&quot;, &quot;김자바&quot; ,25000);

        book1.setSaleVolume(0);
        book2.setSaleVolume(500);
        book3.setSaleVolume(1500);

        book1.output();        System.out.println(&quot;-----&quot;);
        book2.output();        System.out.println(&quot;-----&quot;);
        book3.output();
    }
}
</code></pre>
<h2 id="circle">Circle</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Circle {

    // Field
    int x;
    int y;
    double radius;

    // Constructor
    Circle() {
        x = 0;
        y = 0;
        radius = 1;
    }
    Circle(double r) {
        x = 0;
        y = 0;
        radius = r;
    }
    Circle(int _x, int _y, double r) {
        x = _x;
        y = _y;
        radius = r;
    }

    // Method
    double calcArea() {
        return radius * radius * Math.PI;
    }
    double calcCircum() {
        return 2 * Math.PI * radius;
    }
    void output() {
        System.out.println(&quot;중심좌표 : [&quot; + x + &quot;, &quot; + y + &quot;]&quot;);
        System.out.println(&quot;반지름 : &quot; + radius);
        System.out.println(&quot;크기 : &quot; + calcArea());
        System.out.println(&quot;둘레 : &quot; + calcCircum());        
    }
}
</code></pre>
<h2 id="circlemain">CircleMain</h2>
<pre><code class="language-java">package com.mywork.ex;

public class CircleMain {
    public static void main(String[] args) {
        Circle circle1 = new Circle();
        Circle circle2 = new Circle(1.5);
        Circle circle3 = new Circle(3, 3, 2.5);

        circle1.output();
        circle2.output();
        circle3.output();
    }
}
</code></pre>
<h2 id="local">Local</h2>
<pre><code class="language-java">package com.mywork.ex;
public class Local {

    // Field
    String name;
    int age;
    String sn;          // 주민등록번호(식별번호가 1~4는 한국인, 5~8은 외국인, 주민등록번호가 없어도 외국인)
    boolean isKorean;   // 한국인: true, 외국인: false

    // Constructor
    Local(String _name, int _age) {
        name = _name;
        age = _age;
    }
    Local(String _name, int _age, String _sn) {
        name = _name;
        age = _age;
        sn = _sn;
        isKorean = sn.charAt(7) &lt;= &#39;4&#39; ? true : false;
    }
    // Method
    void output() {
        System.out.println(&quot;이름 : &quot; + name);
        System.out.println(&quot;나이 : &quot; + age);
        System.out.println(&quot;주민등록번호 : &quot; + (sn == null ? &quot;없음&quot; : sn));
        System.out.println(isKorean ? &quot;한국인&quot; : &quot;외국인&quot;);
    }

}
</code></pre>
<h2 id="localmain">LocalMain</h2>
<pre><code class="language-java">package com.mywork.ex;

public class LocalMain {
    public static void main(String[] args) {

        Local person1 = new Local(&quot;홍길동&quot;, 20, &quot;901215-1234567&quot;);
        Local person2 = new Local(&quot;응우엔티엔&quot;, 21, &quot;911215-6789123&quot;);
        Local person3 = new Local(&quot;james&quot;, 22);

        person1.output();    System.out.println(&quot;-----&quot;);
        person2.output();    System.out.println(&quot;-----&quot;);
        person3.output();

    }
}
</code></pre>
<h2 id="rect">Rect</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Rect {
    // 1. Fields
    int width;
    int height;
    boolean isSquare;

    // Constructor
    // 1. 생성자이다.
    // 2. 객체(인스턴스)를 생성할 때 호출되는 메소드이다.
    // 3. 객체 초기화 용도로 사용한다.
    // 4. 리턴이 없다.
    // 5. 클래스 명과 같다
    Rect(){
        width = 1;
        height = 1;
        isSquare = true;
    }

    Rect(int side){
        width = side;
        height = side;
        isSquare = true;
    }

    Rect(int w, int h){
        width = w;
        height = h;
        isSquare = (w == h) ? true : false;
    }

    // Method
    void output(){
        System.out.println(&quot;너비 : &quot; + width);
        System.out.println(&quot;높이 : &quot; + height);
        System.out.println(&quot;크기 : &quot; + calcArea());
    }
    int calcArea() {
        return width + height;
    }
}
</code></pre>
<h2 id="rectmain">RectMain</h2>
<pre><code class="language-java">package com.mywork.ex;

public class RectMain {
    public static void main(String[] args) {
        // 1. 객체(인스턴스) 생서
        // ==&gt;&gt;&gt; 생성자가 호출된다!
        Rect nemo1 = new Rect();    // Rect(){} [Default(기본) 생성자] 
                                    //   -&gt; 프로그래머가 만들지 않아도 자바가 자동으로 만들어준다.
        Rect nemo2 = new Rect(3);
        Rect nemo3 = new Rect(3, 5);

        // 2. 객체 메소드 호출
        nemo1.output();
        nemo2.output();
        nemo3.output();
    }

}
</code></pre>
<h2 id="student">Student</h2>
<pre><code class="language-java">package com.mywork.ex;
import java.util.Scanner;

public class Student {

    // Field
    String name;
    String dept;
    String score1;
    String score2;
    double average;
    boolean isPass;

    // Constructor
    Student(String _name, String _dept) {
        name = _name;
        dept = _dept;
    }

    // Method
    void input(Scanner scanner) {
        System.out.print(&quot;중간 &gt;&gt; &quot;);
        score1 = scanner.nextLine();
        System.out.print(&quot;기말 &gt;&gt; &quot;);
        score2 = scanner.nextLine();
        average = (Double.parseDouble(score1) + Double.parseDouble(score2)) / 2;
        isPass = average &gt;= 80 ? true : false;
    }
    void output() {
        System.out.println(&quot;이름 : &quot; + name);
        System.out.println(&quot;학과 : &quot; + dept);
        System.out.println(&quot;평균 : &quot; + average);
        System.out.println(&quot;결과 : &quot; + (isPass ? &quot;합격&quot; : &quot;불합격&quot;));
    }

}
</code></pre>
<h2 id="studentmain">StudentMain</h2>
<pre><code class="language-java">package com.mywork.ex;
import java.util.Scanner;

public class StudentMain {
    public static void main(String[] args) {

        Student student = new Student(&quot;홍길동&quot;, &quot;컴퓨터공학과&quot;);
        student.input(new Scanner(System.in));
        student.output();

    }
}
</code></pre>
<h2 id="triangle">Triangle</h2>
<pre><code class="language-java">package com.mywork.ex;

public class Triangle {
    // Field
    int width;
    int height;

    // Constructor
    Triangle(){
        width = 1;
        height = 1;
    }
    Triangle(int w, int h){
        width = w;
        height = h;
    }
    // Method
    double calcArea() {
        return width * height / 2.0;
    }
    void output() {
        System.out.println(&quot;넓이 : &quot; + width);
        System.out.println(&quot;높이 : &quot; + height);
        System.out.println(&quot;크기 : &quot; + calcArea());
    }
}
</code></pre>
<h2 id="trianglemain">TriangleMain</h2>
<pre><code class="language-java">package com.mywork.ex;

public class TriangleMain {
    public static void main(String[] args) {
        Triangle semo1 = new Triangle();
        Triangle semo2 = new Triangle(1, 3);
        semo1.output();
        semo2.output();
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[상태 패턴(State Pattern)]]></title>
            <link>https://velog.io/@y_dragonrise/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%83%81%ED%83%9C-%ED%8C%A8%ED%84%B4State-Pattern</link>
            <guid>https://velog.io/@y_dragonrise/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%83%81%ED%83%9C-%ED%8C%A8%ED%84%B4State-Pattern</guid>
            <pubDate>Tue, 29 Sep 2020 14:19:19 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<ul>
<li>어떤 행위를 수행할 때 상태에 행위를 수행하도록 위임</li>
<li>시스템의 각 상태를 클래스로 분리해 표현</li>
<li>각 클래스에서 수행하는 행위들을 메서드로 구현</li>
<li>외부로부터 캡슐화하기 위해 인터페이스를 생성하여 시스템의 각 상태를 나타나는 클래스로 실체화</li>
</ul>
<p><img src="https://images.velog.io/images/y_dragonrise/post/b0cd2535-b0f8-4aa6-8fdc-7c1c164e89b2/image.png" alt="state"></p>
<ul>
<li><code>State</code>: 시스템의 모든 상태에 공통의 인터페이스를 제공한다. 따라서 이 인터페이스를 실체화한 어떤 상태 클래스도 기존 상태 클래스를 대신해 교체해서 사용할 수 있다.</li>
<li><code>State1, State2, State3</code>: Context 객체가 요청한 작업을 자신의 방식으로 실제 실행한다. 대부분의 경우 다음 상태를 결정해 상태 변경을 Context 객체에 요청하는 역할도 수행한다.</li>
<li><code>Context</code>: State를 이용하는 역할을 수행한다. 현재 시스템의 상태를 나타내는 상태 변수 (state)와 실제 시스템의 상태를 구성하는 여러 가지 변수가 있다. 또한 각 상태 클래스에서 상태 변경을 요청해 상태를 바꿀 수 있도록 하는 메서드(setState)가 제공된다. Context 요소를 구현한 클래스의 request 메서드는 실제 행위를 실행하는 대신 해당 상태 객체에 행위 실행을 위임한다.</li>
</ul>
<h3 id="상태-머신-다이어그램">상태 머신 다이어그램</h3>
<ul>
<li>UML에서의 상태와 상태 변화를 모델링하는 도구
<img src="https://images.velog.io/images/y_dragonrise/post/2e06c287-60dc-42b9-95fb-1780296bd54d/image.png" alt="windmill"></li>
<li>바람 세기를 선택하거나 회전 등을 할 수 없고 정해진 바람 세기로만 동작하는 선풍기(단순한 기능)</li>
<li>사각형: <code>상태(state)</code></li>
<li>화살표: 전이(state transition)</li>
</ul>
<blockquote>
<p><code>상태(state)</code></p>
</blockquote>
<ul>
<li>객체가 시스템에 존재하는 동안, 즉 객체의 라이프 타임 동안 객체가 가질 수 있는 어떤 조건이나 상황</li>
<li>ex) 객체가 어떤 상태에 있는 동안 어떤 액티비티 등을 수행하거나 특정 이벤트 발생을 기다리는 것</li>
<li>시작 상태: 객체가 시작하는 처음 상태<ul>
<li>시작 상태에서의 진입은 객체를 새로 생성하는 이벤트만 명시하거나 아예 어떤 것도 명시하지 않아야 함</li>
</ul>
</li>
<li>상태 진입: 객체의 한 상태에서 다른 상태로 이동하는 것<ul>
<li>특정 이벤트가 발생한 후 명세된 조건을 만족한 경우에 이루어진다.</li>
</ul>
</li>
</ul>
<h3 id="해석">해석</h3>
<ul>
<li>선풍기는 기본적으로 OFF 상태에서 시작한다.</li>
<li>OFF 상태에서 사용자가 선풍기 스위치를 켜면 switch_on 이벤트를 발생시킨다. 이때 전원이 들어온 상태라면(power_exists 조건) ON 상태로 진입한다. 이때 turnon 액션을 실행하게 된다.</li>
<li>OFF 상태에서 사용자가 선풍기 스위치를 켜면 switch_on 이벤트를 발생시킨다. 이때 전원이 들어오지 않은 상태라면(power_exists 조건) OFF 상태에 머무른다.</li>
<li>사용자가 ON 상태에서 동작 버튼을 누르면 run 이벤트를 발생시키고 WORKING 상태로 진입한다. 이때 operate 액션을 실행하게 된다.</li>
<li>선풍기가 ON 상태나 WORKING 상태에 머무를 때 사용자가 스위치를 끄면 switch_off 이벤트가 발생하고 이 이벤트로 인해 OFF 상태로 진입한다.</li>
</ul>
<h3 id="형광등-만들기">형광등 만들기</h3>
<h4 id="전제조건">전제조건</h4>
<ul>
<li><p>형광등(Light 클래스)을 만들려면 형광등의 행위를 분석할 필요가 있다.</p>
</li>
<li><p>꺼져 있을 때 On 버튼을 누르면 켜지고, 켜져 있을 때 Off 버튼을 누르면 꺼진다.</p>
</li>
<li><p>만약 켜져 있는 상태에서 On 버튼을 누르면 그대로 켜져 있고, 꺼져 있는 상태에서 Off 버튼을 눌러도 아무런 변화가 없다.
<img src="https://images.velog.io/images/y_dragonrise/post/a46ca53f-6961-48cf-b7d2-1475a4e652ed/image.png" alt="light1"></p>
</li>
<li><p>OFF, ON: 형광등의 상태</p>
</li>
<li><p>off_button_pushed, on_button_pushed: 형광등의 Off 버튼과 On 버튼의 상태</p>
<pre><code class="language-java">private static int ON = 0;
private static int OFF = 1;</code></pre>
</li>
<li><p>형광등의 상태를 저장하는 변수</p>
<pre><code class="language-java">private int state;</code></pre>
</li>
</ul>
<h3 id="구현">구현</h3>
<h4 id="light-클래스">Light 클래스</h4>
<pre><code class="language-java">public class Light{
    private static int ON = 0; // 형광등이 켜진 상태
    private static int OFF = 1; // 형광등이 꺼진 상태
    pricate int state; // 형광등의 현재 상태

    public Light(){
        state = OFF; // 형광등 초기 상태는 꺼져 있는 상태임
    }

    public void on_button_pushed(){
        if( state == ON ){
            System.out.println(&quot;반응 없음&quot;);
        }
        else { // 형광등이 꺼져 있을 때 On 버튼을 누르면 켜진 상태로 전환
            System.out.println(&quot;Light On!&quot;);
            state = ON;
        }
    }

    public void off_button_pushed(){
        if( state == OFF) {
            System.out.println(&quot;반응 없음&quot;);
        }
        else { // 형광등이 켜져 있을 때 OFF 버튼을 누르면 꺼진 상태로 전환됨
            System.out.println(&quot;Light Off!&quot;);
            state = OFF;
        }
    }
}</code></pre>
<h4 id="client-클래스">Client 클래스</h4>
<pre><code class="language-java">public class Client{
    public static void main(String[] args){
        Light light = new Light();
        light.off(); // 반응 없음
        light.on();
        light.off();
    }
}</code></pre>
<h4 id="문제점">문제점</h4>
<ul>
<li>형광등에 새로운 상태를 추가할 떄, 가령 형광등에 &#39;취침등&#39; 상태를 추가하려면?</li>
</ul>
<h3 id="설계">설계</h3>
<p><img src="https://images.velog.io/images/y_dragonrise/post/0432b761-6cc9-4d9f-9daa-6437caaaa110/image.png" alt="light2"></p>
<ul>
<li>취침등 상태를 나타내는 상수인 SLEEPING를 추가</li>
</ul>
<pre><code class="language-java">private static int SLEEPING = 2;</code></pre>
<ul>
<li>on_button_pushed 상태와 off_button_pushed 메서드 안에서 현재 상태 값이 SLEEPING 변수 값과 같은지를 검사하고 값이 같다면 요구사항에 맞게 수정</li>
</ul>
<pre><code class="language-java">public void on_button_pushed(){
    if(state == ON) { // 형광등이 켜져 있는 경우에 On 버튼을 누르면 취침등 상태로 전환됨
        System.out.println(&quot;취침등 상태&quot;);
        state = SLEEPING;
    }
    else if(state == SLEEPING) { // 형광등이 취침등 상태에 있는 경우
        System.out.println(&quot;Light On!&quot;); // On 버튼을 누르면 켜진 상태로 전환됨
        state = ON;
    }
    else { // 상태가 꺼져 있는 경우에 On 버튼을 누르면 켜진 상태로 전환됨
        System.out.println(&quot;Light On!&quot;);
        state = ON;
    }
}</code></pre>
<h3 id="요구사항-반영">요구사항 반영</h3>
<pre><code class="language-java">public class Light{
    private static int ON = 0;
    private static int OFF = 1;
    private static int SLEEPING = 2;
    private int state;

    public Light(){
        state = OFF; // 초기 상태는 형광등이 꺼져 있는 상태
    }

    public void off_button_pushed(){
        if(state == OFF) { // 형광등이 꺼져 있는 경우에 OFF 버튼을 누르면 상태 전환 없음
            System.out.println(&quot;반응 없음&quot;);
        }
        else if(state == SLEEPING) { // 형광등이 취침등 상태에 있는 경우
            System.out.println(&quot;Light OFF!&quot;); // Off 버튼을 누르면 OFF로 전환됨
            state = OFF;
        }
        else {
            System.out.println(&quot;Light Off!&quot;);
            state = OFF;
        }
    }
}

public void on_button_pushed(){
    if(state == ON){ // 형광등이 켜져 있는 경우에 On 버튼을 누르면 취침등 상태로 전환됨
        System.out.println(&quot;취침등 상태&quot;);
        state = SLEEPING;
    } 
    else if(state == SLEEPING){ // 형광등이 취침등 상태에 있는 경우
        System.out.println(&quot;Light On!&quot;);
        state = ON;
    }
    else { // 꺼져 있는 상태라면 On 버튼을 눌렀을 때 켜진 상태로 전환됨
        System.out.println(&quot;Light On!&quot;);
        state = ON;
    }
}</code></pre>
<ul>
<li>새로운 상태가 추가되는 경우에 상태 변화를 초래하는 모든 메서드에 이를 반영하기 위해 코드 수정은 불가피함</li>
</ul>
<h4 id="해결책">해결책</h4>
<ul>
<li>무엇이 변하는가?</li>
<li>변하는 것에 따른 캡슐화</li>
<li>상태 변화에 독립적으로 코드를 수정하는게 목표</li>
<li>상태를 클래스로 분리</li>
<li>의존적인 행위도 상태 클래스에 두어 특정 상태에 따른 행위 구현</li>
</ul>
<h3 id="개선된-설계-구현">개선된 설계, 구현</h3>
<p><img src="https://images.velog.io/images/y_dragonrise/post/587e0780-77e3-4c96-bf61-44bf2fd2b400/image.png" alt="stateMachineDiagram"></p>
<ul>
<li><a href="https://velog.io/@y_dragonrise/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4Strategy-Pattern">스트래티지 패턴</a>과 구조가 매우 흡사함</li>
<li>Light 클래스에서 구체적인 상태 클래스가 아닌 추상화된 State 인터페이스만 참조하므로 현재 어떤 상태에 있는지와 무관하게 코드를 작성할 수 있음</li>
<li>Light 클래스에서는 상태 클래스 작업만 위임하면 됨</li>
</ul>
<h4 id="state-인터페이스">State 인터페이스</h4>
<pre><code class="language-java">interface State{
    public void on_button_pushed(Light light);
    public void off_button_pushed(Light light);
}
</code></pre>
<h4 id="on-클래스">ON 클래스</h4>
<pre><code class="language-java">public class ON implements State{
    public void on_button_pushed(Light light){
        System.out.println(&quot;반응 없음&quot;);
    }

    public void off_button_pushed(Light light){
        System.out.println(&quot;Light Off!&quot;);
        light.setState(new OFF(light));
    }
}</code></pre>
<h4 id="off-클래스">OFF 클래스</h4>
<pre><code class="language-java">public class OFF implements State{
    public void on_button_pushed(Light light){
        System.out.println(&quot;Light On!&quot;);
        light.setState(new ON(light));
    }

    public void off_button_pushed(Light light){
        System.out.println(&quot;반응 없음&quot;);
    }
}</code></pre>
<h4 id="light-클래스-1">Light 클래스</h4>
<pre><code class="language-java">public class Light{
    private State state;

    public Light(){
        state = new OFF();
    }

    public void setState(State state){
        this.state = state;
    }

    public void on_button_pushed(){
        state.on_button_pushed(this);
    }

    public void off_button_pushed(){
        state.off_button_pushed(this);
    }
}</code></pre>
<ul>
<li>state 변수를 통해 현재 시스템의 상태 객체를 참조</li>
<li>Light 클래스는 시스템이 어떤 상태에 있는지 무관</li>
</ul>
<h4 id="현-코드의-문제점">현 코드의 문제점</h4>
<ul>
<li>상태 변화가 생길 때마다 새로운 상태 객체 생성<ul>
<li>메모리 낭비, 성능 저하 야기</li>
</ul>
</li>
</ul>
<h3 id="개선된-싱글턴-패턴-on-off-클래스로의-변경">개선된 싱글턴 패턴 ON, OFF 클래스로의 변경</h3>
<h4 id="on-클래스-1">ON 클래스</h4>
<pre><code class="language-java">public class ON implements State{
    private static ON on = new ON(); // ON 클래스의 인스턴스로 초기화됨
    private ON() { }

    public static ON getInstance() { // 초기화된 ON 클래스의 인스턴스를 반환함
        return on;
    }

    public void on_button_pushed(Light light){ // ON 상태일 때 On 버튼을 눌러도 변화 없음
        System.out.println(&quot;반응 없음&quot;);
    }

    public void off_button_pushed(Light light){
        light.setState(OFF.getInstance());
        System.out.println(&quot;Light Off!&quot;);
    }
}</code></pre>
<h4 id="off-클래스-1">OFF 클래스</h4>
<pre><code class="language-java">public class OFF implements State{
    private static OFF off = new OFF(); // OFF 클래스의 인스턴스로 초기화됨
    private OFF() { }

    public static OFF getInstance() { // 초기화된 OFF 클래스의 인스턴스를 반환함
        return off;
    }

    public void on_button_pushed(Light light){ // Off 상태일 때 On 버튼을 눌러도 On 상태임
        light.setState(ON.getInstance());
        System.out.println(&quot;Light On!&quot;);
    }

    public void off_button_pushed(Light light){ // Off 상태일 때 Off 버튼을 눌러도 변화 없음
        System.out.println(&quot;반응 없음&quot;);
    }
}</code></pre>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>정인상,채흥석, 『JAVA 객체 지향 디자인 패턴』, 한빛미디어(2014.4.2), 218p~232p</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[전략 패턴(Strategy Pattern)]]></title>
            <link>https://velog.io/@y_dragonrise/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4Strategy-Pattern</link>
            <guid>https://velog.io/@y_dragonrise/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4Strategy-Pattern</guid>
            <pubDate>Tue, 29 Sep 2020 14:09:50 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<ul>
<li><p><code>전략</code>을 쉽게 바꿀 수 있도록 해줌</p>
</li>
<li><p>같은 문제를 해결하는 여러 알고리즘이 클래스별로 캡슐화되어 있고 이들이 필요할 때 교체할 수 있도록 함으로써 동일한 문제를 다른 알고리즘으로 해결할 수 있게 하는 디자인 패턴</p>
</li>
</ul>
<blockquote>
<p><code>전략</code>
어떤 목적을 달성하기 위해 일을 수행하는 방식, 비즈니스 규칙, 문제를 해결하는 알고리즘
ex) 게임 프로그래밍에서 게임 캐릭터가 자신이 처한 상황에 따라 공격이나 행동하는 방식을 바꾸고 싶을 때</p>
</blockquote>
<p><img src="https://images.velog.io/images/y_dragonrise/post/01b02920-5e7d-4a90-b5be-7cdfe0f6091d/image.png" alt="strategy1"></p>
<ul>
<li><p><code>Strategy</code>: 인터페이스나 추상 클래스로 외부에서 동일한 방식으로 알고리즘을 호출하는 방법을 명시</p>
</li>
<li><p><code>ConcreateStrategy1, 2, 3</code>: 스트래티지 패턴에서 명시한 알고리즘을 실제로 구현한 클래스</p>
</li>
<li><p><code>Context</code>: 스트래티지 패턴을 이용하는 역할 수행. 필요에 따라 동적으로 구체적인 전략을 바꿀 수 있도록 setter 메서드 제공</p>
</li>
</ul>
<h3 id="로봇-만들기">로봇 만들기</h3>
<h4 id="설계">설계</h4>
<p><img src="https://images.velog.io/images/y_dragonrise/post/7257712b-7f85-4fc6-9de8-a20c60b17a44/image.png" alt="robot strategy1"></p>
<ul>
<li>추상 클래스 Robot의 자식 클래스: Atom 클래스, TaekwonV 클래스</li>
<li>추상 클래스 Robot의 추상 메서드 정의: attack method(), move method()</li>
</ul>
<h4 id="구현">구현</h4>
<h4 id="robot-추상-클래스">Robot 추상 클래스</h4>
<pre><code class="language-java">public abstract class Robot{
    private String name;
    public Robot(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public abstract void attack();
    public abstract void move();
}</code></pre>
<h4 id="taekwonv-구현-클래스">TaekwonV 구현 클래스</h4>
<pre><code class="language-java">public class TaekwonV extends Robot{
    public TaekwonV(String name){
        super(name);
    }

    public void attack(){
        System.out.println(&quot;I have Missile and can attack with it.&quot;);
    }

    public void move(){
        System.out.println(&quot;I can only walk.&quot;);
    }
}</code></pre>
<h4 id="atom-구현-클래스">Atom 구현 클래스</h4>
<pre><code class="language-java">public class Atom extends Robot{
    public Atom(String name){
        super(name);
    }

    public void attack(){
        System.out.println(&quot;I have strong punch and can attack with it.&quot;);
    }

    public void move(){
        System.out.println(&quot;I can fly.&quot;);
    }
}</code></pre>
<h4 id="client-클래스">Client 클래스</h4>
<pre><code class="language-java">public class Client{
    public static void main(String[] args){
        Robot taekwonV = new TaekwonV(&quot;TaekwonV&quot;);
        Robot atom = new Atom(&quot;Atom&quot;);

        System.out.println(&quot;My name is &quot; + taekwonV.getName());
        taekwonV.move();
        taekwonV.attack();

        System.out.println();

        System.out.println(&quot;My name is &quot; + atom.getName());
        atom.move();
        atom.attack();
    }
}</code></pre>
<h4 id="문제점">문제점</h4>
<h4 id="새로운-기능-수정의-경우">새로운 기능 수정의 경우</h4>
<ul>
<li><p>기존 로봇의 공격 또는 이동 방법을 수정하려면 어떤 변경 작업을 해야 하는가?</p>
<ul>
<li>ex) 아톰이 날 수는 없고 오직 걷게만 만들고 싶다면?, 태권V를 날게 하려면?</li>
</ul>
</li>
<li><p>새로운 로봇을 만들어 기존의 공격 또는 이동 방법을 추가하거나 수정하려면?</p>
<ul>
<li>ex) 새로운 로봇으로 지구의 용사 선가드를 만들어 태권V의 미사일 공격 기능을 추가하려면?</li>
</ul>
</li>
</ul>
<blockquote>
<ul>
<li>기존의 코드 내용 수정 발생(<a href="https://velog.io/@y_dragonrise/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84-%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99OCP-Open-Closed-Principle">OCP</a> 위배)  </li>
<li>Atom 클래스의 move 메서드, TaekwonV 클래스의 move 메서드 기능의 중복</li>
</ul>
</blockquote>
<h3 id="새로운-로봇에-공격이동-방법을-추가수정하는-경우">새로운 로봇에 공격/이동 방법을 추가/수정하는 경우</h3>
<p><img src="https://images.velog.io/images/y_dragonrise/post/f0348662-62e5-4cdc-af5f-6f13b9d77742/image.png" alt="robot strategy2"></p>
<ul>
<li><p>새로운 로봇에 기존의 공격 또는 이동 방법을 추가하거나 변경하려고 하면 문제 발생</p>
</li>
<li><p>다른 클래스와의 특정 메서드 중복 사용</p>
</li>
<li><p>시스템 변경에 따른 기존 모든 코드 수정</p>
</li>
</ul>
<h4 id="해결책">해결책</h4>
<ul>
<li><p>무엇이 변화되었는가? 에 중점</p>
</li>
<li><p>변화된 것을 찾은 후 <a href="https://velog.io/@y_dragonrise/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84-%EC%BA%A1%EC%8A%90%ED%99%94Encapsulation">캡슐화</a></p>
<ul>
<li>이동 방식: move()</li>
<li>공격 방식: attack()</li>
</ul>
</li>
<li><p>외부에서 구체적인 이동 방식, 공격 방식을 담은 클래스 은닉화</p>
</li>
<li><p>공격, 이동을 위한 인터페이스 생성, 실현할 클래스를 만듦
<img src="https://images.velog.io/images/y_dragonrise/post/3ac40aed-b36b-4971-8e21-dfaf1ec999ca/image.png" alt="strategy ex2"></p>
</li>
<li><p>클라이언트: 연관 관계를 이용해 이동 기능과 공격 기능의 변화 포함(Robot 클래스)</p>
</li>
<li><p>MovingStrategy, AttackStrategy 인터페이스를 포함해야 함</p>
</li>
</ul>
<h3 id="개선된-설계-구현">개선된 설계, 구현</h3>
<p><img src="https://images.velog.io/images/y_dragonrise/post/6d6e5a35-d28d-44a6-a983-1ecca8691952/design%20pattern.png" alt="strategy ex3"></p>
<table>
<thead>
<tr>
<th align="left">클래스</th>
<th align="left">클래스 설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Robot</td>
<td align="left">Robot 클래스, 이동과 공격을 실행하는 메서드, 이를 상속받아 구체적인 로봇을 만듦</td>
</tr>
<tr>
<td align="left">Atom, TaekwonV</td>
<td align="left">Robot 클래스를 상속받아 실제 로봇을 구현</td>
</tr>
<tr>
<td align="left"><code>&lt;&lt;interface&gt;&gt;</code> AttackStrategy</td>
<td align="left">각 로봇이 취할 수 있는 공격 방법에 대한 인터페이스</td>
</tr>
<tr>
<td align="left">PunchStrategy, MissileStrategy</td>
<td align="left">각 공격 방법을 실제로 구현함</td>
</tr>
<tr>
<td align="left"><code>&lt;&lt;interface&gt;&gt;</code> MovingStrategy</td>
<td align="left">각 로봇이 취할 수 있는 이동 방법에 대한 인터페이스</td>
</tr>
<tr>
<td align="left">WalkingStrategy, FlyingStrategy</td>
<td align="left">각 이동 방법을 실제로 구현함</td>
</tr>
</tbody></table>
<ul>
<li><p>구체적인 이동 방식과 공격 방식이 MovingStrategy, AttackStrategy 인터페이스에 의해 캡슐화</p>
<ul>
<li>향후 이동 방식, 공격 방식의 변화를 수용할 수 있음</li>
</ul>
</li>
<li><p>새로운 공격 방식 개발 시</p>
<ul>
<li>AttackStrategy 인터페이스가 변화에 대한 일종의 방화벽 역할을 수행해 Robot 클래스의 변경 차단</li>
</ul>
</li>
<li><p>OCP(Open-Closed Principle) 만족하는 설계</p>
<ul>
<li>새로운 기능 추가 시, 기존의 코드에 영향을 미치지 않음</li>
</ul>
</li>
<li><p>외부에서 로봇 객체의 이동 방식과 공격 방식을 임의대로 변경해야하는 메서드 생성</p>
<ul>
<li>setter를 통해 공격, 이동 방식 메서드를 정의해서 필요에 의해 변경 가능(집약 관계)</li>
</ul>
</li>
</ul>
<h4 id="robot-추상-클래스-1">Robot 추상 클래스</h4>
<pre><code class="language-java">public abstract class Robot{
    private String name;
    private MovingStrategy movingStrategy;
    private AttackStrategy attackStrategy;

    public Robot(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void move(){
        movingStrategy.move();
    }

    public void attack(){
        attackStrategy.attack();
    }

    public void setMovingStrategy(MovingStrategy movingStrategy){
        this.movingStrategy = movingStrategy;
    }

    public void setAttackStrategy(AttackStrategy attackStrategy){
        this.attackStrategy = attackStrategy;
    }
}</code></pre>
<h4 id="atom-클래스">Atom 클래스</h4>
<pre><code class="language-java">public class Atom extends Robot{
    public Atom(String name){
        super(name);
    }
}</code></pre>
<h4 id="taekwonv-클래스">TaekwonV 클래스</h4>
<pre><code class="language-java">public class TaekwonV extends Robot{
    public TaekwonV(String name){
        super(name);
    }
}</code></pre>
<h4 id="movingstrategy-인터페이스">MovingStrategy 인터페이스</h4>
<pre><code class="language-java">interface MovingStrategy{
    public void move();
}</code></pre>
<h4 id="flyingstrategy-구현체">FlyingStrategy 구현체</h4>
<pre><code class="language-java">public class FlyingStrategy implements MovingStrategy{
    public void move(){
        System.out.println(&quot;I can fly.&quot;);
    }
}</code></pre>
<h4 id="walkingstrategy-구현체">WalkingStrategy 구현체</h4>
<pre><code class="language-java">public class WalkingStrategy implements MovingStrategy{
    public void move(){
        System.out.println(&quot;I can only walk.&quot;);
    }
}</code></pre>
<h4 id="attackstrategy-인터페이스">AttackStrategy 인터페이스</h4>
<pre><code class="language-java">interface AttackStrategy{
    public void attack();
}</code></pre>
<h4 id="missilestrategy-구현체">MissileStrategy 구현체</h4>
<pre><code class="language-java">public class MissileStrategy implements AttackStrategy{
    public void attack(){
        System.out.println(&quot;I have Missile and can attack with it.&quot;);
    }
}</code></pre>
<h4 id="punchstrategy-구현체">PunchStrategy 구현체</h4>
<pre><code class="language-java">public class PunchStrategy implements AttackStrategy{
    public void attack(){
        System.out.println(&quot;I have strong punch and can attack with it.&quot;);
    }
}</code></pre>
<h4 id="client-클래스-1">Client 클래스</h4>
<pre><code class="language-java">public class Client{
    public static void main(String[] args){
        Robot taekwonV = new TaekwonV(&quot;TaekwonV&quot;);
        Robot atom = new Atom(&quot;Atom&quot;);

        taekwonV.setMovingStrategy(new WalkingStrategy());
        taekwonV.setAttackStrategy(new MissileStrategy());

        atom.setMovingStrategy(new WalkingStrategy()); // 이동 전략을 날아간다는 전략으로 설정
        atom.setAttackStrategy(new PunchStrategy()); // 공격 전략을 펀치를 구사하는 전략으로 설정

        System.out.println(&quot;My name is &quot; + taekwonV.getName());
        taekwonV.move();
        taekwonV.attack();

        System.out.println();

        System.out.println(&quot;My name is &quot; + atom.getName());
        atom.move();
        atom.attack();
    }
}</code></pre>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>정인상,채흥석, 『JAVA 객체 지향 디자인 패턴』, 한빛미디어(2014.4.2), 166p~179p</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[대소문자 변환]]></title>
            <link>https://velog.io/@y_dragonrise/%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@y_dragonrise/%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%ED%99%98</guid>
            <pubDate>Tue, 29 Sep 2020 13:53:33 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<ul>
<li>주어진 문자열의 대문자는 소문자로, 소문자는 대문자로 변환하시오</li>
</ul>
<h4 id="출력">출력</h4>
<pre><code class="language-html">HELLOwORLd</code></pre>
<h3 id="풀이">풀이</h3>
<pre><code class="language-java">public class Main{
    public static void main(String[] args){
        String input = &quot;helloWorlD&quot;;
        char[] arr;
        arr = input.toCharArray(); // 문자열 객체를 char array type으로 반환
        System.out.print(arr);
        System.out.println();

        for(int i=0; i&lt;arr.lenght; i++){
            if(arr[i] &gt;= &#39;a&#39; &amp;&amp; arr[i] &lt;= &#39;z&#39;){        // i번째 요소가 소문자라면
                arr[i] = (char)(arr[i] + &#39;A&#39; - &#39;a&#39;);   // 대문자와 소문자와의 간격만큼 더해준다.
            } else if(arr[i] &gt;= &#39;A&#39; &amp;&amp; arr[i] &lt;= &#39;Z&#39;){
                arr[i] = (char)(arr[i] - (&#39;A&#39; - &#39;a&#39;);
            }
        }

        System.out.print(arr);
    }
}</code></pre>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>진쓰 코딩, &quot;[알고리즘 기초 100제] 5번 대소문자 변환&quot;, <a href="https://www.youtube.com/watch?v=DTEiENYVR14&amp;list=PLVoihNyHW4xkm_KJ8_N8X7F6EQP4uSRyR&amp;index=6">www.youtube.com/watch?v=DTEiENYVR14&amp;list=PLVoihNyHW4xkm_KJ8_N8X7F6EQP4uSRyR&amp;index=6</a>(2020.09.06)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[10진수 2진수 변환]]></title>
            <link>https://velog.io/@y_dragonrise/10%EC%A7%84%EC%88%98-2%EC%A7%84%EC%88%98-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@y_dragonrise/10%EC%A7%84%EC%88%98-2%EC%A7%84%EC%88%98-%EB%B3%80%ED%99%98</guid>
            <pubDate>Tue, 29 Sep 2020 13:52:35 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<ul>
<li>주어진 10진수를 2진수로 변환하시오</li>
</ul>
<h4 id="출력">출력</h4>
<pre><code class="language-html">010011</code></pre>
<h3 id="풀이">풀이</h3>
<pre><code class="language-java">public class Main{
    public static void main(String[] args){
        int inputNum = 19;  // 10진수
        int bin[] = new int[100]; // 2진수가 저장된 배열

        /*
                     (몫) (나머지)
          19 / 2      9...1
           9 / 2      4...1
           4 / 2      2...0
           2 / 2      1...0
           1 / 2      0...1

           010011 =&gt; 19
        */

        int i = 0;  // 인덱스 초기화
        int mok = inputNum;  // 몫에 10진수 저장

        while(mok &gt; 0){  // 몫이 나누어 떨어질 때까지 반복
            bin[i] = mok % 2;  // 몫을 2로 나누어 나머지 값을 저장
            mok /= 2;    // 몫을 2로 나눈 값을 갱신
            i++;         // 인덱스를 1증가시켜 bin[i] 배열의 다음 저장된 값을 꺼내도록 함
        }

        i--;  // bin[i] 배열의 인덱스는 0부터 4까지 저장되었으므로 현재 인덱스 값인 5에서 1을 감한다.
        for(; i&gt;=0; i--){
            System.out.print(bin[i]);
        }
    }
}</code></pre>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>진쓰 코딩, &quot;[알고리즘 기초 100제] 4번 10진수를 2진수로 변환&quot;, <a href="https://www.youtube.com/watch?v=8Xh2Zgap9hs&amp;list=PLVoihNyHW4xkm_KJ8_N8X7F6EQP4uSRyR&amp;index=5">www.youtube.com/watch?v=8Xh2Zgap9hs&amp;list=PLVoihNyHW4xkm_KJ8_N8X7F6EQP4uSRyR&amp;index=5</a>(2020.09.06)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[연속된 정수들을 더하여 얻을 수 있는 최대값]]></title>
            <link>https://velog.io/@y_dragonrise/%EC%97%B0%EC%86%8D%EB%90%9C-%EC%A0%95%EC%88%98%EB%93%A4%EC%9D%84-%EB%8D%94%ED%95%98%EC%97%AC-%EC%96%BB%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%B5%9C%EB%8C%80%EA%B0%92</link>
            <guid>https://velog.io/@y_dragonrise/%EC%97%B0%EC%86%8D%EB%90%9C-%EC%A0%95%EC%88%98%EB%93%A4%EC%9D%84-%EB%8D%94%ED%95%98%EC%97%AC-%EC%96%BB%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%B5%9C%EB%8C%80%EA%B0%92</guid>
            <pubDate>Tue, 29 Sep 2020 13:51:39 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<ul>
<li><p>n개의 정수를 입력받아 배열에 저장한다.</p>
</li>
<li><p>이들 중에서 0개 이상의 연속된 정수들을 더하여 얻을 수 있는 최대값을 구하여 출력하시오.</p>
</li>
</ul>
<h4 id="예제-입력">예제 입력</h4>
<pre><code class="language-html">13
-2 3 5 -14 12 3 -9 8 -1 13 2 -5 4</code></pre>
<h4 id="예제-출력">예제 출력</h4>
<pre><code class="language-html">28</code></pre>
<h3 id="풀이">풀이</h3>
<pre><code class="language-java">public class Main{
    public static void main(String[] args){
        Scanner kb = new Scanner(System.in);
        int n = kb.nextInt();
        int[] data = new int[n];
        for(int i=0; i&lt;n; i++)
            data[i] = kb.nextInt();
        kb.close();

        int max = 0;
        for(int i=0; i&lt;n; i++){
            int sum = 0;
            for(int j=i; j&lt;n; j++){ // 시작과 끝점이 같음
                sum += data[j];
                if(sum &gt; max)
                    max = sum;
            }
        }
        System.out.println(&quot;The max sum is &quot; + max);
    }
}</code></pre>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>권오흠 교수, 인프런 - &quot;Java로 배우는 자료구조&quot;,<a href="https://www.inflearn.com/course/java-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0/dashboard">www.inflearn.com/course/java-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0/dashboard</a>(2020.09.06)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[소수 출력하기]]></title>
            <link>https://velog.io/@y_dragonrise/%EC%86%8C%EC%88%98-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@y_dragonrise/%EC%86%8C%EC%88%98-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 29 Sep 2020 13:49:12 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<ul>
<li>1~100000사이의 모든 <code>소수</code>들을 찾아서 출력하시오.</li>
</ul>
<p><code>소수</code></p>
<ul>
<li>1과 자기자신을 제외한 약수를 갖지 않는 수</li>
</ul>
<h4 id="출력">출력</h4>
<pre><code class="language-html">2
3
5
7
11
13

...

99923
99929
99961
99971
99989
99991</code></pre>
<h3 id="풀이">풀이</h3>
<pre><code class="language-java">public class Main{
     public static void main(String[] args){
         for(int i=2; i&lt;=100000; n++){
              boolean isPrime = true;
              for(int i=2; i*i&lt;=n &amp;&amp; isPrime; i++{
                   if(n%i == 0)
                       isPrime = false;
              }
              if(isPrime)
                  System.out.println(n);
         }
     }
}</code></pre>
<ul>
<li><p>각각의 정수 n에 대해서 이 for문을 돌면서 2보다 크거나 같은 약수가 있는지 검사한다. 하나라도 약수가 있다면 이미 소수가 아니므로 더 이상 검사할 필요가 없다.</p>
</li>
<li><p>변수 isPrime이 어떤 역할을 하는지 잘 생각해봐야한다.</p>
</li>
</ul>
<h3 id="문제-1">문제</h3>
<p>입력된 수가 소수인지 판별하시오</p>
<h4 id="출력-1">출력</h4>
<pre><code class="language-html">7은 소수입니다.</code></pre>
<h3 id="풀이-1">풀이</h3>
<pre><code class="language-java">public class Main{
     public static void main(String[] args){
         int num = 7;

         boolean isPrimeNumber = true;

         for(int i=2; i&lt;=num/2; i++){
              if(num%i==0)
                  isPrimeNumber = false;
         }
         if(isPrimeNumber){
             System.out.println(num + &quot;은 소수입니다.&quot;);
         } else {
             System.out.println(num + &quot;은 소수가 아닙니다.&quot;);
         }
     }
}</code></pre>
<blockquote>
<p><strong>Reference</strong></p>
</blockquote>
<ul>
<li>권오흠 교수, 인프런 - &quot;Java로 배우는 자료구조&quot;,<a href="https://www.inflearn.com/course/java-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0/dashboard">www.inflearn.com/course/java-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0/dashboard</a>(2020.09.06)</li>
<li>진쓰 코딩, &quot;[알고리즘 기초 100제] 7번 소수 판별&quot;, <a href="https://www.youtube.com/watch?v=CZOkPNGWpDA&amp;list=PLVoihNyHW4xkm_KJ8_N8X7F6EQP4uSRyR&amp;index=8">www.youtube.com/watch?v=CZOkPNGWpDA&amp;list=PLVoihNyHW4xkm_KJ8_N8X7F6EQP4uSRyR&amp;index=8</a>(2020.09.06)</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>