<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ko-inseoklee.log</title>
        <link>https://velog.io/</link>
        <description>작심삼일 * 122 - 1</description>
        <lastBuildDate>Thu, 20 Oct 2022 05:25:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ko-inseoklee.log</title>
            <url>https://velog.velcdn.com/images/ko-inseoklee/profile/be80dc40-408b-4ed8-a93f-4225c43b1322/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ko-inseoklee.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ko-inseoklee" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[React testing library에서 테스트를 하다 발생할 수 있는 오류들(feat. Redux, Router 테스트 중 생긴 오류들)]]></title>
            <link>https://velog.io/@ko-inseoklee/React-testing-library%EC%97%90%EC%84%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A5%BC-%ED%95%98%EB%8B%A4-%EB%B0%9C%EC%83%9D%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%98%A4%EB%A5%98%EB%93%A4feat.-Redux-Router-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A4%91-%EC%83%9D%EA%B8%B4-%EC%98%A4%EB%A5%98%EB%93%A4</link>
            <guid>https://velog.io/@ko-inseoklee/React-testing-library%EC%97%90%EC%84%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A5%BC-%ED%95%98%EB%8B%A4-%EB%B0%9C%EC%83%9D%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%98%A4%EB%A5%98%EB%93%A4feat.-Redux-Router-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A4%91-%EC%83%9D%EA%B8%B4-%EC%98%A4%EB%A5%98%EB%93%A4</guid>
            <pubDate>Thu, 20 Oct 2022 05:25:43 GMT</pubDate>
            <description><![CDATA[<p><strong>이전 포스팅에서 Jest를 사용하여 Typescript로 구현한 로직을 테스트하는 방법 공부했다. 그러던 도중, React라는 Frontend 개발환경에서 컴포넌트가 정상적으로 동작하는지 테스트하는 것이 더욱 필요하지 않을까? 하는 생각에 찾아본 결과, React Testing Library를 알게 되었다.</strong></p>
<p>프로젝트 셋업을 하면서 Redux, Route를 적용할 때마다 문제가 발생했다. 결국, <strong>테스트 구조에 대한 이해</strong>가 부족했기 때문에 에러가 떴다. (다음에는 인지하고 개발하자!)</p>
<h2 id="1-react-testing-libraryrtl">1. React Testing Library(RTL)</h2>
<p>리액트 테스팅 라이브러리는 리액트 컴포넌트를 테스트하기 위한 툴이다. Jest를 기반으로 동작하기 때문에, Jest로 테스트 코드를 작성해 본 경험이 있다면 접근이 쉬울 것 같다.</p>
<p>Jest 구조에서 render() 함수를 이용하여 원하는 컴포넌트를 실행시키고, 실행된 화면에 필요한 컴포넌트들이 있는지 파악할 수 있다. 자세한 API는 공식 홈페이지 문서를 참고하는 편이 정확하다고 생각한다.</p>
<p><a href="https://testing-library.com/docs/react-testing-library/api">RTL 공식 API 문서 링크</a> &lt;- 여기!</p>
<h2 id="2-error1---redux">2. Error1 - Redux</h2>
<p>아무 State도 없는 초기 프로젝트에서는 정상적으로 수행되었는데, Redux로 전역 상태를 관리하는 로직을 추가하니 에러가 떴다.</p>
<pre><code>ERROR: could not find react-redux context value; please ensure the component is wrapped in a &lt;Provider&gt;      </code></pre><p>컴포넌트를 redux 하위로 올려놓았는데, Provider로 Wrapping되지 않아 생기는 문제이다. <strong>간단하지만 중요한 사실은, 테스트 각각 마다 새로운 DOM으로 화면을 렌더링하기 때문에 실제 코드에서는 Provider가 컴포넌트를 감싸고 있었지만, 테스트 환경에서는 아니었다는 점이다.</strong> 이 점을 간과하고 &quot;React testing library redux&quot; 만 주구장창 검색하다가, 공식 홈페이지에서 다음과 같은 예시를 볼 수 있었다.</p>
<p><a href="https://redux.js.org/usage/writing-tests#connected-components">Redux 테스팅 관련 예시 링크</a> &lt;- 여기!</p>
<p>결국 테스팅 환경에서도 상태를 관리할 수 있는 모듈을 만들어야했고, 공식 홈페이지의 친절한 안내와 같이 renderWithProviders()라는 모듈을 구현하여 적용할 수 있었다.</p>
<h2 id="3-route">3. Route</h2>
<p>Redux 문제를 해결하고 Routing을 적용하고 테스트를 돌려봤는데, 또 문제가 생겼다! (ㅠㅠ)</p>
<p><img src="https://velog.velcdn.com/images/ko-inseoklee/post/dae44d79-ec35-49f9-902f-c41e9dccf5fe/image.png" alt=""></p>
<pre><code>ERROR: useHref() may be used only in the context of a &lt;Router&gt; component.
ERROR: useRoute() may be used only in the context of a &lt;Router&gt; component.</code></pre><p>포스팅하는 시점에서 보니 Redux 때와 같은 문제이지만,, Redux는 공식 문서를 코드만 긁어오며 따라가서 크게 고민하지 않았던 것 같다.(이게 왜 되지? 할만큼 바로 돼서...)</p>
<p>결국, DOM 구성에서 React-router-dom에서 사용하는 컴포넌트를 처리해 줄 browerRouter가 없었기 때문이었다! 다른 라이브러리를 사용해도 마찬가지이지만 부모 컴포넌트가 있어야 사용되는 자식 컴포넌트의 경우, 테스트 환경에서 부모 컴포넌트를 재정의하여 사용하여야 한다! 실제 개발 소스의 실행과 <strong>독립적</strong>이기 때문이다!</p>
<h2 id="어플리케이션의-실행-구조를-알아가는-과정은-매우-중요하다">어플리케이션의 실행 구조를 알아가는 과정은 매우 중요하다!</h2>
<h4 id="포스팅한-내용-중-틀린-부분이-있거나-보완될-부분은-가감없이-말씀해주시면-감사하겠습니다">포스팅한 내용 중 틀린 부분이 있거나 보완될 부분은 가감없이 말씀해주시면 감사하겠습니다!</h4>
<p>22.10.20 첫 포스팅</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[EC2에서 Spring Boot PM2로 배포하기]]></title>
            <link>https://velog.io/@ko-inseoklee/EC2%EC%97%90%EC%84%9C-Spring-Boot-PM2%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ko-inseoklee/EC2%EC%97%90%EC%84%9C-Spring-Boot-PM2%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 07 Oct 2022 03:41:42 GMT</pubDate>
            <description><![CDATA[<p>자체 프로젝트를 배포할 때 nohup 명령어를 이용하여 백그라운드에서 스프링 부트를 실행했었다. nohup으로 배포한 서버는 프로세스에서 직접 관리를 해야 하기도 하고, 시간이 조금 지나면 자동으로 프로세스가 종료되어 매번 다시 켜줬어야 했다. 그래서 프로세스가 유지되고 쉽게 관리할 수 있는 PM2를 사용해 배포하기로 했다.</p>
<h2 id="npm-설치">NPM 설치</h2>
<p>현재 내 인스턴스에는 Node Package Manager가 설치되어 있지 않기 때문에, Nodejs를 먼저 설치한다.</p>
<p>터미널에서 Node를 설치하기 위해 AWS 공식 홈페이지를 참고했다.</p>
<p><a href="https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html">https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html</a></p>
<p>터미널에 다음과 같이 입력한다.</p>
<pre><code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

. ~/.nvm/nvm.sh

nvm install --lts</code></pre><p>잘 설치가 되었으면 버전이 잡힌다.</p>
<p><img src="https://velog.velcdn.com/images/ko-inseoklee/post/5cb8fbef-d5bc-41a1-912d-d766862441fe/image.png" alt=""></p>
<h2 id="pm2-설치">PM2 설치</h2>
<p>npm을 사용할 수 있게 되었으니, PM2를 설치해보자.
모든 프로젝트에서 사용할 것이기 때문에 글로벌하게 설치한다.</p>
<pre><code>npm install -g pm2</code></pre><p>설치가 완료되고, 터미널에 pm2를 입력하면 다음과 같이 뜬다.</p>
<p><img src="https://velog.velcdn.com/images/ko-inseoklee/post/2aa16654-ec07-4381-9c36-0af004e6b8e9/image.png" alt=""></p>
<p>잘 설치가 되었으면, PM2로 Spring boot를 실행해보자.</p>
<h2 id="실행">실행</h2>
<p>실행 전에, Spring boot가 jar 파일로 build되어 있지 않은 경우 프로젝트 루트 디렉토리에서 다음과 같은 명령어를 입력해준다(Gradle 기준, Maven은 몰라융).</p>
<pre><code>./gradlew build</code></pre><p> 빌드가 성공한 경우, {<em>root_directory</em>}/build/libs 에 파일이 생성된다.</p>
<p> 다음으로, Pm2로 실행시키기 위해 [filename].json 파일을 생성하고 실행 스크립트를 작성한다. pm2 공식 홈페이지를 참고했다.</p>
<pre><code class="language-javascript">// server.json
{
  &quot;apps&quot; : [{
    name   : &quot;[이름]&quot;,
    script : &quot;java&quot;,
    args   : [
        &quot;-jar&quot;,
          &quot;[libs 디렉토리]/[스냅샷 파일이름].jar&quot;
    ]
  }]
}</code></pre>
<p>json파일 작성 이후, pm2를 실행시켜보자.</p>
<pre><code>pm2 start server.json</code></pre><p>구동이 성공적으로 되면 pm2에서 관리하고 있는 프로세스를  보여준다. 이후 포스트맨으로 요청을 날려서 확인하면 된다.</p>
<p>끝!</p>
<h3 id="출처">출처</h3>
<ul>
<li>AWS 공식문서</li>
<li>Node 공식문서</li>
<li>PM2 공식문서</li>
</ul>
<p>틀린 부분이 있다면 말씀해주세요. 감사합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 입국심사(JavaScript)]]></title>
            <link>https://velog.io/@ko-inseoklee/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9E%85%EA%B5%AD%EC%8B%AC%EC%82%AC</link>
            <guid>https://velog.io/@ko-inseoklee/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9E%85%EA%B5%AD%EC%8B%AC%EC%82%AC</guid>
            <pubDate>Mon, 26 Sep 2022 14:25:09 GMT</pubDate>
            <description><![CDATA[<p>입국심사는 심사시간이 다른 m명의 심사위원이 n명의 사람들을 심사하여 모두 통과시키는데 걸리는 최소 시간을 찾는 문제이다.</p>
<h2 id="풀이">풀이</h2>
<p>이분 탐색을 이용하여 최소 시간을 구한다. 
주의할 점은, 이분탐색의 오른쪽에 최대 시간을 잡는 과정이다. 문제의 제한조건은 다음과 같다.</p>
<pre><code>심사받는 사람의 수 = (1,1000000000)
심사 시간의 범위 = (1,1000000000)
심사위원의 수 = (1,100000)</code></pre><p>   n명의 심사받는 사람이 m명의 심사위원에게 심사를 받는다고 가정했을 때, 쉽게 생각할 수 있는 최대값은</p>
<pre><code>MAX_VAL = n * MAX(심사위원의 심사시간) / 심사위원의 수</code></pre><p> 이다.</p>
<p> 이를 기준으로 코드를 작성하면, 다음과 같다.</p>
<h2 id="코드">코드</h2>
<pre><code class="language-js"> function solution(n, times) {
    var answer = 0;

    times.sort((a,b) =&gt; a - b); 

    //right 범위 설정(최대 심사인원 * 최대 입국심사 시간 / 심사위원 수)
    var right = Math.floor((times[times.length - 1] * n) / times.length);
    var left = 1;

    while(left &lt; right){
        var mid = Math.floor((left + right) / 2);

        var tmpTime = 0;
        for(let i = 0; i &lt; times.length; i++){
            tmpTime += Math.floor(mid / times[i]);
            if(tmpTime &gt;= n) break;
        }
        if (tmpTime &gt;= n) {
            right = mid;
        }
        else left = mid + 1;
    }

    answer = right;

    return answer;
}</code></pre>
<h2 id="배운-점">배운 점</h2>
<h3 id="1-left-right의-범위">1. Left, Right의 범위</h3>
<p> 문제마다 이분탐색을 사용하는 범위가 달라진다는 점을 배웠다. 위 문제에서 예시가 </p>
<pre><code>n = 6
times = [7,10]</code></pre><p> 로 나왔는데, 알고리즘을 대충짜서 28, 29초 둘다 7이 나와 구분을 할 수 없는 불상사가 생겼다. 그래서 n과 tmpTime의 값이 같을 때도 right의 값을 줄여 최소를 갖게 만들었다.</p>
<p>   그랬더니 right의 값이 정답을 지나쳐서 왼쪽으로 가는 경우가 생겼다. 그래서 결국</p>
<pre><code>right = mid - 1 =&gt; right = mid</code></pre><p> 로 바꿔주었다.</p>
<h3 id="2-loop-performance">2. Loop Performance</h3>
<p> 처음에는 for-of 구문을 사용하여 문제를 풀었는데, 퍼포먼스가 너무 낮게 나왔다. (물론, Mid를 구하는 과정에서 2를 나눠주지 않은 것 때문이었다.. 실수를 줄이자.)</p>
<p> 처음에는 몰랐기 때문에 for-of의 성능 문제라고 생각하여, 일반적인 for문으로 바꿔주었다. for의 반복문은 일반적인 for문이 가장 빠르다는 것을 알았다.</p>
<h3 id="3-javascript-sort">3. Javascript Sort</h3>
<p> 자바스크립트에서는 일반적으로 sort에 compare 함수를 입력하지 않으면 <strong>string을 기준</strong>으로 정렬한다. 정렬 기준이 string의 경우, [7, 10]의 예시에서 1이 사전 순으로 작기 때문에 [10, 7] 의 순서로 정렬한다. 이를 피해 숫자 크기 순으로 정렬하기 위해 코드를 다음과 같이 변경했다.</p>
<pre><code class="language-js">    // Before
    array1.sort();

    // After
    array1.sort((a,b) =&gt; a - b);
</code></pre>
<h2 id="참고-자료">참고 자료</h2>
<p>문제: <a href="https://school.programmers.co.kr/learn/challenges?order=acceptance_desc&amp;page=1">https://school.programmers.co.kr/learn/challenges?order=acceptance_desc&amp;page=1</a></p>
<p>반복문 성능 비교: <a href="https://gurtn.tistory.com/121">https://gurtn.tistory.com/121</a></p>
<p>정렬: <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/sort</a></p>
<p>** 잘못된 부분이 있다면 댓글에 남겨주시면 감사하겠습니다. **</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Typescript에서 JEST를 사용한 단위테스트를 해보자.]]></title>
            <link>https://velog.io/@ko-inseoklee/JEST%EB%A5%BC-Typescript%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@ko-inseoklee/JEST%EB%A5%BC-Typescript%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Wed, 14 Sep 2022 08:42:39 GMT</pubDate>
            <description><![CDATA[<p><strong>단위 테스트 기법에 대해 공부를 하던 중 React 에서 사용할 수 있는 testing framework JEST에 대해 알게되어 사용해보고 정리한 글입니다. 오류가 있을 수 있으니 알려주시면 감사하겠습니다.</strong></p>
<h2 id="jest란">JEST란?</h2>
<ul>
<li>편리함에 포커스를 맞춘 Javascript Testing Framework</li>
<li>Babel, Typescript, React, Angular, Vew 등 Javascript 기반 라이브러리에서도 사용이 가능하다. <del>페이스북에서 만들었고, 오픈소스 라이브러리이다!!</del></li>
</ul>
<p>[github]!<a href="https://github.com/facebook/jest">https://github.com/facebook/jest</a></p>
<p>&emsp;</p>
<h2 id="특징">특징</h2>
<ol>
<li><p>zero config - 대부분의 Javascript Project에서 configuration 없이 작동하는 것을 목표로 한다. <del>Typescript나 React에서는 configuration을 간단하지만 따로 해줘야하는데.. ~</del></p>
</li>
<li><p>snapshots - 큰 규모의 객체나 로직을 스냅샷 단위로 묶을 수 있다. 스냅샷은 테스트 환경에서 생성되거나 인라인으로 내장된다.</p>
</li>
<li><p>isolated - JEST는 source code와 병렬 구조로 실행되기 때문에 실제 로직에 영향을 주지 않는다는 장점이 있다.</p>
</li>
</ol>
<p>&emsp;</p>
<h2 id="설치">설치</h2>
<p>타입스크립트에서 Jest를 사용하려면, <strong>Babel을 이용해 먼저 Transpiling을 하고, 테스트를 수행한다.</strong> node project를 만들고, 다음 라이브러리를 install하자.</p>
<pre><code class="language-console">    yarn add --dev babel-jest @babel/core @babel/preset-env @babel/preset-typescript</code></pre>
<p>Install 후, project의 rootdir에 babel.config.js 파일을 생성하고 다음과 같이 env와 ts preset을 설정해준다.</p>
<pre><code class="language-js">// babel.config.js

module.exports = {
  presets: [
    [&#39;@babel/preset-env&#39;, {targets: {node: &#39;current&#39;}}],
    &#39;@babel/preset-typescript&#39;,
  ],
};</code></pre>
<p>&emsp;</p>
<h2 id="어떻게-사용할까">어떻게 사용할까?</h2>
<p>공식 홈페이지를 돌아다니며 느낀 점이, 일반 사용법 뿐만 아니라 다양한 라이브러리, DB, 플러그인과 함께 사용하는 방법이 친절히 나와있다! <del>내 글은 나만 꺼내보면 되지 뭐..</del> 가장 간단한 사용법  <del>과 자주 사용하는 Matchers, 비동기 테스팅</del>  에 대해 소개해보려고 한다.
&emsp;</p>
<h3 id="조금-더-편하게-사용해볼까">조~금 더 편하게 사용해볼까?</h3>
<p>package.json의 script를 수정하여 npm 명령어로 입력해보자!</p>
<pre><code class="language-js">&quot;scripts&quot;: {
    &quot;test&quot;: &quot;jest&quot;
 },</code></pre>
<p>&emsp;</p>
<h3 id="사용법">사용법</h3>
<p>먼저, 공식홈페이지에 있는 sum.ts 파일을 만들고 두 수의 합을 구하는 함수를 구현한다.</p>
<pre><code class="language-js">// sum.ts
export const sum = (a: number, b: number) : number =&gt; {
    return a + b;
}</code></pre>
<p>구현 후, sum.ts에 있는 로직을 테스트하기 위한 파일이라는 의미로 sum.test.ts라는 파일을 생성한다.</p>
<pre><code class="language-js">// sum.test.ts
import {sum} from &#39;./sum&#39;;
import {describe, expect, test} from &#39;@jest/globals&#39;;

describe(&#39;sum module&#39;, () =&gt; {
  test(&#39;adds 1 + 2 to equal 3&#39;, () =&gt; {
    expect(sum(1, 2)).toBe(3);
  });
});</code></pre>
<p>테스트 코드의 구조는 다음과 같다.</p>
<pre><code>describe(desc, func) // 테스트할 로직에 대한 설명을 넣는다. 
test(content, func) // test할 내용과 수행할 로직을 넣는다.
expect(testing logic or something).toBe(expected result) // 로직과 기대값을 넣는다.</code></pre><p>위 구조로 작성하고 실행하면, 다음과 같은 결과를 얻을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/ko-inseoklee/post/c4d44c05-57dd-4072-a79f-52e5115a2094/image.png" alt=""></p>
<p>&emsp;</p>
<h2 id="q-실제-프로젝트에서는-어떻게-쓰면-좋을까">Q. 실제 프로젝트에서는 어떻게 쓰면 좋을까?</h2>
<p>정답은 없지만.. 고민을 해보면 <del>src와 동일하게 test라는 폴더를 만들고, 현재 project 구조와 동일한 트리구조로 test 폴더를 구성하여 파일별로 테스트를 하면 어떨까 싶다.</del> (중복된 폴더 구조를 굳이 사용할 필요가 있을까 싶다...-22.10.19) 나중에 새로 시작하는 프로젝트에서는 적용해서 개발해봐야겠다. </p>
<p>&emsp;</p>
<h2 id="마치며">마치며</h2>
<p>UX 기반의 테스팅 환경을 코드로 구축하는 것은 당장에는 너~~무 귀찮지만, 후에 유지보수를 더욱 용이하게 한다는 점에서 매우 필요한 기술인 것 같다. 당장에 귀찮음에 지지 말자 ~</p>
<p>&emsp;</p>
<h2 id="출처">출처</h2>
<p>[JEST]!<a href="https://jestjs.io/">https://jestjs.io/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React-Typescript] Input 태그에서 name props 가져오기]]></title>
            <link>https://velog.io/@ko-inseoklee/React-Typescript-Input-%ED%83%9C%EA%B7%B8%EC%97%90%EC%84%9C-name-props-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@ko-inseoklee/React-Typescript-Input-%ED%83%9C%EA%B7%B8%EC%97%90%EC%84%9C-name-props-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Thu, 30 Jun 2022 15:07:27 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>&nbsp; 서울시에서 제공하는 OpenAPI로 지하철 정보를 보여주는 프로젝트를 진행하다 난관에 부딪혔다. 메뉴를 Input 태그의 button으로 구성하고, onClick 시에 Input의 name에 따라 해당하는 메뉴로 넘어가는 Header Component를 구현하고 있었는데 name 태그를 찾을 수 없다는 오류가 떴다. Javascript에서는 Type 선언이 없기 때문에 Tag의 Attribute를 쉽게 불러올 수 있지만, TypeScript를 사용하다보니 Input에서 name attribute를 불러오는데 애를 먹었다.</p>
<h2 id="과정">과정</h2>
<p>  시작 코드는 다음과 같았다.</p>
<pre><code class="language-typescript">const HandleClick = (event:React.MouseEvent&lt;HTMLInputElement&gt;) =&gt; {
     const e = event.target;
      console.log(e.name);
}</code></pre>
<p>target을 찍고, 3번째 e.name을 찍는데 없는 property라는 Error가 떴다. </p>
<p><img src="https://velog.velcdn.com/images/ko-inseoklee/post/ce6db9c9-563d-471b-a654-e9ad99b29f70/image.png" alt=""></p>
<p>그렇다면, event.target의 타입에서는 name을 props을 갖고 있지 않다는 말이고, 어떻게 구성되어 있을지 궁금해서 HTMLInputElement를 Generic Type으로하는 MouseEvent를 뜯어보았다. 간단히 그림으로 설명하면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/ko-inseoklee/post/288ae965-9ec1-4e1f-8f97-d61656556986/image.png" alt=""></p>
<p>MouseEvent가 결국 BaseSyntheticEvent라는 Interface에서 나오는데, BaseSyntheticEvent는 다음과 같이 정의되어 있다.</p>
<p><img src="blob:https://velog.io/e3cb421b-0b11-4c0b-994b-0059ec750a35" alt="업로드중.."></p>
<p>여기에 Target과  currentTarget 두 Property가 있었고, 위 Property 중 필요한 것을 사용하면 된다.</p>
<h2 id="결과">결과</h2>
<p>currentTarget Props에서 name 태그를 찾아 name에 따라 다른 메뉴로 이동하는 Navigation 기능을 완성했다. Interface의 상속 구조와, 부모에게 있는 Property를 찾아 내가 원하는 데이터를 얻어내는 방법이 조금 더 익숙해진 경험이었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Algorithm] Binary Search]]></title>
            <link>https://velog.io/@ko-inseoklee/%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4-%EC%9D%B4%EB%B6%84-%ED%83%90%EC%83%89</link>
            <guid>https://velog.io/@ko-inseoklee/%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4-%EC%9D%B4%EB%B6%84-%ED%83%90%EC%83%89</guid>
            <pubDate>Sun, 03 Apr 2022 06:03:04 GMT</pubDate>
            <description><![CDATA[<p><strong>개인의 짧은 식견으로 작성했으니, 많은 조언 부탁드립니다.</strong></p>
<h2 id="설명">설명</h2>
<ul>
<li>이분탐색은 기본적으로 Array와 같은 자료 구조에서 특정 값을 찾아낼 때 쓰인다.</li>
<li>찾고자 하는 값과, 현재 보고 있는 값을 비교하여 왼쪽과 오른쪽으로 탐색 범위를 쪼개 다시 탐색하는 과정을 거친다.</li>
<li>보고 있는 값과 찾고자 하는 값의 대소관계가 분명해야 하기 때문에, 이분 탐색을 사용하기 위해서는 배열이 정렬되어 있어야 한다.</li>
</ul>
<h2 id="사용처">사용처</h2>
<ul>
<li>배열 속의 특정 값을 찾고자 할 때.</li>
<li>배열의 값들을 활용하여 찾아야 할 값에 특정 범위 내의 최적해를 찾을 때.</li>
</ul>
<h2 id="code">Code</h2>
<ul>
<li>가장 기본적인 이분탐색 코드는 다음과 같다.</li>
</ul>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;

int main(){
    //Data - 크기가 5인 배열을 선언.
    int arr[] = {1,4,2,6,8};

    // 배열이 정렬되어 있어야 이분 탐색을 사용할 수 있으므로 배열 정렬.
    sort(arr,arr+5);

    // 찾고자 하는 값, 값의 유무를 판단할 boolean 변수 선언
    int ans = 2; bool result = false;

    //처음 시작할 때 위치는 양 끝 점을 위치로 한다.
    int left = 0; right = 5 - 1;

    //left index가 right index를 넘어갈 경우, 배열의 모든 범위를 탐색한 것이기 때문에 종료.
    while(left &lt;= right){
        //left와 right index의 중간 값을 선언하고, 이 값을 찾고자하는 ans와 비교.
        int mid = (left + right) / 2;

        //1. 찾고자 하는 값보다 중간 값과 같으므로, result 변수값을 변경하고 루프에서 빠져나옴.
        if(mid == ans){
            result = true;
            break;
        }
        //2. 현재 값이 찾고자 하는 값보다 크므로, 현재 값보다 작은 범위에서 다시 탐색을 시작.
        else if(mid &gt; ans) right = mid - 1;
        //3. 2번의 반대 개념이므로 현재 값보다 큰 범위에서 다시 탐색.
        else left = mid + 1;
    }

    cout &lt;&lt; result &lt;&lt; endl;

    return 0;
}
</code></pre>
<h2 id="관련-문제-코드">관련 문제 코드</h2>
<p><a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/binary_search/p1920.cpp">백준 1920번 문제 - 수 찾기</a>
<a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/binary_search/p2110.cpp">백준 2110번 문제 - 공유기 설치</a>
<a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/binary_search/p2476.cpp">백준 2467번 문제 - 용액</a></p>
<h2 id="출처">출처</h2>
<p>문제 출처
<a href="https://www.acmicpc.net/">백준 온라인 저지</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] Knapsack Problem]]></title>
            <link>https://velog.io/@ko-inseoklee/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Knapsack-Problem</link>
            <guid>https://velog.io/@ko-inseoklee/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Knapsack-Problem</guid>
            <pubDate>Mon, 27 Dec 2021 09:25:28 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<ul>
