<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>doomini.log</title>
        <link>https://velog.io/</link>
        <description>귀여운 걸 좋아하는 개발자입니다 😸</description>
        <lastBuildDate>Sun, 25 May 2025 14:20:28 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>doomini.log</title>
            <url>https://velog.velcdn.com/images/j-ij-i/profile/60ea45fc-7ae9-4920-b254-84a2ccf5965b/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. doomini.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/j-ij-i" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[네이버 지도 Open API 인증이 실패하였습니다. 클라이언트 아이디와 웹 서비스 URL을 확인해 주세요. (2025.05 기준)]]></title>
            <link>https://velog.io/@j-ij-i/%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%A7%80%EB%8F%84-Open-API-%EC%9D%B8%EC%A6%9D%EC%9D%B4-%EC%8B%A4%ED%8C%A8%ED%95%98%EC%98%80%EC%8A%B5%EB%8B%88%EB%8B%A4.-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%95%84%EC%9D%B4%EB%94%94%EC%99%80-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-URL%EC%9D%84-%ED%99%95%EC%9D%B8%ED%95%B4-%EC%A3%BC%EC%84%B8%EC%9A%94.-2025.05-%EA%B8%B0%EC%A4%80</link>
            <guid>https://velog.io/@j-ij-i/%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%A7%80%EB%8F%84-Open-API-%EC%9D%B8%EC%A6%9D%EC%9D%B4-%EC%8B%A4%ED%8C%A8%ED%95%98%EC%98%80%EC%8A%B5%EB%8B%88%EB%8B%A4.-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%95%84%EC%9D%B4%EB%94%94%EC%99%80-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-URL%EC%9D%84-%ED%99%95%EC%9D%B8%ED%95%B4-%EC%A3%BC%EC%84%B8%EC%9A%94.-2025.05-%EA%B8%B0%EC%A4%80</guid>
            <pubDate>Sun, 25 May 2025 14:20:28 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/j-ij-i/post/34d1bd68-3b6e-4887-9ea5-53b548901b22/image.png" alt=""></p>
<h3 id="오류-상황">오류 상황</h3>
<p><img src="https://velog.velcdn.com/images/j-ij-i/post/d398c2c8-9aa0-4655-8193-91db3d79cecc/image.png" alt=""></p>
<blockquote>
<p>네이버 지도 Open API 인증이 실패하였습니다. 클라이언트 아이디와 웹 서비스 URL을 확인해 주세요.,  * Error Code / Error Message: 200 / Authentication Failed,  * Client ID: (클라이언트키),  * URI: <a href="http://localhost:3000/">http://localhost:3000/</a></p>
</blockquote>
<p>Next.js에서 naver map api를 받아서 사용했는데 계속해서 인증이 실패하는 현상이 있었습니다.</p>
<h3 id="사용된-코드">사용된 코드</h3>
<pre><code>&lt;Script type=&quot;text/javascript&quot; src {`https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=${process.env.NEXT_PUBLIC_NAVER_ID}`} /&gt;</code></pre><h3 id="해결">해결</h3>
<p><img src="https://velog.velcdn.com/images/j-ij-i/post/2b1d43de-193e-448e-b510-2f1eaea73bcc/image.png" alt=""></p>
<ul>
<li>공식 문서를 확인해보니, 최신 버전 기준으로 <code>ncpClientId</code>가 <code>ncpKeyId</code>로 변경되었습니다.</li>
<li>테스트용으로 블로그에서 예제를 참고했는데, 대부분 예전 방식인 <code>ncpClientId</code> 기준으로 작성되어 있어서 생긴 오류였습니다. 😂</li>
</ul>
<h3 id="출처-및-참고">출처 및 참고</h3>
<p><a href="https://navermaps.github.io/maps.js.ncp/docs/tutorial-2-Getting-Started.html">https://navermaps.github.io/maps.js.ncp/docs/tutorial-2-Getting-Started.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Programmers] Lv. 3 최고의 집합 (python, js)]]></title>
            <link>https://velog.io/@j-ij-i/Programmers-Lv.-3-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EC%A7%91%ED%95%A9-python-js</link>
            <guid>https://velog.io/@j-ij-i/Programmers-Lv.-3-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EC%A7%91%ED%95%A9-python-js</guid>
            <pubDate>Mon, 02 Jan 2023 14:25:00 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12938?language=javascript">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ul>