<li><p>Knapsack Problem은 일정 무게를 담을 수 있는 배낭 안에 담을 수 있는 물건의 총량을 최적화 하는 문제이다. 배낭의 크기, 물건의 개수, 각 물건의 무게와 가치가 주어질 때, 배낭에 넣을 수 있는 물건들의 가치가 최대가 되게 하는 조합을 찾는 문제이다.</p>
</li>
<li><p>Knapsack Problem은 크게 <strong>0-1 Knapsack Problem</strong>과 <strong>Fractional Knapsack Problem</strong>으로 나뉜다.</p>
</li>
</ul>
<ul>
<li>Knapsack Problem의 예제는 백준 문제 12865번. 평범한 배낭 문제를 풀었다.</li>
</ul>
<h2 id="0-1-knapsack-problem">0-1 Knapsack Problem</h2>
<ul>
<li><p>물건을 쪼개 배낭에 넣을 수 없을 때, 각 물건을 배낭에 넣을 지 말지 결정하는 문제.</p>
</li>
<li><p>Dynamic Programming으로 문제를 해결할 수 있다.</p>
</li>
</ul>
<blockquote>
<h3 id="접근-방식">접근 방식</h3>
</blockquote>
<h4 id="data-structure">Data Structure</h4>
<ul>
<li>물건의 무게, 가치를 저장할 Structure</li>
<li>물건의 개수 * 가방의 무게만큼의 데이터를 저장할 수 있는 2-D Array<h4 id="concept">Concept</h4>
<ul>
<li>물건을 최적으로 조합해야 하므로, 각 배낭의 무게에서 가질 수 있는 최고의 가치를 저장해두고, 다음 물건을 탐색할 때 이전 물건까지의 결과값을 참고하는 방식으로 해결할 수 있다.</li>
<li>Case1: 물건의 무게가 남아있는 배낭의 무게보다 큰 경우
-&gt; 물건이 들어갈 수 없기 때문에, 이전 물건의 현재 남은 배낭 무게에서의 가치와, 현재 물건의 가치와 현재 물건이 들어갈 자리를 남긴 상태에서의 이전 물건의 가치 합과 비교한다.</li>
<li>Case2: 물건의 무게가 남아있는 배낭의 무게보다 작은 경우</li>
</ul>
</li>
<li><blockquote>
<p>물건이 들어갈 수 있기 때문에 이전 물건을 탐색할 때 같은 무게에 현재 물건의 가치를 더한다.</p>
</blockquote>
<h4 id="일반화">일반화</h4>
<ul>
<li>위 컨셉을 일반화 하면 다음과 같다.<h5 id="notation">Notation</h5>
<img src="https://images.velog.io/images/ko-inseoklee/post/4700e938-3b3c-4898-89a9-d66a01b98fb4/image.png" alt=""><h5 id="fomula">Fomula</h5>
<img src="https://images.velog.io/images/ko-inseoklee/post/cfb3bdd6-aeae-47e8-b5a8-6c0a6c60f34c/image.png" alt=""></li>
<li>위와 같은 일반식으로 생성한 2-D array의 최대값을 구한다.</li>
</ul>
</li>
</ul>
<h3 id="코드구현c">코드구현(C++)</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;stdlib.h&gt;