<li>s를 n만큼 최대한 일정하게 나누었을때가 곱했을 때 가장 큰 값이 됩니다.</li>
<li>따라서 s / n을 하여 몫을 구하고 몫이 s개 만큼 있는 배열을 만듭니다.</li>
<li>그리고 나머지를 1씩 차례대로 더해줍니다.</li>
<li>그리고 sort를 해주어 작은수가 앞에 나오게 합니다.</li>
</ul>
<h3 id="다른풀이-탐색">다른풀이 탐색</h3>
<ul>
<li>python에서 divmod를 사용하면 몫과 나머지를 바로 구할 수 있습니다.</li>
<li>js에서 Array().fill()을 쓰면 편하게 변수를 원하는 만큼 배열에 넣을 수 있습니다.</li>
</ul>
<h3 id="해결-코드">해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">def solution(n, s):
    answer = [s//n] * n
    rem = s%n

    for i in range(rem):
        answer[i] +=1
    answer.sort()

    if answer[0] == 0:
        return [-1]
    else:
        return answer</code></pre>
<h4 id="javascript">javascript</h4>
<pre><code class="language-jsx">function solution(n, s) {
    let answer = [];

    const quo = Math.floor(s/n);
    const rem = Number(s%n);

    for(let i = 0; i &lt; n ; i++){
        answer.push(quo);
    }
    for(let i = 0 ; i &lt; rem ; i ++){
        answer[i] += 1;
    }
    answer.sort();

    if(answer[0] == 0){
        return [-1];
    }else{
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git 주요 명령어 - Git CHEAT SHEET]]></title>
            <link>https://velog.io/@j-ij-i/Git-%EC%A3%BC%EC%9A%94-%EB%AA%85%EB%A0%B9%EC%96%B4-Git-CHEAT-SHEET</link>
            <guid>https://velog.io/@j-ij-i/Git-%EC%A3%BC%EC%9A%94-%EB%AA%85%EB%A0%B9%EC%96%B4-Git-CHEAT-SHEET</guid>
            <pubDate>Thu, 29 Dec 2022 03:28:32 GMT</pubDate>
            <description><![CDATA[<h2 id="왜-작성하게-되었는가">왜 작성하게 되었는가?</h2>
<p>컨퍼런스에 갔다 <code>github</code>에서 진행하는 부스에 들려서 <strong><code>git cheat sheet</code></strong>를 받았습니다!
지류로 남아있으면 보관하기 어려워서 내용들을 벨로그로 옮겨놓으려고 작성했습니다.
<img src="https://velog.velcdn.com/images/j-ij-i/post/d43dbbff-3ca6-4177-a489-aab3bdeb139d/image.png" alt=""></p>
<h2 id="git-cheat-sheet">GIT CHEAT SHEET</h2>
<blockquote>
<p><strong>Git</strong>은 오픈 소스 분산 버전 관리 시스템으로 귀하의 노트북이나 PC에서 Github가 구동될 수 있도록 지원합니다.
이 <strong>Cheat sheet</strong>는 일반적으로 자주 사용되는 Git 명령어를 요약하여 정리한 것 입니다.</p>
</blockquote>
<h3 id="툴-구성">툴 구성</h3>
<h4 id="모든-로컬-저장소에-대한-사용자-정보-구성">모든 로컬 저장소에 대한 사용자 정보 구성</h4>
<ul>
<li><strong><code>$ git config --global user.name &quot;[name]&quot;</code></strong>
Commit Transaction에 원하는 이름을 붙이는 설정</li>
<li><strong><code>$ git config --global user.email &quot;[email address]&quot;</code></strong>
Commit Transaction에 원하는 이메일 설정</li>
<li><strong><code>$ git config --global color.ui auto</code></strong>
명령줄 출력시 가독성을 부여할 자동 색상 기능 활성화</li>
</ul>
<h3 id="저장소-생성">저장소 생성</h3>
<h4 id="새-저장소를-시작하거나-기존-url에서-가져오기">새 저장소를 시작하거나 기존 URL에서 가져오기</h4>
<ul>
<li><strong><code>$ git init [project-name]</code></strong>
지정된 이름으로 새로운 로컬 저장소 생성</li>
<li><strong><code>$ git clone [url]</code></strong>
프로젝트 및 전체 버전 히스토리를 다운로드</li>
</ul>
<h3 id="검토-및-커밋">검토 및 커밋</h3>
<h4 id="편집한-파일을-리뷰하고-commit-transaction-만들기">편집한 파일을 리뷰하고 Commit Transaction 만들기</h4>
<ul>
<li><strong><code>$ git status</code></strong>
새로운 파일이나 Commit 되기 위한 수정된 파일 모두 나열</li>
<li><strong><code>$ git diff</code></strong>
아직 올려 지기 전 파일의 차이점들 나열</li>
<li><strong><code>$ git add [file]</code></strong>
버전 관리에 대비한 파일 스냅샷</li>
<li><strong><code>$ git diff --staged</code></strong>
올려진 파일과 가장 마지막 버전의 파일의 차이점들 나열</li>
<li><strong><code>$ git reset [file]</code></strong>
올리지는 않고 그 내용은 보존하기</li>
<li><strong><code>$ git commit -m &quot;[descriptive message]&quot;</code></strong>
버전 히스토리 상에서 영구적으로 파일 스냅샷을 기록</li>
</ul>
<h3 id="커밋-그룹화">커밋 그룹화</h3>
<h4 id="일련의-commit들에-이름을-지정하고-완성된-노력물들을-결합">일련의 Commit들에 이름을 지정하고 완성된 노력물들을 결합</h4>
<ul>
<li><strong><code>$ git branch</code></strong>
현 저장소에 있는 모든 로컬 브렌치 나열</li>
<li><strong><code>$ git branch [branch-name]</code></strong>
새로운 브렌치 생성</li>
<li><strong><code>$ git checkout [branch-name]</code></strong>
현재 작업중 프렌치에서 체크아웃하고 다른 브렌치로 전환하기</li>
<li><strong><code>$ git merge [branch]</code></strong>
지정된 브렌치의 기록을 현 브렌치에 결합</li>
<li><strong><code>$ git branch -d [branch-name]</code></strong>
지정된 브렌치를 삭제</li>
</ul>
<h3 id="파일명-리팩터링">파일명 리팩터링</h3>
<h4 id="각-버전들의-파일들을-재배치-및-제거">각 버전들의 파일들을 재배치 및 제거</h4>
<ul>
<li><strong><code>$ git rm [file]</code></strong>
저장소를 제거하고 관련된 브렌치도 제거하기</li>
<li><strong><code>$ git rm --cached [file]</code></strong>
버전 관리의 파일을 삭제 - 로컬에서는 파일 보존</li>
<li><strong><code>$ git mv [file-original] [file-renamed]</code></strong>
파일이름을 변경하고 Commit할 준비하기</li>
</ul>
<h3 id="히스토리-제거">히스토리 제거</h3>
<h4 id="임시-파일과-경로들을-제외하기">임시 파일과 경로들을 제외하기</h4>
<pre><code>.log
build/
temp-*</code></pre><p>.gitignore라는 텍스트 파일은 지정된 패턴과 일치하는 파일 및 경로의 우발적 인 버전을 표시하지 않습니다.</p>
<ul>
<li><strong><code>$ git ls-files --other --ignored --exclude-standard</code></strong>
해당 프로젝트에서 무시됐던 파일들 모두 나열</li>
</ul>
<h3 id="프래그먼트-저장">프래그먼트 저장</h3>
<h4 id="미완성된-변경사항들을-복원하거나-저장하기">미완성된 변경사항들을 복원하거나 저장하기</h4>
<ul>
<li><strong><code>$ git stash</code></strong>
수정된 모든 추적파일을 임시로 저장</li>
<li><strong><code>$ git stash pop</code></strong>
가장 최근에 숨겨진 파일을 복원</li>
<li><strong><code>$ git stash list</code></strong>
숨겨진 모든 changesets을 나열</li>
<li><strong><code>$ git stash drop</code></strong>
가장 최근 숨겨진 changeset을 버리기</li>
</ul>
<h3 id="히스토리-리뷰">히스토리 리뷰</h3>
<h4 id="프로젝트-파일의-변화를-탐색하고-검사">프로젝트 파일의 변화를 탐색하고 검사</h4>
<ul>
<li><strong><code>$ git log</code></strong>
현 브렌치의 버전 기록을 나열</li>
<li><strong><code>$ git log --follow [file]</code></strong>
이름 변경을 포함하여 파일의 버전기록 나열</li>
<li><strong><code>$ git diff [first-branch]...[second-branch]</code></strong>
두 브렌치 사이에 내용의 차이점을 표시</li>
<li><strong><code>$ git show [commit]</code></strong>
메타데이터와 지정된 Commit의 내용 변화를 출력</li>
</ul>
<h3 id="commit-다시하기">COMMIT 다시하기</h3>
<h4 id="실수를-삭제하고-재배치-기록-만들기">실수를 삭제하고 재배치 기록 만들기</h4>
<ul>
<li><strong><code>$ git reset [commit]</code></strong>
[commit]이후의 모든 commit을 되돌리기- 로컬상에서는 변경사항</li>
<li><strong><code>$ git reset --hard [commit]</code></strong>
지정된 commit 까지의 모든 기록과 변경점들을 버리기</li>
</ul>
<h3 id="변경-내역-동기화-하기">변경 내역 동기화 하기</h3>
<h4 id="저장소-북마크-등록-및-버전-기록-교환">저장소 북마크 등록 및 버전 기록 교환</h4>
<ul>
<li><strong><code>$ git fetch [bookmark]</code></strong>
저장소 북마크에서 모든 기록 다운로드</li>
<li><strong><code>$ git merge [bookmark]/[branch]</code></strong>
북마크의 브렌치를 현 로컬 브렌치에 결합</li>
<li><strong><code>$ git push [alias] [branch]</code></strong>
모든 로컬 Commit들을 Github에 업로드하기<ul>
<li><strong><code>$ git pull</code></strong>
북마크 기록 다운로드 및 변경점들 결합하기</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>다음번에는 해당 git 명령어들을 하나하나 해보면서 어떤 역할을 하는지 살펴보겠습니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Softeer] 전광판  (python)]]></title>
            <link>https://velog.io/@j-ij-i/Softeer-%EC%A0%84%EA%B4%91%ED%8C%90-python</link>
            <guid>https://velog.io/@j-ij-i/Softeer-%EC%A0%84%EA%B4%91%ED%8C%90-python</guid>
            <pubDate>Fri, 16 Dec 2022 02:14:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/j-ij-i/post/d75d2828-cc43-4afd-b25e-8b5174c63564/image.png" alt=""></p>
<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://softeer.ai/practice/result.do?eventIdx=1&amp;submissionSn=SW_PRBL_SBMS_111775&amp;psProblemId=624">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ol>
<li>0부터 9까지 숫자에 불이 들어오는 전광판 배열로 만들어 놓는다.</li>
<li>비교 문자열 두개를 한자리씩 비교하면서 두 숫자의 전광판 배열이 다르면 +1 해준다. </li>
</ol>
<h3 id="다른-풀이">다른 풀이</h3>
<ul>
<li>나는 숫자가 주어지지 않을때는 &#39;-&#39;로 표현하고 하나하나 한쪽이 -일때, 양쪽이 -일때를 체크해주었는데 그냥 &#39;-&#39;일때는 [0,0,0,0,0,0,0]으로 표현하면 더 코드가 심플하게 작성이 가능했다.<h3 id="해결-코드">해결 코드</h3>
</li>
</ul>
<h4 id="python">Python</h4>
<pre><code class="language-python">
arr = [[1,1,1,0,1,1,1],[0,0,1,0,0,1,0],[1,0,1,1,1,0,1],[1,0,1,1,0,1,1],[0,1,1,1,0,1,0],[1,1,0,1,0,1,1],[1,1,0,1,1,1,1],[1,1,1,0,0,1,0],[1,1,1,1,1,1,1],[1,1,1,1,0,1,1]]

n = int(input())

for _ in range(n):
    init, change = input().split()    

    while len(init)&lt;5:
        init = &#39;-&#39;+init
    while len(change)&lt;5:
        change = &#39;-&#39;+change
    result = 0
    for i in range(5):
        if init[i] == &#39;-&#39; and change[i] == &#39;-&#39;:
            continue
        elif init[i] == &#39;-&#39;:
            for a in arr[int(change[i])]:
                if a == 1:
                    result += 1
        elif change[i] == &#39;-&#39;:
            for a in arr[int(init[i])]:
                if a == 1:
                    result += 1
        else:
            for a in range(7):
                if not arr[int(init[i])][a] == arr[int(change[i])][a]:
                    result += 1
    print(result)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Softeer] 비밀메뉴 (python)]]></title>
            <link>https://velog.io/@j-ij-i/Softeer-%EB%B9%84%EB%B0%80%EB%A9%94%EB%89%B4-python</link>
            <guid>https://velog.io/@j-ij-i/Softeer-%EB%B9%84%EB%B0%80%EB%A9%94%EB%89%B4-python</guid>
            <pubDate>Fri, 16 Dec 2022 01:32:53 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://softeer.ai/practice/info.do?idx=1&amp;eid=623">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ol>
<li>버튼 입력 배열을 모두 받은 다음, 버튼 입력 배열을 처음부터 하나씩 보면서 비밀 메뉴 조작의 첫번째와 같은지 비교한다.</li>
<li>비밀 메뉴 조작의 첫번째랑 똑같은 경우 비밀 메뉴 조작인지 여부를 판단하는데, for 문으로 비밀 메뉴 조작의 길이만큼 돌면서 일치할때마다 cnt를 증가시키고, cnt가 비밀 메뉴 조작의 길이와 최종적으로 일치하면 성공.<h3 id="다른풀이-탐색">다른풀이 탐색</h3>
</li>
</ol>
<ul>
<li>두 배열을 문자열화 시켜서 if  in 만 써서 4줄만에 풀수도 있었다.</li>
<li>M == N[i:i+m]을 써서 이렇게도 간단하게 문자열을 비교할 수 있었다.<h3 id="해결-코드">해결 코드</h3>
</li>
</ul>
<h4 id="python">Python</h4>
<pre><code class="language-python">m,n,k = map(int,input().split())

s_arr = list(map(int, input().split()))

button_list = list(map(int, input().split()))

result = False

for i in range(len(button_list)):
    if s_arr[0] == button_list[i]:
        cnt = 0
        for j in range(len(s_arr)):
            if i+j &gt;= len(button_list):
                break
            else:
                if s_arr[j] == button_list[i+j]:
                    cnt += 1
        if cnt == len(s_arr):
            result = True
            break