using namespace std;

struct thing{
    int weight;
    int value;
};

int n, k;
thing* things;

int main(){
    cin &gt;&gt; n &gt;&gt; k;

    things = new thing[n];
    int ** mat;
    mat = (int **) malloc(sizeof(int *) * (n));    

    for(int i = 0; i &lt; n; i++){
        cin &gt;&gt; things[i].weight &gt;&gt; things[i].value;
        mat[i] = new int[k+1];
    }

    int max_val = 0;

    for(int i = 0; i &lt;= k; i++){
        if(things[0].weight &gt; i) mat[0][i] = 0;
        else mat[0][i] = things[0].value;
    }

    max_val = mat[0][k];

    for(int i = 1; i &lt; n; i++){
        for(int j = 0; j &lt;= k; j++){
            if(j &lt; things[i].weight) mat[i][j] = mat[i-1][j];
            else{
                int val1 = things[i].value + mat[i-1][j-things[i].weight];
                int val2 = mat[i-1][j];

                mat[i][j] = val1 &gt; val2? val1 : val2;

                if(mat[i][j] &gt; max_val) max_val = mat[i][j];
            }
        }
    }

    cout &lt;&lt; max_val &lt;&lt; endl;
}</code></pre>
<h2 id="factional-knapsack-problem">Factional Knapsack Problem</h2>
<ul>
<li>물건을 쪼개 배낭에 넣을 수 있을 때, 배낭 안에 들어갈 수 있는 최대 가치를 구하는 문제.</li>
<li>Greedy Algorithm으로 문제를 해결할 수 있다.</li>
</ul>
<blockquote>
<h3 id="접근-방식-1">접근 방식</h3>
</blockquote>
<ol>
<li>물건을 쪼갤 수 있기 때문에, 각 물건의 가치와 무게의 비율을 계산한다.</li>
<li>계산한 물건의 단위 무게당 가치 비율이 높은 순서로 정렬한다.</li>
<li>물건을 차례대로 가방에 넣고, 가방에 전부 넣지 못하는 마지막 물건을 쪼개 넣을 수 있는 만큼만 넣어준다.</li>
</ol>
<h3 id="코드-구현c">코드 구현(C++)</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;