if result:
    print(&quot;secret&quot;)
else:
    print(&quot;normal&quot;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Softeer] 회의실 예약 (python)]]></title>
            <link>https://velog.io/@j-ij-i/Softeer-%ED%9A%8C%EC%9D%98%EC%8B%A4-%EC%98%88%EC%95%BD-python</link>
            <guid>https://velog.io/@j-ij-i/Softeer-%ED%9A%8C%EC%9D%98%EC%8B%A4-%EC%98%88%EC%95%BD-python</guid>
            <pubDate>Thu, 15 Dec 2022 02:14:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/j-ij-i/post/ff6369e2-f6ae-4e47-ad69-1467a02b95b2/image.png" alt=""></p>
<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://softeer.ai/practice/info.do?idx=1&amp;eid=626&amp;sw_prbl_sbms_sn=111569">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ol>
<li>input으로 주어지는 미팅룸 이름을 key로 넣고 value는 순서 값을 넣어준다. 
 ex ) santafe:0 aerocity:1 porter:2</li>
<li>미팅룸 예약 리스트는 2차원 배열로 만들어서 [미팅룸][9(9시<del>18시 타임)] 형태의 배열로 만들었다. 9는 9</del>10, 10<del>11, 12</del>13 ... 17~18을 각각의 한칸으로 표현해서 9 크기로 표현했다.</li>
<li>미팅룸 시간에 예약이 되어있으면 -1, 기본값은 0으로 해서 미팅룸을 돌면서 0일때는 예약가능하여 시작 및 끝 시간을 문자열로 만들어 주었다.</li>
</ol>
<h3 id="문제-후기">문제 후기</h3>
<ul>
<li>오랜만에 swea의 입출력을 느껴보는 것 같았다..</li>
<li>프로그래머스가 얼마나 편한지 다시한번 느끼게 되었고 차라리 백준 입출력이 깔끔하다는 것을 느꼈다..!</li>
<li>객체를 sorted 후에 더이상 객체 형태로 남지 않는 다는 것을 까먹고 자꾸 객체를 불러와서 틀렸다.</li>
</ul>
<h3 id="해결-코드">해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">import sys
from collections import defaultdict

n, m= map(int, input().split())

meeting_name = defaultdict()

# 9-10-11-12-13-14-15-16-17-18
meeting_res_list = [[0 for _ in range(9)] for _ in range(n)]

for i in range(n):
    room_name = input()
    meeting_name[room_name] = i

for _ in range(m):
    name, start, end = input().split()
    for i in range( int(start)-9, int(end)-9):
        meeting_res_list[meeting_name[name]][i] = -1

meeting_name_sorted = (sorted(meeting_name.keys()))
total_cnt = 0
for key in meeting_name_sorted:
    print(f&quot;Room {key}:&quot;)
    cnt = 0
    arr = []
    m_key = meeting_name[key]
    times = &#39;&#39;
    flag = False
    for meet in range(9):
        if not flag and meeting_res_list[m_key][meet] == 0:
            flag = True
            if meet == 0:
                times += &quot;09&quot;
            else:
                times += str(meet+9)
            times += &#39;-&#39;
        elif flag and meeting_res_list[m_key][meet] == 0:
            continue
        elif flag and meeting_res_list[m_key][meet] == -1:
            times += str(meet+9)
            arr.append(times)
            times = &#39;&#39;
            flag = False
            cnt += 1
    if flag:
        times += &quot;18&quot;
        arr.append(times)
        cnt += 1
    if cnt == 0:
        print(&quot;Not available&quot;)
    else:
        print(f&quot;{cnt} available:&quot;)
        for time in arr:
            print(time)
    total_cnt+=1            
    if total_cnt &lt; n:
        print(&quot;——&quot;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Baekjoon] 12865 평범한 배낭 (python)]]></title>
            <link>https://velog.io/@j-ij-i/Baekjoon-12865-%ED%8F%89%EB%B2%94%ED%95%9C-%EB%B0%B0%EB%82%AD-python</link>
            <guid>https://velog.io/@j-ij-i/Baekjoon-12865-%ED%8F%89%EB%B2%94%ED%95%9C-%EB%B0%B0%EB%82%AD-python</guid>
            <pubDate>Wed, 14 Dec 2022 02:23:00 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://www.acmicpc.net/problem/12865">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ul>
<li><p>dp문제의 가장 기본적인 문제라 오랜만에 다시 풀었다.</p>
</li>
<li><p>n은 주어지는 물건의 갯수, k는 넣을 수 있는 최대 무게였고 무게배열 w[n+1], 가치배열 v[n+1]를 두고 dp[n+1][k+1]만큼의 dp 배열을 만들어주었다.</p>
</li>
<li><p>총 for 문이 2개가 돌면서 가장 큰 가치를 넣는 dp배열을 만들었고 마지막에 dp[n][k]를 return하면 완료하도록 짰다.</p>
</li>
<li><p>첫번째 for문은 n(물건의 갯수)까지 증가시킨다. 물건 배열을 입력때 받았던 순서대로 증가시킨다.</p>
</li>
<li><p>두번째 for문은 k(무게)까지 증가시키면서 넣을 수 있는 무게에 따른 가치 값을 넣어준다.</p>
</li>
<li><p>따라서 dp[1][7] 이면 첫번째 물건만 파악했을때 7의 무게까지 가질수 있는 dp의 값에 가장 큰 가치를 넣는다.</p>
</li>
<li><p>만약 현재 넣는 물건이 고려하는 무게가 클 경우는 그 물건을 넣기 전의 가치 값을 넣어준다. 따라서 dp[i-1][j]가 된다.</p>
</li>
<li><p>그렇지 않을 경우는 2가지를 비교해서 넣으면 되는데, </p>
<ol>
<li>(dp[i][지금 가질 수 있는 최대 무게 - 현재 그 물건의 무게] + 현재 물건의 가치)</li>
<li>현재 물건을 안넣고 이전 물건까지 고려했을 떄의 가치 =&gt; dp[i-1][j]</li>
</ol>
</li>
<li><p>두 가지를 고려하여 큰 값을 dp[i][j]에 넣는 방식으로 진행한다.</p>
</li>
</ul>
<h3 id="해결-코드">해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">n, k = map(int, input().split())

w = [0 for _ in range(n+1)]
v = [0 for _ in range(n+1)]
dp = [[0 for _ in range(k+1)]for _ in range(n+1)]

for i in range(1,n+1):
    w[i], v[i] = map(int, input().split())

for i in range(1,n+1):
    for j in range(1, k+1):
        if w[i] &gt; j:
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max( (dp[i-1][j-w[i]] + v[i]), dp[i-1][j])

print(dp[n][k])
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Programmers] Lv.3 등굣길 (python)]]></title>
            <link>https://velog.io/@j-ij-i/Programmers-Lv.3-%EB%93%B1%EA%B5%A3%EA%B8%B8-python</link>
            <guid>https://velog.io/@j-ij-i/Programmers-Lv.3-%EB%93%B1%EA%B5%A3%EA%B8%B8-python</guid>
            <pubDate>Tue, 13 Dec 2022 14:35:34 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42898">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<p><img src="https://velog.velcdn.com/images/j-ij-i/post/d6181486-27c6-48a7-89b7-44a468dbc0dc/image.png" alt=""></p>
<ul>
<li>처음에 puddles의 좌표가 반대로 되어있는지 몰랐는데 이것 때문에 틀렸었다..! 🤣</li>
<li><code>arr[i][j] = arr[i][j-1] + arr[i-1][j]</code> 이 점화식을 사용해서 arr를 갱신해주었다.</li>
<li>해당 그림처럼 왼쪽과 위쪽의 값들을 더해 <code>arr[i][j]</code>를 만들어 주었다.</li>
</ul>
<h3 id="다른풀이-탐색">다른풀이 탐색</h3>
<ul>
<li><code>if [i, j] in puddles</code>를 사용해서 굳이 하나하나 체크하지 않아도 쉽게 풀 수 있는 방법이 있었다!</li>
</ul>
<h3 id="나의-해결-코드">나의 해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">from collections import deque 
def solution(m, n, puddles):
    answer = 0
    arr = [[0 for _ in range(m+1)] for _ in range(n+1)]

    for p in puddles:
        x,y = p
        arr[y][x] = -1

    arr[1][1] = 1

    for i in range(1,n+1):
        for j in range(1,m+1):
            if arr[i][j] == -1:
                continue
            if arr[i-1][j] == -1 and arr[i][j-1] == -1:
                continue
            elif arr[i][j-1] == -1:
                arr[i][j] += arr[i-1][j]
            elif arr[i-1][j] == -1:
                arr[i][j] += arr[i][j-1]
            else:
                arr[i][j] += (arr[i][j-1] + arr[i-1][j])


    return arr[n][m] % 1000000007

print(solution(7, 4, [[2, 1], [2, 2], [2, 3], [4, 2], [4, 3], [4, 4], [6, 2], [6, 3]]))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Programmers] Lv.2 할인 행사  (python, js)]]></title>
            <link>https://velog.io/@j-ij-i/Programmers-Lv.2-%ED%95%A0%EC%9D%B8-%ED%96%89%EC%82%AC-python-js</link>
            <guid>https://velog.io/@j-ij-i/Programmers-Lv.2-%ED%95%A0%EC%9D%B8-%ED%96%89%EC%82%AC-python-js</guid>
            <pubDate>Tue, 13 Dec 2022 13:46:25 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/131127">link 📃 </a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ul>
<li>처음에 총 몇일이 가입 가능한 날짜인지 구하는 것이 아니라 가장 빨리 가입을 했을 떄 언제인지를 구해서 답이 빨리 도출되지 못했다..🥲</li>
<li>want 배열과 number 배열을 lists 라는 딕셔너리 (js에서는 객체)로 만들었다. 각각 want 배열은 key값, 그에 대응하는 number 배열은 value로 넣었다.</li>
<li>discount 배열을 처음부터 돌면서 10의 범위만큼 lists 딕셔너리 값을 모두 제거할 수 있으면 answer값을 1 증가시켜 최종적으로 answer 값을 return 해주게 풀었다.</li>
</ul>
<h3 id="다른풀이-탐색">다른풀이 탐색</h3>
<ul>
<li>discount가 어짜피 무조건 10의 범위이기 때문에 [i:i+10]으로 간단하게 해주었다.</li>
<li>python의 Counter을 써서 해당 배열이 몇개의 key, value를 갖는지 바로 파악해주는 방법이 있었다.</li>
</ul>
<h3 id="나의-해결-코드">나의 해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">def solution(want, number, discount):
    answer = 0
    target = 0
    total_cnt = sum(number)

    lists = dict()

    for i in range(len(number)):
        lists[want[i]] = number[i]
    copy_lists = lists.copy()

    while target &lt; len(discount):
        for i in range(target, target+total_cnt):
            if i &gt;= len(discount):
                target = len(discount)
                break
            elif discount[i] not in want:
                target = i + 1
                break
            elif discount[i] in want:
                if copy_lists[discount[i]] &lt;= 0:
                    copy_lists = lists.copy()
                    target += 1
                    break
                else:
                    copy_lists[discount[i]] -= 1
                    print(copy_lists[discount[i]])
        else:
            answer += 1
            target += 1
        copy_lists = lists.copy()

    return answer</code></pre>