struct thing{
    int weight;
    int value;
    double value_ratio;
};

bool cmp(thing t1, thing t2){
    return t1.value_ratio &gt; t2.value_ratio;
}

int n, k;
thing* things;

int main(){
    cin &gt;&gt; n &gt;&gt; k;

    things = new thing[n];

    for(int i = 0; i &lt; n; i++){
        cin &gt;&gt; things[i].weight &gt;&gt; things[i].value;
        things[i].value_ratio = (double) things[i].value / things[i].weight;
    }

    sort(things, things + n, cmp);

    double max_val = 0;

    int idx = 0;
    while(1){
        if(things[idx].weight &gt; k){
            max_val += things[idx].value_ratio * k;
            break;
        }
        else{
            max_val += things[idx].value;
            k -= things[idx].weight;
        }
        idx++;
        if(k == 0 || idx == n) break;
    }

    cout &lt;&lt; max_val &lt;&lt; endl;
}</code></pre>
<h2 id="출처-및-링크">출처 및 링크</h2>
<p>문제
<a href="https://leetcode.com/problems/add-two-numbers/">https://leetcode.com/problems/add-two-numbers/</a>
코드
<a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/2.AddTwoNumbers.py">https://github.com/ko-inseoklee/ProblemSolving/blob/main/2.AddTwoNumbers.py</a></p>
<h4 id="풀이와-후기-이외에-다른-알고리즘이-있거나-알고리즘-오류-코드에서-불필요한-부분이나-더-효율적으로-사용할-수-있는-부분이-있다면-말씀해주세요">풀이와 후기 이외에 다른 알고리즘이 있거나, 알고리즘 오류, 코드에서 불필요한 부분이나 더 효율적으로 사용할 수 있는 부분이 있다면 말씀해주세요.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Study] 09.06 스프링 공부 노트]]></title>
            <link>https://velog.io/@ko-inseoklee/Study-09.06-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B3%B5%EB%B6%80-%EB%85%B8%ED%8A%B8</link>
            <guid>https://velog.io/@ko-inseoklee/Study-09.06-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B3%B5%EB%B6%80-%EB%85%B8%ED%8A%B8</guid>
            <pubDate>Mon, 06 Sep 2021 12:08:37 GMT</pubDate>
            <description><![CDATA[<h2 id="git-lf-to-crlf-오류">git LF to CRLF 오류</h2>
<ul>
<li>개행문자를 처리방식이 OS마다 다르기 때문에 생기는 오류. 윈도우 OS에서는 CRLF를 개행문자로 사용하기 때문에 git config core.autocrlf true 명령어를 입력해주면 된다.</li>
</ul>
<h2 id="test-이용">Test 이용</h2>
<ul>
<li><p>지금까지는 디바이스에서 콘솔에 찍어보는 방식으로 간단한 테스트를 했었지만, 강의를 통해 Test 패키지를 적극적으로 이용해야겠다는 생각을 했다.</p>
</li>
<li><p>강의에서는 Given-When-Then으로 이어지는 테스트 패턴을 소개한다. 각 부분의 태스크를 명확히해 명료한 테스트 과정을 제공한다. </p>
<pre><code class="language-java">@Test
public void join(){
  //Given
  //When
  //Then    
}</code></pre>
</li>
</ul>
<h2 id="tdd-test-driven-development">TDD (Test Driven Development)</h2>
<ul>
<li>개발할 기능에 대한 테스트 케이스를 미리 작성하고 그 테스트를 통과하기 위한 코드를 작성하는 reverse 방식의 코딩 기법.</li>
</ul>
<h2 id="강의">강의</h2>
<p>스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의(김영한)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 9012.괄호]]></title>
            <link>https://velog.io/@ko-inseoklee/%EB%B0%B1%EC%A4%80-9012.%EA%B4%84%ED%98%B8</link>
            <guid>https://velog.io/@ko-inseoklee/%EB%B0%B1%EC%A4%80-9012.%EA%B4%84%ED%98%B8</guid>
            <pubDate>Thu, 02 Sep 2021 09:58:31 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고 부른다. 한 쌍의 괄호 기호로 된 “( )” 문자열은 기본 VPS 이라고 부른다. 만일 x 가 VPS 라면 이것을 하나의 괄호에 넣은 새로운 문자열 “(x)”도 VPS 가 된다. 그리고 두 VPS x 와 y를 접합(concatenation)시킨 새로운 문자열 xy도 VPS 가 된다. 예를 들어 “(())()”와 “((()))” 는 VPS 이지만 “(()(”, “(())()))” , 그리고 “(()” 는 모두 VPS 가 아닌 문자열이다. </p>
<p>여러분은 입력으로 주어진 괄호 문자열이 VPS 인지 아닌지를 판단해서 그 결과를 YES 와 NO 로 나타내어야 한다. </p>
<h2 id="입출력">입출력</h2>
<blockquote>
<p>Input
6
(())())
(((()())()
(()())((()))
((()()(()))(((())))()
()()()()(()()())()
(()((())()(</p>
</blockquote>
<blockquote>
<p>Output
NO
NO
YES
NO
YES
NO</p>
</blockquote>
<h2 id="풀이">풀이</h2>
<p>이 문제는 스택으로 풀 수 있다. VPS의 특성을 생각해보면,</p>
<ol>
<li>한번 열린 괄호는 반드시 닫혀야 한다.( &#39;(&#39; )</li>
<li>닫힌 괄호는 열린 괄호보다 먼저 올 수 없다.</li>
<li>모든 괄호에는 짝이 있어야 한다.</li>
</ol>
<p>두 가지를 스택에 적용시키면, 다음과 같이 해결할 수 있다.</p>
<ol>
<li>열린 괄호가 올 경우, 스택에 PUSH한다.
2-1. 닫힌 괄호가 열린 괄호보다 먼저 오는 경우, VPS를 만족하지 않는다.
2-2. 2-1이 아닌 경우, 스택에서 POP한다.</li>
<li>모든 과정이 끝났을 때, 스택은 비어있어야 한다.</li>
</ol>
<p>위 과정으로 문제를 해결했다.</p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;stack&gt;
#include &lt;cstring&gt;

using namespace std;

bool checkVPS(char *command){
    stack&lt;char&gt; parenthesis;


    for(int i = 0; i &lt; strlen(command); i++){
        if(command[i] == &#39;)&#39;){
            if(parenthesis.empty()) {
                return false;
            }
            else parenthesis.pop();
        }
        else{
            parenthesis.push(command[i]);
        }
    }   

    return parenthesis.empty();
}

int main(){
    int numberOfCommand = -1;
    cin &gt;&gt; numberOfCommand;
    char commandLine[51];
    char *command = commandLine;

    for(int i = 0; i &lt; numberOfCommand; i++){
        cin &gt;&gt; command;
        if(checkVPS(command)) cout &lt;&lt; &quot;YES&quot; &lt;&lt; endl;
        else cout &lt;&lt; &quot;NO&quot; &lt;&lt; endl;
    }

    return 0;
}</code></pre>
<h2 id="후기">후기</h2>
<ul>
<li><p>처음에는 계속해서 runtime error(NeverBeNull)를 받았는데, 생각해보니 입력받는 command 문자열의 포인터에 사이즈를 할당해주지 않아서 생긴 에러였다.
<img src="https://images.velog.io/images/ko-inseoklee/post/050cbb49-5486-4489-a250-9e268ddcc252/image.png" alt=""></p>
</li>
<li><p>틀렸다는 메세지가 계속해서 나왔는데, 명령을 입력받는 문자열의 길이가 문제였다. 문제에서는 괄호로 되어있는 명령문의 길이가 2&lt;= length &lt;= 50으로 되어 있었는데, 50개의 괄호가 입력될 경우 문자열 마지막에 \0가 입력될 수 없기 때문에 계속 틀렸다는 문구를 받았다. 입력 문자열의 길이를 51로 변경한 이후 정답을 받을 수 있었다.</p>
</li>
<li><p>처음에는 표시만 잘 하자는 의미로 Stack의 타입을 int로 받았는데, 생각해보니 int type은 4byte이고, char type은 1byte이니 메모리 활용면에서 char type을 이용하는 것이 효율적이라고 생각해서 변경했다.</p>
</li>
</ul>
<h4 id="풀이와-후기-이외에-다른-알고리즘이-있거나-코드에서-불필요한-부분이나-더-효율적으로-사용할-수-있는-부분이-있다면-말씀해주세요">풀이와 후기 이외에 다른 알고리즘이 있거나, 코드에서 불필요한 부분이나 더 효율적으로 사용할 수 있는 부분이 있다면 말씀해주세요.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Flutter개발노트] 09.01 Platform Exception & AlertDialog]]></title>
            <link>https://velog.io/@ko-inseoklee/Flutter%EA%B0%9C%EB%B0%9C%EB%85%B8%ED%8A%B8-09.01-Platform-Exception-AlertDialog</link>
            <guid>https://velog.io/@ko-inseoklee/Flutter%EA%B0%9C%EB%B0%9C%EB%85%B8%ED%8A%B8-09.01-Platform-Exception-AlertDialog</guid>
            <pubDate>Wed, 01 Sep 2021 17:48:25 GMT</pubDate>
            <description><![CDATA[<h2 id="platform-exception-문제해결">Platform Exception 문제해결.</h2>
<p>학교에서 대여한 맥북을 반납하고, 부득이하게 윈도우 환경의 데스크탑에 프로젝트를 이전해왔다. 세팅을 끝내고, 작업을 시작하려 에뮬레이터에 빌드했는데, 로그인 화면에서 홈 화면으로 이동이 안됐다. 에러 로그를 확인해보니 Platform Exception(sign_in)이 떠 있었다.(고칠 때 캡처를 해둘 껄 그랬다.)
<img src="https://images.velog.io/images/ko-inseoklee/post/d39c3fe9-82ff-46a5-ab57-35ea0f5f54a1/%EC%82%AC%EB%B3%B8%20-Screenshot_1630516483.png" alt=""></p>
<p>해결 방법은 의외로 간단하다. 개발 기기를 바꿔 SHA 인증서를 새로 입력해줘야 했던 것이다.
먼저, SHA인증서를 확인한다.</p>
<blockquote>
<p>cd ./android
keytool -list -v -keystore debug.keystore</p>
</blockquote>
<p>이후, Firebase의 프로젝트 설정에 들어가서 찾은 SHA인증서를 등록해주면 된다!</p>
<h2 id="alertdialog-width-조절하기">AlertDialog Width 조절하기.</h2>
<p>프로젝트 안에 AlertDialog를 사용하는 기능들이 굉장히 많은데, 디자이너가 뽑아주는 디자인보다 항상 width가 작아 보기 좋지 않았다. 구글링을 했을 때 Dialog로 변경하고 width를 double.infinite로 변경해주는 해결법이 가장 많이 나왔지만, 내 경우에서는 적용되지 않았다.
한참을 고민하다, Flutter dev tool을 이용해 확인해보니, Padding이 alertdialog를 감싸고 있다는 것을 알아차렸다. API를 찾던 중 InsetPadding이라는 속성이 눈에 들어왔다.
<img src="https://images.velog.io/images/ko-inseoklee/post/67d98eeb-5656-44b8-a471-e7a01ca36c81/image.png" alt=""></p>
<p>위 속성을 조정해주니 Width가 늘어난것을 확인할 수 있었다. API활용을 잘해야겠다고 다시 한 번 다짐해본다.</p>
<div style="display:flex;">
<img src="https://images.velog.io/images/ko-inseoklee/post/fee99d98-d278-4d67-ae35-721a5d4e50be/before.png" alt="준비 중" width='30%' height='30%'>
  &nbsp &nbsp &nbsp
    <img src="https://images.velog.io/images/ko-inseoklee/post/438be9d9-7ab1-4791-920d-62559aefdf5a/after.png" alt="준비 중" width="30%"  height="30%">
</div>

<h3 id="코드">코드</h3>
<p>AlertDialog에 아래와 같은 property를 추가해주었다. padding의 값을 넣어줄 때 사용한 ScreenUtil() 패키지는 각 디바이스 환경에 맞는 길이에 맞게 사이즈를 조절해주는 패키지이다. pubdev에 자세히 나와있다.</p>
<pre><code class="language-dart">      insetPadding: EdgeInsets.fromLTRB(ScreenUtil().setWidth(20), ScreenUtil().setHeight(16), ScreenUtil().setWidth(20), ScreenUtil().setHeight(16)),</code></pre>
<h2 id="출처">출처</h2>
<p>[SHA 인증서 찾기] <a href="https://kwonsaw.tistory.com/327">https://kwonsaw.tistory.com/327</a> [토끼파파의 게임 블로그]</p>
<p>[ALERTDIALOG API] <a href="https://api.flutter.dev/flutter/material/AlertDialog/insetPadding.html">https://api.flutter.dev/flutter/material/AlertDialog/insetPadding.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CPP] 백준10828. 스택]]></title>
            <link>https://velog.io/@ko-inseoklee/%EB%B0%B1%EC%A4%80-10828.-%EC%8A%A4%ED%83%9D-mwcz6hbx</link>
            <guid>https://velog.io/@ko-inseoklee/%EB%B0%B1%EC%A4%80-10828.-%EC%8A%A4%ED%83%9D-mwcz6hbx</guid>
            <pubDate>Wed, 01 Sep 2021 04:48:07 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.</p>
<p>명령은 총 다섯 가지이다.</p>
<p>push X: 정수 X를 스택에 넣는 연산이다.
pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
size: 스택에 들어있는 정수의 개수를 출력한다.
empty: 스택이 비어있으면 1, 아니면 0을 출력한다.
top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.</p>
<h2 id="입출력">입출력</h2>
<blockquote>
<p>Input:
14
push 1
push 2
top
size
empty
pop
pop
pop
size
empty
pop
push 3
empty
top</p>
</blockquote>
<blockquote>
<p>Output:
2
2
0
2
1
-1
0
1
-1
0
3</p>
</blockquote>
<h2 id="내-풀이">내 풀이</h2>
<p>사실 스택은 STL에도 기본적으로 내장되어 있지만, 다시 한번 자료구조, C++을 공부하는 마음으로 직접 구현해봤다. 스택의 기능들은 별다른 알고리즘이 필요하지는 않아 풀이 자체보다는 어색한 언어를 사용함에 있어서 입출력이나, 문법의 문제가 많았다.</p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;sstream&gt;
#include &lt;cstring&gt;
#include &lt;cstdio&gt;

using namespace std;

#define MAXLENGTH = 10000;

class Stack{
    private:
        int top, MaxSize;
        int *stack;
    public:
        Stack(int size);
        int isEmpty();
        int isFool();
        int topElement();
        int pop();
        int size();
        void push(int element);
};

Stack::Stack(int size){
    MaxSize = size;
    stack = new int[MaxSize];
    top = -1;
}

int Stack::isEmpty(){
    if(top == -1) return 1;
    return 0;
}

int Stack::isFool(){
    if(top == MaxSize-1) return 1;
    return 0;
}

int Stack::topElement(){
    if(isEmpty() == 1) return -1;
    return stack[top];
}

int Stack::size(){
    return top+1;
}

int Stack::pop(){
    if(isEmpty() == 1) return -1;
    return stack[top--];
}

void Stack::push(int element){
    if(isFool() != 1) stack[++top] = element;
}

int commandNumber(char* command){    
    if(!strcmp(command,&quot;pop&quot;)) return 1;
    if(!strcmp(command,&quot;size&quot;)) return 2;
    if(!strcmp(command,&quot;empty&quot;)) return 3;
    if(!strcmp(command,&quot;top&quot;)) return 4;
    if(!strcmp(command,&quot;push&quot;)) return 0;
    return -1;
}

int main(){
    Stack stack = Stack(MAXLENGTH);

    int numberOfCommand;
    cin &gt;&gt; numberOfCommand;
    fflush(stdin);


    char command[20]; 
    int i = 0;

    for(int i = 0; i &lt; numberOfCommand; i++){
        scanf(&quot;%s&quot;,command);

        switch(commandNumber(command)){
            case 0:{
                int element;
                scanf(&quot;%d&quot;,&amp;element);

                stack.push(element);
                break;
            }
            case 1:{
                cout &lt;&lt; stack.pop() &lt;&lt; endl;
                break;
            }
            case 2:{
                cout &lt;&lt; stack.size() &lt;&lt; endl;
                break;
            }
            case 3:{
                cout &lt;&lt; stack.isEmpty() &lt;&lt; endl;
                break;
            }
            case 4:{
                cout &lt;&lt; stack.topElement() &lt;&lt; endl;
                break;
            }
            default:{}

        }
    }
    return 0;
}</code></pre>
<h2 id="후기">후기</h2>
<ul>
<li><p>입력을 받는데 있어서 큰 어려움이 있어 계속해서 틀렸다는 메세지를 받았다. 결국 입력문을 수정하다 문제를 풀게 되었다. 처음에는 모든 문자열을 string 타입으로 사용했었는데, C만 했던 나는 char*과 string에서 사용하는 함수의 차이를 잘 구분하기가 어려웠다. gets, fgets, scanf를 차례로 쓰다보니 문제를 해결할 수 있었다. scanf가 공백을 구분해서 입력을 받아온다는 것 이외에는 아직 입출력에서 결과의 차이를 보이는지 잘 모르겠다. 내 IDE에서는 fgets, scanf 모두 정상적으로 작동했다.</p>
</li>
<li><p>입력 받는 로직을 입력문에 맞게 변경하기도 했다. fgets의 경우 push를 염두하여 처음 사용했었는데, push 뒤에 오는 숫자를 한번에 받아오기 위해 사용했었다. 결국 공백 기준으로 자르는 scanf를 사용하여 push일 경우 한번 더 입력을 받아오는 방식으로 입력 로직을 변경했다. 결과적으로는 Command(push)와 숫자(ex.14)를 한꺼번에 받아와서 뒤에 숫자를 따로 분류하는 로직보다 간결했다는 것을 느꼈다.</p>
</li>
<li><p>알고리즘을 생각할 필요가 없다보니, 주어진 조건에 맞게끔 코딩하려 노력했다. command 변수의 길이가 20인 것도 수정해야겠지만, 주어진 조건 안에서 가장 메모리를 적게 사용하게끔 노력했다. 언어가 조금 더 익숙해지면 동적할당을 이용하여 stack 사이즈를 동적으로 할당하는 방식으로 구현해 봐야겠다.</p>
</li>
</ul>
<h2 id="출처-및-링크">출처 및 링크</h2>
<p>문제
<a href="https://www.acmicpc.net/problem/10828">https://www.acmicpc.net/problem/10828</a>
코드
<a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/10828.Stack.cpp">https://github.com/ko-inseoklee/ProblemSolving/blob/main/10828.Stack.cpp</a></p>
<h4 id="풀이와-후기-이외에-다른-알고리즘이-있거나-코드에서-불필요한-부분이나-더-효율적으로-사용할-수-있는-부분이-있다면-말씀해주세요">풀이와 후기 이외에 다른 알고리즘이 있거나, 코드에서 불필요한 부분이나 더 효율적으로 사용할 수 있는 부분이 있다면 말씀해주세요.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] Leetcode RE-2. Add Two Numbers  ]]></title>
            <link>https://velog.io/@ko-inseoklee/Problem-Solving-RE-2.-Add-Two-Numbers</link>
            <guid>https://velog.io/@ko-inseoklee/Problem-Solving-RE-2.-Add-Two-Numbers</guid>
            <pubDate>Sat, 27 Mar 2021 09:37:45 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-및-예시는-이전에-포스팅한-글을-찾아보시기-바랍니다">문제 및 예시는 이전에 포스팅한 글을 찾아보시기 바랍니다.</h3>
<h2 id="다른-풀이">다른 풀이</h2>
<ul>
<li>L1과 L2의 값을 Stack처럼 꺼내 Integer로 저장한다.</li>
<li>결과로 나온 두 Integer를 더한다.</li>
<li>두 Integer의 합에서 각 자리 수를 가져와 ListNode로 만들어준다.</li>
</ul>
<h2 id="코드">코드</h2>
<p><img src="https://images.velog.io/images/ko-inseoklee/post/c990d491-7d34-4197-a987-93b6ea46b415/%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%202021-03-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.45.53.png" alt=""></p>
<h2 id="두-풀이-비교">두 풀이 비교</h2>
<ul>
<li>코드가 이전 코드에 비해 약간 길다. (30줄 vs 40줄)</li>
<li>Time Complexity면에서는 양쪽 다 전체 Linked List를 한번 탐색하기 때문에 O(n)이기 때문에 큰 차이가 없지만, 이전 코드에는 조건문 및 반복문의 조건이 수정한 코드에 비해 다소 많고 복잡하기 때문에, 실질적인 Runtime은 후자가 조금 더 빠를 것 같다.</li>
<li>개인적으로는, 뒤에 짠 코드가 가독성면에서 더 낫고 짜기 쉽다는 생각이 들어서(30줄과 40줄의 싸움이지만...) 후자가 더 낫다고 생각한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] Leetcode 29. Divide Two Integers]]></title>
            <link>https://velog.io/@ko-inseoklee/Problem-Solving-29.-Divide-Two-Integers</link>
            <guid>https://velog.io/@ko-inseoklee/Problem-Solving-29.-Divide-Two-Integers</guid>
            <pubDate>Sat, 27 Mar 2021 08:19:27 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>Dividend, Divisor 두 Integer 값을 나누면 되는 간단한 문제이다. 하지만, multiply, divide, percent operation을 사용하면 안되는 제약 조건이 있다. 결과 값으로는 나눈 값의 몫을 출력한다.</p>