<h4 id="javascript">javascript</h4>
<pre><code class="language-jsx">function solution(want, number, discount) {
    let answer = 0;
    let target = 0;
    let total_cnt = number.reduce((a,b) =&gt; a+b, 0);

    const lists = {};

    for(let i = 0 ; i &lt; number.length ; i++){
        lists[want[i]] = number[i];
    }

    let copy_lists = Object.assign({}, lists);

    while(target &lt; discount.length){
        Flag = true
        for(let i = target ; i &lt; target + total_cnt ; i++){
            if(i &gt;= discount.length){
                target = discount.length;
                Flag = false
                break
            }else if(!(Object.keys(copy_lists).includes(discount[i]))){
                target = i + 1
                Flag = false
                break
            }else if(Object.keys(copy_lists).includes(discount[i])){
                if(copy_lists[discount[i]] &lt;= 0){
                    copy_lists = Object.assign({},lists)
                    target += 1
                    Flag = false
                    break
                }else{
                    copy_lists[discount[i]] -= 1
                }
            }
        }
        if(Flag){
            answer += 1
            target += 1
        }
        copy_lists = Object.assign({},lists)
    }

    return answer;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[const, let와 블록 레벨 스코프]]></title>
            <link>https://velog.io/@j-ij-i/const-let%EC%99%80-%EB%B8%94%EB%A1%9D-%EB%A0%88%EB%B2%A8-%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@j-ij-i/const-let%EC%99%80-%EB%B8%94%EB%A1%9D-%EB%A0%88%EB%B2%A8-%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Mon, 12 Dec 2022 07:51:26 GMT</pubDate>
            <description><![CDATA[<p>기술 면접 중에 <strong>&#39;const와 let은 왜 나누게 되었을까요?, const와 let을 블록 스코프 관련해서 말해주세요.&#39;</strong> 라는 면접질문들을 받았고 재할당 부분밖에 대답하지 못하였습니다.🥲 공부를 하면서 기록하고자 const, let 내용 중에서도 블록 레벨 스코프에 대해 작성하겠습니다.</p>
<h3 id="var의-함수-레벨-스코프">var의 함수 레벨 스코프</h3>
<p>ES5에서는 <code>var</code> 키워드를 사용해서 변수를 선언해야 했습니다. 하지만 <code>var</code> 키워드는 많은 단점들이 있었는데 특히나 <strong>&#39;함수 레벨 스코프&#39;</strong> 라는 특징은 전역변수를 남발하게 되는 가능성을 높여 문제가 있었습니다.</p>
<blockquote>
<p><strong>함수 레벨 스코프(Function-level scope)</strong>
함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.</p>
</blockquote>
<pre><code class="language-javascript">var foo = 123;
console.log(foo) // 123
{
    var foo = 456;
}
console.log(foo) // 456</code></pre>
<p>위와 같이 코드 블록에서 var로 선언된 변수가 이미 전역 변수로 선언되었으면 중복선언이 허용되어 전역변수의 foo가 456으로 재할당됩니다. </p>
<h3 id="const-let의-블록-레벨-스코프">const, let의 블록 레벨 스코프</h3>
<blockquote>
<p><strong>블록 레벨 스코프(Block-level scope)</strong>
모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.</p>
</blockquote>
<pre><code class="language-javascript">let foo = 123; // 전역 변수

{
  let foo = 456; // 지역 변수
  let bar = 456; // 지역 변수
}

console.log(foo); // 123
console.log(bar); // ReferenceError: bar is not defined</code></pre>
<p>let 키워드로 선언된 foo는 블록 레벨 스코프를 따라 지역변수로 선언됩니다. 블록 간 별개의 변수로 생성되어 재할당을 막을 수 있습니다.</p>
<h3 id="const를-사용해야하는-이유">const를 사용해야하는 이유</h3>
<ul>
<li>코드 이해 관련된 측면에서는 추론하기 쉬운 코드를 만들 수 있기 때문입니다.</li>
<li>변수를 사용하면 상황에 따라 바뀌는 값을 추론해야 하지만, 재할당 할 수 없는 상수를 사용하면 추론하지 못하는 케이스가 줄어들 수 있습니다</li>
</ul>
<h3 id="const-타입-객체">const 타입 객체</h3>
<ul>
<li>const 타입의 객체는 변수와 달리 객체 내용이 변경되더라도 객체 타입 변수에 할당된 주소값이 변경되지 않습니다.</li>
<li>재할당은 불가능 하지만 객체 프로퍼티는 보호되지 않아 값을 추가, 삭제, 변경이 가능합니다.</li>
</ul>
<pre><code class="language-javascript">const user = { name: &#39;JJ&#39; };

// user = {}; // TypeError, 재할당 금지

// 객체의 내용은 변경 가능
user.name = &#39;AA&#39;;

console.log(user); // { name: &#39;AA&#39; }
</code></pre>
<h3 id="참고-링크">참고 링크</h3>
<p><a href="https://poiemaweb.com/es6-block-scope">https://poiemaweb.com/es6-block-scope</a>
<a href="https://medium.com/dailyjs/use-const-and-make-your-javascript-code-better-aac4f3786ca1">https://medium.com/dailyjs/use-const-and-make-your-javascript-code-better-aac4f3786ca1</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Programmers] Lv.2 124 나라의 숫자 (python, js)]]></title>
            <link>https://velog.io/@j-ij-i/Programmers-Lv.2-124-%EB%82%98%EB%9D%BC%EC%9D%98-%EC%88%AB%EC%9E%90-python-js</link>
            <guid>https://velog.io/@j-ij-i/Programmers-Lv.2-124-%EB%82%98%EB%9D%BC%EC%9D%98-%EC%88%AB%EC%9E%90-python-js</guid>
            <pubDate>Mon, 12 Dec 2022 02:01:01 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/j-ij-i/post/3057f053-2c5c-491e-a626-32f90e2290a6/image.png" alt=""></p>
<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12899?language=python3#">link 📃 
</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ul>
<li>3진법을 구하는 것 처럼 주어지는 n을 3으로 나누면서 나머지가 1이면 1, 2면 2, 0이면 4가 되게 answer에다가 추가해주고, 나머지가 0일때는 몫이 -1만큼 더해주었다.</li>
<li>나머지가 0일때는 나누어 떨어지기 때문에 몫이 -1만큼 적게 체크한다. 
ex) n=3일때, 몫이 1, 나머지가 0이지만 answer는 4 한자리수로 나와야 하기 때문에 몫에는 -1을 하여 n을 0으로 만들어 준다.</li>
<li>n을 3으로 나눈 몫을 계속 n으로 갱신해주면서 n이 0이 될때까지 while문을 사용해서 반복해줬다.</li>
</ul>
<h3 id="해결-코드">해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">def solution(n):    
    answer = &#39;&#39;
    n = int(n)
    while n &gt; 0:
        a = n // 3
        b = n % 3
        if b == 0:
            b = 4
            a -= 1
        n = a
        answer = str(b)+answer

    return answer
</code></pre>
<h4 id="javascript">javascript</h4>
<pre><code class="language-jsx">function solution(n) {
    var answer = &#39;&#39;;
    while(n &gt; 0){
        a = parseInt(n / 3)
        b = n % 3
        if(b == 0){
            b = 4
            a -= 1
        }
        n = a
        answer = (b) + answer
    }
    return answer;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Programmers] Lv.1 폰켓몬 (python, js)]]></title>
            <link>https://velog.io/@j-ij-i/Programmers-%ED%8F%B0%EC%BC%93%EB%AA%AC-python-js</link>
            <guid>https://velog.io/@j-ij-i/Programmers-%ED%8F%B0%EC%BC%93%EB%AA%AC-python-js</guid>
            <pubDate>Mon, 12 Dec 2022 01:45:53 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-링크">문제 링크</h3>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/1845?language=python3">Link 📃</a></p>