<h2 id="입출력">입출력</h2>
<blockquote>
<p>Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 = truncate(3.33333..) = 3.</p>
</blockquote>
<blockquote>
<p>Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = truncate(-2.33333..) = -2.</p>
</blockquote>
<h2 id="풀이">풀이</h2>
<ul>
<li><p>Integer범위, divisor != 0 등의 기본적인 조건과, 내 로직이 성립하기 위한 조건들을 코드 앞부분에 처리했다.</p>
<blockquote>
<p>Dividend = Divisor * 몫 + 나머지</p>
</blockquote>
</li>
<li><p>기본적인 나눗셈은 위와 같이 표현이 가능한데, 곱셈 대신 Divisor의 제곱 수를 이용하여 뺄셈을 해주는 방식으로 표현이 가능하다. 268/3 을 예시로 들어보자.
<img src="https://images.velog.io/images/ko-inseoklee/post/908bd2ad-619e-498b-bd6f-bcb280e1935d/%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%202021-03-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.57.28.png" alt=""> </p>
</li>
<li><p>위 예시와 같이 나누는 수의 거듭제곱 값을 빼주는 식의 접근이 가능하다.</p>
</li>
<li><p>Dividend 값에 가장 근접한 Divisor의 거듭제곱 수를 구한다.</p>
</li>
<li><p>Dividend 값이 Divisor값보다 작아질 때까지(나머지만 남을 때 까지) Dividend에서 Divisor의 거듭제곱 수를 빼주며 거듭제곱 수를 줄여주는 작업을 반복한다.</p>
</li>
</ul>
<h2 id="분석">분석</h2>
<ul>
<li>먼저, Dividend와 인접한 Divisor의 거듭제곱을 구하기 위해 O(log n)만큼 시간이 필요.</li>
<li>다음으로, Dividend를 Divisor의 거듭제곱 수로 빼주면서 거듭제곱 수를 줄이기 때문에 O(log n)의 시간이 필요.</li>
<li>Total Time Complexity: O(log n)</li>
</ul>
<h2 id="코드">코드</h2>
<pre><code>class Solution:
def divide(self, dividend: int, divisor: int) -&gt; int:
    sign = True
    result = 0

    limit = pow(2,31) - 1

    if(-(limit + 1) &gt; dividend &gt; limit):
        return -1
    if(divisor == 0 or -(limit + 1) &gt; divisor &gt; limit):
        return -1

    if(divisor == 1):
        return dividend
    if(divisor == -1):
        if(dividend &gt; limit + 1):
            return -(limit + 1)
        if(dividend &lt; -limit):
            return limit
        return -dividend

    dend = dividend
    sor = divisor

    if(sor &lt; 0):
        sor = -sor
        sign = not sign
    if(dend &lt; 0):
        dend = -dend
        sign = not sign

    if(sor &gt; dend):
        return 0

    a = dend
    b = sor

    exp = 1
    while(a &gt;= b):
        exp += 1
        b = pow(sor, exp)

    exp -= 1
    b = pow(sor, exp)

    while(a &gt;= sor):
        if(a &gt;= b):
            a -= b
            result += pow(sor,exp-1)
        else:
            exp -= 1
            b = pow(sor,exp)

    if(sign):
        if(result &gt; limit):
            return limit
        return result
    else:
        return -result</code></pre><h2 id="후기">후기</h2>