<h3 id="문제-풀이">문제 풀이</h3>
<ul>
<li>주어지는 폰켓몬 중 가질 수 있는 최대 갯수는 N/2 이기 때문에 nums 배열 안에 있는 숫자(폰켓몬)의 갯수가 N/2보다 크면 답은 N/2, 적으면 nums 배열의 숫자 종류의 갯수로 답이 나오게 풀었다.</li>
<li>python은 defaultdict를 이용하여 기본값은 0이지만 nums에서 만나면 차례대로 +1씩 증가하게 만들어 중복을 제거했다.</li>
<li>js에서는 객체를 이용해서 객체값에 들어가면 +1이 되도록 하여 중복을 제거했다.</li>
</ul>
<h3 id="다른-풀이-탐색">다른 풀이 탐색</h3>
<ul>
<li>set으로 중복을 줄인 후 length를 계산.</li>
</ul>
<h3 id="해결-코드">해결 코드</h3>
<h4 id="python">Python</h4>
<pre><code class="language-python">from collections import defaultdict 
def solution(nums):
    dic = defaultdict(int)
    max_num = len(nums)//2
    for i in nums:
        dic[i] += 1
    if max_num &lt; len(dic):
        return max_num
    else:
        return len(dic)</code></pre>
<h4 id="javascript">javascript</h4>
<pre><code class="language-javascript">function solution(nums) {
    var answer = 0;
    let arr = {}
    const max_num = nums.length / 2

    for(let i = 0 ; i &lt; nums.length ; i++){
        if(!arr[nums[i]]){
            arr[nums[i]] = 1
        }else{
            arr[nums[i]] += 1
        }
    }

    if(Object.keys(arr).length &gt; max_num){
        return max_num
    }else{
        return Object.keys(arr).length
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Programmers] Lv.3 섬 연결하기 (python, js)]]></title>
            <link>https://velog.io/@j-ij-i/PGS-%EC%84%AC-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-py-js</link>
            <guid>https://velog.io/@j-ij-i/PGS-%EC%84%AC-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-py-js</guid>
            <pubDate>Sat, 10 Dec 2022 06:47:21 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42861">문제 링크</a></p>
<p><strong>문제 설명</strong>
n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.</p>
<p>다리를 여러 번 건너더라도, 도달할 수만 있으면 통행 가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>섬의 개수 n은 1 이상 100 이하입니다.</li>
<li>costs의 길이는 ((n-1) * n) / 2이하입니다.</li>
<li>임의의 i에 대해, costs[i][0] 와 costs[i] [1]에는 다리가 연결되는 두 섬의 번호가 들어있고, costs[i] [2]에는 이 두 섬을 연결하는 다리를 건설할 때 드는 비용입니다.</li>
<li>같은 연결은 두 번 주어지지 않습니다. 또한 순서가 바뀌더라도 같은 연결로 봅니다. 즉 0과 1 사이를 연결하는 비용이 주어졌을 때, 1과 0의 비용이 주어지지 않습니다.</li>
<li>모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.</li>
<li>연결할 수 없는 섬은 주어지지 않습니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/j-ij-i/post/6d788635-1d36-493c-b9b4-415dd9582ec7/image.png" alt=""></p>
<hr>
<p><strong>풀이과정</strong></p>
<ul>
<li>그래프 탐색을 하여 최소신장트리가 되도록 만드는 크루스칼 알고리즘을 이용하여 풀었다.</li>
<li>기본적인 union-find 방법을 처음에 생각해서 풀었지만, 더 좋은 방법이 있을까 찾아본 결과 set을 사용해서 vertex를 추가하면서 간선의 가중치를 늘려가는 방식의 방법을 찾아 이 방식으로 풀게 되었다.</li>
<li>하지만 link된 vertex가 증가할때마다 costs의 처음부터 탐색하는 점이 있어 costs가 늘어나게 되면 좋지 않다고 느꼈다.</li>
</ul>
<p><strong>파이썬 풀이</strong></p>
<pre><code>def solution(n, costs):
    answer = 0

    costs.sort(key = lambda x : x[2])
    link = set([costs[0][0]])

    while len(link) &lt; n:
        for v in costs:
            if v[0] in link and v[1] in link:
                continue
            if v[0] in link or v[1] in link:
                link.update([v[0],v[1]])
                answer += v[2]
                break

    return answer</code></pre><p><strong>자바스크립트 풀이</strong></p>