<p>이 문제는 꽤 흥미로웠다. 어떤 알고리즘을 사용했다기보다, 기본적인 사칙연산의 이해가 필요한 문제였다고 생각한다. 평소에는 잘 생각하지 않고 사칙연산을 사용하다보니 원리를 다시 생각하는데 까지의 시간이 많이 들긴 했지만, 그 이후 실질적 코딩은 어렵지 않았다.</p>
<h2 id="출처-및-링크">출처 및 링크</h2>
<p>문제
<a href="https://leetcode.com/problems/divide-two-integers/">https://leetcode.com/problems/divide-two-integers/</a>
코드
<a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/29.DivideTwoIntegers.py/">https://github.com/ko-inseoklee/ProblemSolving/blob/main/29.DivideTwoIntegers.py/</a></p>
<h4 id="풀이와-후기-이외에-다른-알고리즘이-있거나-코드에서-불필요한-부분이나-더-효율적으로-사용할-수-있는-부분이-있다면-말씀해주세요">풀이와 후기 이외에 다른 알고리즘이 있거나, 코드에서 불필요한 부분이나 더 효율적으로 사용할 수 있는 부분이 있다면 말씀해주세요.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] Leetcode 2. Add Two Numbers  ]]></title>
            <link>https://velog.io/@ko-inseoklee/Problem-Solving-2.-Add-Two-Numbers</link>
            <guid>https://velog.io/@ko-inseoklee/Problem-Solving-2.-Add-Two-Numbers</guid>
            <pubDate>Tue, 02 Mar 2021 07:12:51 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>각 노드의 값이 0~9 사이인 Linked List 두 개가 주어진다. 리스트 안의 값들은 역순으로 저장이 되어 있다. 두 리스트 속의 노드의 합을 새로운 Linked List에 저장하면 된다. 역순으로 저장이 되어있기 때문에 받아올림이 발생할 경우 뒤에 오는 값에 올려준다.</p>