<pre><code>function solution(n, costs) {
    var answer = 0;
    costs.sort((a,b) =&gt; (a[2]-b[2]))
    let link = new Set([costs[0][0]]);

    while(link.size &lt; n){
        for(let v = 0 ; v &lt; costs.length; v++){        
            if(link.has(costs[v][0]) &amp;&amp; link.has(costs[v][1])){
                continue;
            }
            if(link.has(costs[v][0]) || link.has(costs[v][1])){
                answer += costs[v][2]
                link.add(costs[v][0])
                link.add(costs[v][1])    
                break
            }
        }
    }
    return answer;
}</code></pre><p><strong>참고</strong>
<a href="https://velog.io/@henrynoowah/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%84%AC-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-PYTHON">https://velog.io/@henrynoowah/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%84%AC-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-PYTHON</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[제어 컴포넌트와 비제어 컴포넌트(React)]]></title>
            <link>https://velog.io/@j-ij-i/%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%99%80-%EB%B9%84%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8React</link>
            <guid>https://velog.io/@j-ij-i/%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%99%80-%EB%B9%84%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8React</guid>
            <pubDate>Tue, 30 Aug 2022 13:51:45 GMT</pubDate>
            <description><![CDATA[<h3 id="tldr">TL;DR</h3>
<ul>
<li><code>State</code>가 <strong>제어 컴포넌트</strong>고 <code>Ref</code>가 <strong>비제어 컴포넌트</strong>로 이분적으로 구분 되는 개념은 아닙니다.</li>
<li><strong>제어 컴포넌트</strong>는 state의 변경마다 Re-Rendering이 되며, <strong>비제어 컴포넌트</strong>는 Re-Rendering이 되지 않습니다.</li>
</ul>
<hr>
<p>온라인 모각코 스터디 하던 중, 취업한 한 스터디 팀원이 갑자기 들어와서는 <strong>&#39;제어 컴포넌트와 비제어 컴포넌트 아시나요?&#39;</strong> 라는 질문을 남겼습니다.
검색해보니 <code>useState</code>와 <code>useRef</code>의 개념에서 나온 단어구나라고 생각하려는 순간, 팀원분이 그런 개념이 아니라고 바로 정정 해주셨습니다. 공식 React 페이지에서도 <code>useState</code>와 <code>useRef</code>의 예시로 다루는데 다른 개념으로 설명해주셔서 한번 기록으로 남기고 싶은 생각이 들었습니다.</p>
<h2 id="react-공식-홈페이지">React 공식 홈페이지</h2>
<h3 id="제어-컴포넌트">제어 컴포넌트</h3>
<blockquote>
<p>React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트됩니다. (...) 이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 “제어 컴포넌트 (controlled component)“라고 합니다.
<a href="https://ko.reactjs.org/docs/forms.html#controlled-components">https://ko.reactjs.org/docs/forms.html#controlled-components</a></p>
</blockquote>
<ul>
<li>React 공식 홈페이지 내에서는 <code>setState</code>를 통해 값을 제어하는 방식을 제어 컴포넌트라고 명칭하고 있습니다.</li>
<li>input의 값은 항상 React state에 의해 결정되며, 모든 키 입력에서 handleChange가 동작하기 때문에 사용자가 입력할 때 보여지는 값이 업데이트됩니다.</li>
</ul>
<h3 id="비제어-컴포넌트">비제어 컴포넌트</h3>
<blockquote>
<p>모든 state 업데이트에 대한 이벤트 핸들러를 작성하는 대신 비제어 컴포넌트를 만들려면 ref를 사용하여 DOM에서 폼 값을 가져올 수 있습니다. (...) 
비제어 컴포넌트는 DOM에 신뢰 가능한 출처를 유지하므로 비제어 컴포넌트를 사용할 때 React와 non-React 코드를 통합하는 것이 쉬울 수 있습니다. 
<a href="https://ko.reactjs.org/docs/uncontrolled-components.html">https://ko.reactjs.org/docs/uncontrolled-components.html</a></p>
</blockquote>
<ul>
<li>데이터를 DOM 자체에서 값을 가져와서 사용합니다.</li>
<li><code>ref</code>를 이용하여 DOM에서 폼값을 가져옵니다.</li>
</ul>
<h2 id="추가적인-내용">추가적인 내용</h2>
<ul>
<li>공식적인 내용은 아니지만 한 시니어 개발자 분의 설명을 전해 들은 내용을 바탕으로 정리하였습니다.</li>
<li>제어 컴포넌트와 비제어 컴포넌트 개념을 처음 접하는 분의 경우, 다른 분의 개념을 보는 것을 추천합니다.</li>
<li>틀린 부분이 있다면 지적 감사드립니다.</li>
</ul>
<h3 id="제어-컴포넌트-1">제어 컴포넌트</h3>
<pre><code>const [state, setState] = useState&lt;String&gt;();
return(
    &lt;div&gt;
        &lt;input value={state} onChange={(e) =&gt; setState(e.target.value)}/&gt;
    &lt;/div&gt;
)</code></pre><ul>
<li>제어 컴포넌트는 setState만의 적용을 뜻하기 보단, input와 setState에서 양방향으로 서로 변경이 가능한 것과 같은 State와 컴포넌트간의 양방향으로 값이 변경되는 컴포넌트를 뜻합니다.</li>
</ul>
<h3 id="비제어-컴포넌트-1">비제어 컴포넌트</h3>
<pre><code>const [state, setState] = useState&lt;string&gt;();

return(
    &lt;UncontrolledComponent onChange={(e)=&gt;setState(e)}/&gt;
)

const UncontrolledComponent = ({defaultValue, onChange}) =&gt; {
    const[innerState,setInnerState] = useState(defaultValue);
    return &lt;input value={innerState} onChange={(e)=&gt;setInnerState(e.target.value)}/&gt;
}</code></pre><ul>
<li>꼭 <code>ref</code>뿐 아니라 이런식으로 외부 state가 내부 state에 영향을 미치지 못하게 하는 것도 비제어 컴포넌트라는 설명을 들었습니다.</li>
<li>이를 통해 항상 값이 리렌더링 되지 않는 비제어 컴포넌트가 되게 됩니다.</li>
</ul>
<h3 id="왜-사용하는가-언제-사용해야-하는지">왜 사용하는가? 언제 사용해야 하는지?</h3>
<ul>
<li><strong>제어 컴포넌트</strong>와 <strong>비제어 컴포넌트</strong>의 큰 차이점은 state의 동기화입니다.</li>
<li><strong>제어 컴포넌트</strong>는 값이 변경될때마다 state를 같이 동기화해줍니다. 값이 조금이라도 바뀌게 되어도 바로 state가 바뀌기 때문에 빠르게 값을 반영하는 장점이 있지만, 불필요한 리렌더링이 된다는 점이 단점입니다.</li>
<li><strong>비제어 컴포넌트</strong>는 DOM이 값을 저장하며 값을 항상 최신 값으로 보장하지 못하지만, 리렌더링이 되지 않아 많은 데이터를 처리하는 폼에 사용하기 좋은 점이 있습니다.</li>
</ul>
<h4 id="참고링크">참고링크</h4>
<p><a href="https://ko.reactjs.org/docs/forms.html#controlled-components">https://ko.reactjs.org/docs/forms.html#controlled-components</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[npm WARN invalid config registry=""]]></title>
            <link>https://velog.io/@j-ij-i/npm-WARN-invalid-config-registry</link>
            <guid>https://velog.io/@j-ij-i/npm-WARN-invalid-config-registry</guid>
            <pubDate>Mon, 12 Apr 2021 08:41:21 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/j-ij-i/post/7ec86831-c9d2-4922-87d0-d0c9065c360b/image.png" alt=""></p>
<pre><code>npm WARN invalid config registry=&quot;&quot;
npm WARN invalid config Must be a full url with &#39;http://&#39;</code></pre><p>react 공부중에 에러를 고치다가 config 설정이 잘못 되었다.
아래 코드로 해결하였다.</p>
<pre><code>npm config rm proxy
npm config rm https-proxy</code></pre>]]></description>
        </item>
    </channel>
</rss>