<h2 id="예시">예시</h2>
<p>예시를 보면, 각 Linked List의 중간에 있는 노드 값의 합은 10이다. 하지만, 각 노드의 값은 0~9 사이로 올 수 있으므로, Next에 오는 노드에 받아올림이 전달되고, 3+4+1의 값으로 8이 오는 것을 볼 수 있다.</p>
<p><img src="https://images.velog.io/images/ko-inseoklee/post/ba0f3078-06dd-4e1e-9973-d6e999586b30/%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%202021-03-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.18.41.png" alt=""></p>
<h2 id="입출력">입출력</h2>
<blockquote>
<p>Input1: l1 = [2,4,3], l2 = [5,6,4]
Output1: [7,0,8]</p>
</blockquote>
<blockquote>
<p>Input2: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output2: [8,9,9,9,0,0,0,1]</p>
</blockquote>
<h2 id="내-풀이">내 풀이</h2>
<ul>
<li><p>Linked List에 대한 이해만 있다면 어렵지 않게 풀 수 있는 문제라고 생각한다.</p>
</li>
<li><p>내 경우에는 리스트 안에서 노드를 이동시키면서 각 노드의 값을 더해 출력할 List에 저장해줬는데, 이 방식으로 풀 때 주의할 점은 Root Node의 값을 저장하지 않으면 찾을 방법이 없다는 것이다. 맨 윗줄의 ListNode 클래스는 문제에서 주어졌는데, Double Linked List가 아니기 때문에 현재 노드를 Next로 갖고 있는 Node를 찾기 어렵기 때문이다. </p>
</li>
<li><p>내 경우에는 While Loop가 돌아가기 전에 result에 temp Instance를 지정해서 Root Node를 확보한 이후 L1,L2 노드의 값을 찾아 순서대로 더했다.</p>
</li>
</ul>
<h2 id="코드">코드</h2>
<p><img src="https://images.velog.io/images/ko-inseoklee/post/7cba5e11-7ef1-4702-85b0-713ae078289a/%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%202021-03-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.43.06.png" alt=""></p>
<h2 id="후기">후기</h2>
<ul>
<li>Leetcode를 처음 이용해봤는데, 문제를 푼 시간과 사용한 메모리의 양을 다른 사람들과 비교해서 보여주는 것이 효과적이었다. 처음 작성한 코드에서는 다른 사람들에 비해 시간을 많이 소모한 것을 발견했고, 한번 다듬은 코드가 위 코드이다.</li>
<li>그럼에도 불구하고 더 효율적인 방법이 많이 있었다. 한 가지 떠오르는 대안은 역순으로 되어 있는 L1과 L2의 값을 다시 역순으로 돌려 원래 순서로 만든 다음 덧셈을 하고 다시 거꾸로 결과 리스트에 집어넣는 방식이다. 정확하게 어느 쪽이 연산 속도가 빠른지 잘 모르겠다.(해보고 글을 수정하겠다.)</li>
</ul>
<h2 id="출처-및-링크">출처 및 링크</h2>
<p>문제
<a href="https://leetcode.com/problems/add-two-numbers/">https://leetcode.com/problems/add-two-numbers/</a>
코드
<a href="https://github.com/ko-inseoklee/ProblemSolving/blob/main/2.AddTwoNumbers.py">https://github.com/ko-inseoklee/ProblemSolving/blob/main/2.AddTwoNumbers.py</a></p>
<h4 id="풀이와-후기-이외에-다른-알고리즘이-있거나-코드에서-불필요한-부분이나-더-효율적으로-사용할-수-있는-부분이-있다면-말씀해주세요">풀이와 후기 이외에 다른 알고리즘이 있거나, 코드에서 불필요한 부분이나 더 효율적으로 사용할 수 있는 부분이 있다면 말씀해주세요.</h4>
]]></description>
        </item>
    </channel>
</rss>