<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>turtle_hw.log</title>
        <link>https://velog.io/</link>
        <description>나의 행복 만들기</description>
        <lastBuildDate>Thu, 25 Apr 2024 00:42:15 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>turtle_hw.log</title>
            <url>https://velog.velcdn.com/images/turtle_hw/profile/0122c857-09e3-43b2-9bf6-6ac4e0c96776/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. turtle_hw.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/turtle_hw" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[HTTP-프로토콜]]></title>
            <link>https://velog.io/@turtle_hw/HTTP-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</link>
            <guid>https://velog.io/@turtle_hw/HTTP-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</guid>
            <pubDate>Thu, 25 Apr 2024 00:42:15 GMT</pubDate>
            <description><![CDATA[<h3 id="http-프로토콜"><a href="https://youtu.be/TwsQX1AnWJU?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">HTTP 프로토콜</a></h3>
<h4 id="1-웹을-만들기-위해-사용되는-기술들">1. 웹을 만들기 위해 사용되는 기술들</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/ac65f6d9-8771-4098-8f94-2fc279750783/image.png" alt=""></p>
<p>&lt; 요 세가지는 한 묶음 =&gt; 웹 표준&gt;</p>
<ul>
<li><p><code>HTML</code> : 웹 페이지를 채울 내용</p>
</li>
<li><p><code>Javascript</code> : 웹 페이지에 들어갈 기능</p>
</li>
<li><p><code>CSS</code> : 웹 페이지를 예쁘게 꾸밀 디자인</p>
<blockquote>
<p>공통점 = 클라이언트 컴퓨터에서 동작하는 코드들이다
저장은 서버쪽에 되어 있고, 그걸 받아와서 내 컴퓨터에서 실행시키는 것!
이거를 받아오는 프로토콜이 HTTP이다.(웹 표준 데이터를 받아오는 애다)</p>
</blockquote>
</li>
<li><p>ASP/JSP/PHP는 서버쪽에서 동작하는 애들이다</p>
</li>
</ul>
<h4 id="2-http-프로토콜의-특징">2. HTTP 프로토콜의 특징</h4>
<ul>
<li>HyperText Transfer Protocol (하이퍼 텍스트 전송 프로토콜)</li>
<li>www에서 쓰이는 핵심 프로토콜로 문서의 전송을 위해 쓰이며, 오늘날 거의 모든 웹 애플리케이션에서 사용되고 있다. -&gt; 음성, 화상 등 여러 종류의 데이터를 MIME로 정의하여 전송 가능</li>
<li>HTTP 특징<ul>
<li>Request / Response(요청/응답) 동작에 기반하여 서비스 제공</li>
</ul>
</li>
</ul>
<h4 id="3-http-프로토콜의-통신-과정">3. HTTP 프로토콜의 통신 과정</h4>
<ul>
<li><p>v 1.0
<img src="https://velog.velcdn.com/images/turtle_hw/post/6308947c-e295-49cd-a297-97977031c018/image.png" alt=""></p>
</li>
<li><p>3Way Handshake 요청 후 HTTP 요청, 응답 하면 바로 연결 종료</p>
</li>
<li><p>v 1.1
<img src="https://velog.velcdn.com/images/turtle_hw/post/a96c5c9d-660c-455f-bb0f-dd25758a7f69/image.png" alt=""></p>
</li>
<li><p>요청 받아갈거 다 받아가면 연결 종료</p>
</li>
</ul>
<h3 id="http-요청-프로토콜"><a href="https://youtu.be/rxaBwwI_JnI?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">HTTP 요청 프로토콜</a></h3>
<ul>
<li>HTTP Method 설명 중 GET, POST만 사용해야 한다고 하지만 개발자 입장에서 RESTful API 개발시 PUT, DELETE도 사용하는게 원칙임</li>
</ul>
<h4 id="1-http-요청">1. HTTP 요청</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/30798b14-ff44-4b90-821b-94eb285c2ca4/image.png" alt=""></p>
<h4 id="2-프로토콜의-구조">2. 프로토콜의 구조</h4>
<p> <img src="https://velog.velcdn.com/images/turtle_hw/post/0cf9e7e5-f5de-4248-8841-f907ef81c3c3/image.png" alt=""></p>
<ul>
<li>제일 첫줄인 Request 라인이 가장 중요함</li>
<li>요청타입(중요) + 공백 + URI(중요) + 공백 + HTTP 버전 </li>
</ul>
<h4 id="3-요청타입--get-post-중요">3. 요청타입 ( GET, POST 중요)</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/eec9d5b3-3799-4b10-8c61-0ac92a4601d7/image.png" alt=""></p>
<ul>
<li><p>GET 방식은 중요하지 않은 정보를 URI에 같이 보내는 방식임</p>
</li>
<li><p>POST 방식은 중요한 정보 ID, PW와 같은 정보를 body에 넣어보내는 방식임</p>
</li>
</ul>
<h3 id="url-uri란"><a href="https://youtu.be/2ikhZ_fNP5Y?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">URL, URI란?</a></h3>
<ul>
<li>URI는 Uniform Resource Identifier 의 약자</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/b60ce6a3-61d9-48c3-9129-23a1ca317bbe/image.png" alt=""></p>
<h4 id="uri-구조">URI 구조</h4>
<ul>
<li>scheme ://host[:port][/path][?query] (scheme 자리엔 7계층 프로토콜 형식지정하면 된다)</li>
</ul>
<h3 id="http-요청-프로토콜-작성-실습"><a href="https://youtu.be/XbGJYsxed2w?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">HTTP 요청 프로토콜 작성 실습</a></h3>
<ul>
<li>GET / HTTP/1.1 을 웹사이트에 요청보내면 요청은 다 감(근데 실습 어떻게 해야하는지 앞에 생략이 너무 되있어서 안됨니다)</li>
</ul>
<h3 id="uri-이해를-위한-실습"><a href="https://youtu.be/HBojczyd1Ac?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">URI 이해를 위한 실습</a></h3>
<ul>
<li>API 만들기</li>
</ul>
<h3 id="http-응답-프로토콜"><a href="https://youtu.be/kuucNF4Zvbs?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">HTTP 응답 프로토콜</a></h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/4d491cb0-b5bf-4883-8a9e-cca825f977a7/image.png" alt=""></p>
<ul>
<li>요청과 똑같음( 요청보다 간단함 )</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/3568e6cd-9c26-49db-8cf7-63d27cc3a633/image.png" alt=""></p>
<h4 id="응답-프로토콜-구조">응답 프로토콜 구조</h4>
<ul>
<li><p>HTTP 버전 + 공백 + 상태코드 + 공백 + 상태문구 </p>
</li>
<li><p>( 상태코드와 상태문구는 세트임 코드만 알아두자)
<img src="https://velog.velcdn.com/images/turtle_hw/post/00a20113-f267-470a-bb33-85e681f5813b/image.png" alt=""></p>
</li>
<li><p>100, 300번대는 몰라도 된다</p>
</li>
<li><p>200번대는 정상적인 통신을 완료했을때임 (정상)
<img src="https://velog.velcdn.com/images/turtle_hw/post/70e0165e-23a7-4b36-a0bb-8309ea69c844/image.png" alt=""></p>
</li>
<li><p>400번대는 클라이언트가 잘못한거임 
<img src="https://velog.velcdn.com/images/turtle_hw/post/5e9034c9-cf20-4697-9a4e-760e301b7760/image.png" alt=""></p>
</li>
<li><p>500번대는 서버가 잘못한거임
<img src="https://velog.velcdn.com/images/turtle_hw/post/84738f31-17e0-4064-86af-3176dd39d508/image.png" alt=""></p>
</li>
<li><p>개발 코드 잘못쳤을때 500번대 자주 나옴</p>
</li>
</ul>
<h3 id="http-헤더-포맷"><a href="https://youtu.be/mQTGmxendk8?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">HTTP 헤더 포맷</a></h3>
<h4 id="헤더-종류">헤더 종류</h4>
<ul>
<li>둘다 사용할수 있는 일반 헤더</li>
<li>각자 사용할 수 있는 요청 헤더와 응답 헤더 </li>
<li>특별한 경우에 사용하는 항목 헤더</li>
</ul>
<h4 id="일반-헤더">일반 헤더</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/2d491799-a561-420b-8f3f-511c492e1441/image.png" alt=""></p>
<h4 id="요청-헤더">요청 헤더</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/aadf9c50-b65c-46ac-a704-d561ab6c68cc/image.png" alt=""></p>
<h4 id="응답-헤더">응답 헤더</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/7a13d675-1eef-4a89-85e3-a4c8adbe0bd4/image.png" alt=""></p>
<h3 id="http-프로토콜-분석-실습"><a href="https://youtu.be/dhMrKTwNI8U?list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi">HTTP 프로토콜 분석 실습</a></h3>
<ul>
<li>burpsuite 활용한 실습 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로세스]]></title>
            <link>https://velog.io/@turtle_hw/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</link>
            <guid>https://velog.io/@turtle_hw/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</guid>
            <pubDate>Thu, 25 Apr 2024 00:41:57 GMT</pubDate>
            <description><![CDATA[<h2 id="프로세스-2"><a href="https://core.ewha.ac.kr/publicview/C0101020140321141759959993?vmode=f">프로세스 #2</a></h2>
<h3 id="질문-답변--동기식-입출력과-비동기식-입출력">질문 답변 &gt; 동기식 입출력과 비동기식 입출력</h3>
<ul>
<li><p>동기식 입출력 ( Synchronous I/O)</p>
<ul>
<li>I/O 요청 후 <code>입출력 작업이 완료된 후</code>에야 제어가 사용자 프로그램에 넘어감</li>
<li>구현방법 1
: I/O가 끝날때까지 CPPU를 낭비시킴
: 매시점 하나의 I/O만 일어날 수 있음</li>
<li>구현방법 2
: I/O가 완료될 떄까지 해당 프로그램에게서 CPU를 빼앗음
: I/O 처리를 기다리는 줄에 그 프로그램을 줄 세움
: 다른 프로그램에게 CPU를 줌</li>
</ul>
</li>
<li><p>비동기식 입출력(Asynchronous I/O)</p>
<ul>
<li>I/O가 시작된 후 <code>입출력 작업이 끝나기를 기다리지 않고</code> 제어가 사용자 프로그램에 즉시 넘어감</li>
</ul>
</li>
</ul>
<h3 id="thread">Thread</h3>
<ul>
<li>A thread(or lightweight process) is a basic unit of CPU utilization</li>
</ul>
<blockquote>
<p>프로세스 하나에 CPU 수행 단위만 여러개 두고 있는 것을 thread라고 한다.</p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">그림1</th>
<th align="center">그림2</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="https://velog.velcdn.com/images/turtle_hw/post/a321d54d-a20f-4c59-a74b-4107f5f73403/image.png" alt=""></td>
<td align="center"><img src="https://velog.velcdn.com/images/turtle_hw/post/a871c084-cee8-48c1-8050-a43245d7d390/image.png" alt=""></td>
</tr>
</tbody></table>
<ul>
<li>Thread의 구성<ul>
<li>program counter</li>
<li>register set</li>
<li>stack space<ul>
<li>Thread 가 동료 thread와 공유하는 부분(=task)</li>
</ul>
</li>
<li>code section</li>
<li>data section</li>
<li>OS resources</li>
</ul>
</li>
</ul>
<h4 id="thread-사용의-장점">Thread 사용의 장점</h4>
<ul>
<li>다중 스레드로 구성된 태스크 구조에서는 하나의 서버 스레드가 blocked(waiting) 상태인 동안에도 동일한 태스크 내의 다른 스레드가 실행되어 빠른 처리를 할 수 있다</li>
<li>스레드를 사용하면 병렬성을 높일 수 있다.(CPU가 여러 개 달린 컴퓨터에서만 얻을 수 있는 장점)(CPU가 하나밖에 없으면 안됨)</li>
</ul>
<h2 id="프로세스-3">프로세스 #3</h2>
<h3 id="single-and-multithreaded-processes">Single and Multithreaded Processes</h3>
<table>
<thead>
<tr>
<th align="center">Single and Multithreaded Processes</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><img src="https://velog.velcdn.com/images/turtle_hw/post/adba716e-225c-4bcd-a317-04b570cb1dfe/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="benefits-of-threads">Benefits of Threads</h3>
<ul>
<li><p>Responsiveness(응답성 향상)
: 답답함 해소 / 원래는 프로세스가 블럭되는데 요청한 그 스레드만 막히고 다른 스레드가 텍스트라도 보여줄 수 있어서 응답성에 있어서의 장점이 생긴다.이미지 파일을 불러오는 동안에 다른 애가 먼저 텍스트 화면에 보여줄 수 있게 됨(비동기식 입출력)</p>
</li>
<li><p>Resource Sharing(자원 공유)
: 똑같은 일을 하는 프로그램이 여러 개 있을 때, 프로그램을 하나만 만들어두고 CPU 수행단위만 여러 개 두게 되면 스레드들이 공유를 통해 자원을 효과적으로 사용할 수 있음</p>
</li>
<li><p>Economy(경제성)
: 문맥 교환(프로세스를 여러개 만드는 것보다, 스레드하나를 생성하고 CPU를 스위치 하는게 오버헤드가 적게 든다) </p>
</li>
<li><p>Utilization of MP Architectures
: 스레드가 여러 개 있을때 서로 다른 CPU에서 병렬적으로 일을 수행할 수 있음 -&gt; 멀티 프로세서 환경에서 효율적으로 실행 가능  </p>
</li>
</ul>
<h3 id="implementation-of-threads">Implementation of Threads</h3>
<h4 id="1-kernel-threads">1. Kernel Threads</h4>
<ul>
<li>threads가 여러 개 있다는 사실을 운영체제 커널이 알고 있음</li>
</ul>
<h4 id="2-user-threads">2. User Threads</h4>
<ul>
<li>라이브러리를 이용해서 지원됨</li>
<li>커널은 모르고 있어서 일반적인 프로세스로 보임</li>
<li>사용자 수준에서 threads 구현하게 됨</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[네트워크_IPv4, ICMP 프로토콜]]></title>
            <link>https://velog.io/@turtle_hw/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%ACIPv4</link>
            <guid>https://velog.io/@turtle_hw/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%ACIPv4</guid>
            <pubDate>Fri, 12 Apr 2024 12:51:59 GMT</pubDate>
            <description><![CDATA[<h2 id="1-ipv4-프로토콜">1. IPv4 프로토콜</h2>
<p>: 네트워크 상에서 데이터를 교환하기 위한 프로토콜로 데이터가 정확하게 전달될 것을 보장하지 않는다.
: 중복된 패킷을 전달하거나 패킷의 순서를 잘못 전달할 가능성도 있다. (악의적으로 이용되면 DoS 공격이 된다)
: 데이터의 정확하고 순차적인 전달은 그보다 상위 프로토콜인 TCP에서 보장한다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/bd2bf5c0-7619-4cf3-9633-4b6525af648a/image.png" alt=""></p>
<ul>
<li>IP option은 붙을 수도 있고 안붙을수도 있음(최대 10개 붙을 수 있음)<pre><code>- 옵션 하나씩 붙을때마다 4바이트씩 추가됨 </code></pre></li>
<li>20바이트라고 생각하면 됨(총 60바이트까지 늘어날 수 있음)</li>
<li>보통은 옵션없이 사용해서 20바이트라고 생각하면 된다.</li>
</ul>
<hr>
<ul>
<li>Version = 버전 4가 온다고 생각하면 됨 16진수 하나가 4비트 (6이 오는 경우 없음/ 버전6은 이 모양자체가 아님) </li>
<li>IHL = 헤더의 길이</li>
<li>identification과 flags(3비트)와 fragment offset(13비트)은 하나의 세트</li>
<li>Flagment Offset = 첫 시작부분으로부터 떨어진 정도</li>
<li>Time To Live(TTL) : 패킷이 존재할 시간을 지정. 오류로 특정 네트워크 대역에서 영원히 머물게되는 것을 방지함.</li>
<li>Protocol : 상위 프로토콜의 타입을 알려준다. (ICMP : 1, 3계층, TCP : 6, 4계층, UDP: 17, 4계층)</li>
<li>Header Checksum : 헤더에 오류가 있는지 비교해서 확인하는 파트 (손실 방지)</li>
<li>Source IP Address : 출발지 IP주소</li>
<li>Destination IP Address : 목적지 IP주소</li>
</ul>
<hr>
<h2 id="2-icmp-프로토콜">2. ICMP 프로토콜</h2>
<blockquote>
<p>Internet Control Message Protocol, 인터넷 제어 메시지 프로토콜
: 네트워크 컴퓨터 위에서 돌아가는 운영체제에서 오류 메시지를 전송받는 데 주로 쓰임
: 프로토콜 구조의 타입과 코드를 통해 오류 메시지를 전송받음</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/a8e7150a-5050-4938-9c23-fb3464ee1d00/image.png" alt=""></p>
<ul>
<li>Type = 대분류  / Code = 소분류</li>
</ul>
<hr>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/8f7b9fb3-5f0d-4804-b0d0-4161cdc56790/image.png" alt=""></p>
<blockquote>
<p><strong>[ Type ]</strong>
0번, 8번 = 응답과 요청
3번, 11번 = 목적지 도달불가, 시간초과 / 3번은 아예 가지를 못한것 , 11번은 가긴했는데 응답을 못받는 것(ex. 상대방이 방화벽 켜둘 경우)
5번 = 원격지에 있는 상대방의 라우팅 테이블(지도)를 수정하는 것</p>
</blockquote>
<hr>
<h2 id="3-라우팅-테이블">3. 라우팅 테이블</h2>
<blockquote>
<p>어디로 보내야 하는지 설정되어 있음 (내가 보낸 패킷은 어디로 갈까)</p>
</blockquote>
<ul>
<li>라우팅? <ul>
<li>최적의 경로 = 주어진 데이터를 가장 짧거나 가장 빠른 시간 안에 전송할 수 있는 경로</li>
<li>서로 다른 네트워크 대역에 있는 장치 간 통신을 할 때 최적의 경로를 통해 통신을 가능하게 해 주는 것</li>
</ul>
</li>
</ul>
<hr>
<h2 id="4-ipv4-조각화-이론">4. IPv4 조각화 이론</h2>
<h3 id="조각화란">조각화란?</h3>
<blockquote>
<p>큰 IP 패킷들이 적은 MTU(Maximun Transmission Unit)를 갖는 링크를 통하여 전송되려면 여러 개의 작은 패킷으로 쪼개어/조각화 되어 전송되어야 함
즉, 목적지까지 패킷을 전달하는 과정에 통과하는 각 라우터마다 전송에 적합한 프레임으로 변환 필요</p>
</blockquote>
<ul>
<li>일단 조각화되면, 최종 목적지에 도달할 때까지 재조립되지 않는 것이 일반적</li>
<li>IPv4에서는 발신지 뿐만 아니라 중간 라우터에서도 IP 조각화 가능</li>
<li>IPv6에서는 IP 단편화가 발신지에서만 가능 / 재조립은 항상 최종 수신지에서만 가능함!!</li>
</ul>
<hr>
<h3 id="조각화-실습">조각화 실습</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/f818970e-26f2-4cde-bff5-9d0a0e2d5732/image.png" alt=""></p>
<ul>
<li>첫번째 패킷의 데이터 크기 = MTU(1500) - 20 = 1480 </li>
<li>마지막 패킷의 데이터 크기 = 4800 - 1480 - 1480 - 1480 = 360</li>
</ul>
<hr>
<p>(강의 : 따라하면서 배우는 IT)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘]]></title>
            <link>https://velog.io/@turtle_hw/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@turtle_hw/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sat, 16 Mar 2024 14:16:47 GMT</pubDate>
            <description><![CDATA[<h2 id="swea">SWEA</h2>
<ul>
<li><p><input checked="" disabled="" type="checkbox">  파리 퇴치(2001)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())

  for tc in range(1, T+1):
      N, M = map(int, input().split())
      flies = [list(map(int, input().split()))for _ in range(N)]

      max_die = 0

      for i in range(N-M+1):
          for j in range(N-M+1):
              result = 0
              for k in range(i, i+M):
                  for l in range(j, j+M):
                      result += flies[k][l]
              if max_die &lt; result:
                  max_die = result
      print(f&#39;#{tc} {max_die}&#39;)  # 이거 출력할 때 자꾸 result출력하려구 함 max_die 출력해야지!!
  -----------------------------------------------------------------
  T = int(input())

  for tc in range(1, T+1):
      N, M = map(int, input().split())  # N = 배열 / M = 파리채크기
      arr = [list(map(int, input().split())) for _ in range(N)]

      arr_2 = []

      for i in range(N-M+1):
          for j in range(N-M+1):
              paris = 0

              for k in range(M):
                  for l in range(M):
                      paris += arr[i+k][j+l]

              arr_2.append(paris) # 리스트에 어펜드해서 

      print(f&#39;#{tc} {max(arr_2)}&#39;)  # 최대값 출력하기 </code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  min max(4828)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      numbers = list(map(int, input().split()))
      max_num = numbers[0]
      min_num = numbers[0]
      for i in numbers:
          if max_num &lt;= i:
              max_num = i
          if min_num &gt;= i:
              min_num = i
      chi = max_num - min_num
      print(f&#39;#{tc} {chi}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  숫자 카드(4834)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  가장 많은 카드의 숫자와 장 수를 차례로 출력
  &#39;&#39;&#39;
  T = int(input())

  for tc in range(1, T+1):
      N = int(input())
      cards = map(int, input())
      # print(cards)
      tmp = [0] * 10 # 카드 개수 체크할 배열
      for card in cards:
          tmp[card] += 1

      max_card = tmp[0]  # 초기값 설정
      for index in range(len(tmp)):
          if max_card &lt;= tmp[index]:
              max_card = tmp[index]
              card_count = index
      print(f&#39;#{tc} {card_count} {max_card}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  구간합(4835) ⇒ 최소값 설정하기</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())

  for tc in range(1, T+1):
      N,M = map(int, input().split())
      numbers = list(input().split())
      # print(numbers)

      # max_sums = 0
      # min_sums =

      for i in range(N-M+1):   # i위치에서 M개의 원소를 더해서 비교해야하기 때문에 범위 -M 해주기
          sums = 0
          for j in range(M):   # 구간합 구하기위한 범위
              sums += int(numbers[i+j])  # i에서 시작하는 구간의 각 원소 sums에 더해서 구간 합 구하기

          if i == 0:
              max_sums,min_sums = sums, sums
          else:
              if max_sums &lt; sums:   # 구간합이 최대값으로 설정해 둔 것보다 크면
                  max_sums = sums     # 구간합으로 최대값 변경 반복
              if min_sums &gt; sums:   # 구간합이 최소값으로 설정해 둔 것보다 작으면
                  min_sums = sums     # 구간합으로 최소값 변경 반복

      result = max_sums - min_sums
      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  쉬운 거스름돈(1970)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  money = [50000, 10000, 5000, 1000, 500, 100, 50, 10]
  money_cnt = [0] * 8

  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      for i in range(8):
          # money의 각 금액으로 나눈 몫이
          # 그 돈을 사용할 개수가 되고
          # 나머지로 다시 또 다른 금액이 몇개 필요한지 반복해야한다
          money_cnt[i] = N // money[i]
          N %= money[i]
      print(f&#39;#{tc}&#39;)
      print(*money_cnt)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  두 개의 숫자열(1959)</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  색칠하기(4836)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  color = 1(빨강)
  color = 2(파랑)
  &#39;&#39;&#39;
  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      arr = [list(map(int, input().split())) for _ in range(N)]

      tmp = [[0] * 10 for _ in range(10)]  # 색칠할 범위 카운트해서 입력해 둘 배열 만들기
      # print(tmp)
      # print(arr)
      for i in arr:  # 배열에서 리스트 하나씩 꺼내와진다.
          for j in range(i[0], i[2] + 1):
              for k in range(i[1], i[3] + 1):
                  if i[4] == 1:
                      tmp[j][k] += 1
                  # elif i[4] == 2:
                  #     tmp[j][k] += 2
                  else:
                      tmp[j][k] += 2
      purple = 0
      for x in range(10):
          for y in range(10):
              if tmp[x][y] == 3:
                  purple += 1

      print(f&#39;#{tc} {purple}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  스도쿠검증(1974)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  N = 9

  # 3*3 확인할 때 쓸 델타
  di = [0,0,1,1,1,2,2,2]
  dj = [1,2,0,1,2,0,1,2]

  for tc in range(1, T+1):
      arr = [list(map(int, input().split())) for _ in range(N)]

      garo = arr # 가로는 그대로 받아와주고

      # 세로
   ## 참고 transpose = [list(i) for i in zip(*lst)]
  ### tmp2 = list(zip(*tmp))  # 전치행렬 # 튜플형태로 행렬이 전치됨
      # sero = list(map(list, zip(*arr))) # 전치행렬하는 방법
      sero = []
      for i in range(N):
          col = []
          for j in range(N):
              col.append(arr[j][i])
          sero.append(col)

      result = 1 # 조건에 안맞는일 없으면 1 출력할거다
      # 3*3 9칸 안에서
      for i in range(0, N, 3):
          for j in range(0, N, 3):
              point = arr[i][j] # 3*3 행렬의 0,0 위치를 point로 잡아주고
              for k in range(8):
                  ni = i + di[k]
                  nj = j + dj[k]
                  # if 0 &lt;= ni &lt; N and 0 &lt;= nj &lt; N:
                  point += arr[ni][nj] # 나머지 8칸을 더해준다.

              # point하나 정해졌을 때마다 검사하기
              for ga, se in zip(garo, sero): # 가로와 세로 배열에서 원소 하나씩 가져와서
                  # print(ga)
                  # 1-9까지의 총합이 45라서
                  if sum(ga) == sum(se) == point == 45: # 원소 내의 숫자들의 합이 45이고
                                                      # 다 더해져있는 point도 45이면
                      continue # 계속 진행시키기
                  else:  # 합이 45가 안되면
                      result = 0  # result 값을 0으로 변환시켜주기

      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  숫자 배열 회전(1961) ⇒ 다시 풀기</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  def rotation_90(arr):
      matrix = [[0]*N for _ in range(N)]
      for i in range(N):
          for j in range(N):
              matrix[i][j] = arr[N-1-j][i]
      return matrix

  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      arr = [list(map(int, input().split())) for _ in range(N)]
      result = rotation_90(arr)
      result2 = rotation_90(result)
      result3 = rotation_90(result2)
      # print(result)

      print(f&#39;#{tc}&#39;)
      for k in range(N):
          a = map(str, result[k])
          b = map(str, result2[k])
          c = map(str, result3[k])
          print(&#39;&#39;.join(a), &#39;&#39;.join(b), &#39;&#39;.join(c))</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  어디에 단어가 들어갈 수 있을까(1979)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  흰색 부분 = 1 (단어 들어갈 수 있는 곳)
  검은색 부분 = 0  (단어 들어갈 수 없는 곳)

  &#39;&#39;&#39;
  T = int(input())

  # 가로 단어 먼저 탐색하기
  for tc in range(1, T+1):
      N, K = map(int, input().split()) # 퍼즐가로세로길이 / 단어의 길이
      puzzle = [list(map(int, input().split())) for _ in range(N)]
      # print(puzzle)
      words = 0  # 들어갈수 있는 단어의 개수
      # 가로로 순회하면서 흰색부분이 나오면 cnt +1 하고
      for i in range(N):
          cnt = 0  # 단어의 길이
          for j in range(N):
              if puzzle[i][j] == 1:
                  cnt += 1
                  # print(cnt)
                  # 하다가 0을 만나거나 퍼즐의 끝이나오면 멈추고
              if puzzle[i][j] == 0 or j == N-1:
                  # 그 때의 길이를 단어의 길이 K와 비교해서
                  if cnt == K:
                      # 길이가 같으면 들어갈 수 있는 단어 +1 해주기
                      words += 1
                  cnt = 0  # 카운트 다한다음에 다시 다음 단어 길이 세려면
                  #         # 초기화 다시 해줘야 하는데 자꾸 까뮤금
      # print(words,&#39;words&#39;)

      for a in range(N):
          cnt2 = 0
          for b in range(N):
              if puzzle[b][a] == 1:
                  cnt2 += 1
              if puzzle[b][a] == 0 or b == N-1:
                  if cnt2 == K:
                      words += 1
                  cnt2 = 0
      print(f&#39;#{tc} {words}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  View(1206) ★</p>
</li>
<li><p>view</p>
<pre><code class="language-python">  # sol_1
  for tc in range(1, T+1):
      N = int(input())  # 건물의 개수 N
      h = list(map(int, input().split())) # N개의 건물의 높이
      cnt = 0 # 세대의 수 카운트
      for i in range(2, N-1):
          max_h = h[i]  # 가운데를 기준으로 얘가 최대조망권 초기설정값이됨
          for j in range(i-2, i+3): # 양쪽 2칸씩 비교해야함
              if i == j: # 나와 나자신을 비교할 필요는 없다
                  continue # 지나가쟈
              if h[i] &gt; h[j] and max_h &gt; h[i]-h[j]:
                  max_h = h[i]-h[j]
              if h[i] &lt;= h[j]:
                  break
          else:
              cnt += max_h
      print(f&#39;#{tc} {cnt}&#39;)

  # sol_2
  T = 10                      # TC 10개 고정
  for tc in range(1, T+1):    # 10번 돌면서
      N = int(input())        # 가로 길이(N개의 건물)
      height = list(map(int, input().split()))   # 건물 높이 노나서 받아오기

      view = 0    # 초기값 설정
      for i in range(2, N-2):
          # 2 이상의 공간이 확보 되어야하니까 i-2부터 비교하기 위해서 설정
          max_v = height[i-2]
          # max_v = 0
          if max_v &lt; height[i-1]:   # i-1과 비교
              max_v = height[i-1]
          if max_v &lt; height[i+1]:  # i+1과 비교
              max_v = height[i+1]
          if max_v &lt; height[i+2]:  # i+2과 비교
              max_v = height[i+2]
          # if max_v &lt; height[i-2]:  # i-2과 비교
          #     max_v = height[i-2]       # 얘는 제거해도 됨
          if height[i] &gt; max_v:  # i가 주변 보다 높으면
              view += height[i] - max_v

      print(f&#39;#{tc} {view}&#39;)

  # sol_3
  T = 10
  for tc in range(1, T+1):
      N = int(input())
      lst = list(map(int, input().split()))

      res = 0
      for i in range(2, N-2):
          d2 = lst[i] - lst[i+1]
          d1 = lst[i] - lst[i+2]
          d_1 = lst[i] - lst[i-1]
          d_2 = lst[i] - lst[i-2]
          if d2 &gt; 0 and d_1 &gt; 0 and d1 &gt; 0 and d_2 &gt;0:
              res += min(d_2, d_1,d1,d2)
      print(f&#39;#{tc} {res}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  Flatten(1208)⇒ 한번만 더</p>
</li>
<li><p>Flatten</p>
<pre><code class="language-python">  T = 10
  for tc in range(1, T+1):
      dump = int(input())
      lst = list(map(int, input().split()))

      for i in range(dump):
          lst.sort()
          if lst[-1] - lst[0] &lt;= 1:
              break
          lst[0] += 1
          lst[-1] -= 1

      res = max(lst) - min(lst)
      print(f&#39;#{tc} {res}&#39;)
  ---------------------------------------------------------------
  for tc in range(1, 11):
    res = 0
    dump = int(input())
    ct = list(map(int, input().split()))
    for _ in range(dump):
      max_1 = max(ct)
      min_1 = min(ct)
      # 최대, 최소 값 인덱스 받아오기
      maxIdx = ct.index(max_1)
      minIdx = ct.index(min_1)
      ct[maxIdx] -= 1
      ct[minIdx] += 1
    res = max(ct) - min(ct)
    print(f&#39;#{tc} {res}&#39;)
  ---------------------------------------------------------------
  T = 10
  W = 100 # 가로는항상 100으로 주어짐

  for tc in range(1, T+1):
      dump_ = int(input()) # 덤프 횟수 제한
      boxes = list(map(int, input().split())) # 각 상자의 높이
      result = 0
      while dump_ &gt; 0: # 덤프횟수가 소진될 때까지
          dump_ -= 1 # 한번 반복할 때마다 덤프횟수 -1
          max_idx = 0
          min_idx = 0
          # 범위설정 1부터 하는 이유는 이미 max_idx 값 초기화를 0으로 해뒀기 때문에
          # 굳이 0부터 비교하면 똑같은거끼리 비교하는거라서 1부터 하면 되는 거!!
          for i in range(1, W):
              # boxes의 몇번째인덱스위치가 최고점일까
              if boxes[max_idx] &lt;= boxes[i]:
                  max_idx = i
              # boxes의 몇번째인덱스위치가 최저점일까
              if boxes[min_idx] &gt;= boxes[i]:
                  min_idx = i
          # 최고점 최저점을 찾은 다음에
          if boxes[max_idx] - boxes[min_idx] &lt;= 1:
              # 최고점과 최저점의 간격이 1보다 작거나 같아지면(평탄화 완료)
              # 최고점과 최저점의 차이를 반환하고 끝낸다.
              result = boxes[max_idx] - boxes[min_idx]
              break
          else: # 평탄화가 완료되지 않으면(아직 진행중이면)
              boxes[max_idx] -= 1 # 가장 높은 상자에서 하나 빼서
              boxes[min_idx] += 1 # 가장 낮은 상자에 하나 더해주기

      if dump_ == 0: # 아직 평탄화 다 못했는데 평탄화제한 횟수 다 써버리면
          min_idx = 0
          max_idx = 0
          for j in range(W): # 범위 돌면서 최고점, 최저점 찾기
              # boxes의 몇번째인덱스위치가 최고점일까
              if boxes[min_idx] &gt; boxes[j]:
                  min_idx = j
              # boxes의 몇번째인덱스위치가 최저점일까
              if boxes[max_idx] &lt;= boxes[j]:
                  max_idx = j
          result = boxes[max_idx] - boxes[min_idx] # 그때의 차이 출력

      print(f&#39;#{tc} {result}&#39;)
  ------------------------------------------------------------------------------------T = 10
  W = 100

  for tc in range(1, T+1):
      dump_cnt = int(input())
      boxes = list(map(int, input().split()))
      boxes.sort()
      while dump_cnt &gt; 0:
          dump_cnt -= 1
          boxes[-1] -= 1
          boxes[0] += 1
          boxes.sort()

      result = max(boxes) - min(boxes)
      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  민석이의 과제 체크하기</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  Sumㅌ</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  특별한 정렬(4843)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      numbers = list(map(int, input().split()))
      # print(numbers)
      result = []
      numbers.sort()
      # print(numbers)
      while numbers:
          result.append(numbers.pop())
          result.append(numbers.pop(0))

      case = result[:10]

      print(f&#39;#{tc}&#39;,*case)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  Magnetic(1220) - if/elif</p>
</li>
<li><p>자석</p>
<pre><code class="language-python">  T = 10

  for tc in range(1, T+1):
      N = int(input()) # 테이블의 한 변의 길이
      table = [list(map(int, input().split())) for _ in range(N)]
      # print(table)
      cnt = 0
      for i in range(N):
          flag = 0
          for j in range(N):
              if table[j][i] == 1:
                  flag = 1
              elif table[j][i] == 2 and flag == 1:
                  cnt += 1
                  flag = 0 # 다시 아무것도 안움직이는 상태로 되돌려주기
      print(f&#39;#{tc} {cnt}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  최대 성적표 만들기(4466)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())

  for tc in range(1, T+1):
      N, K = map(int, input().split())
      scores = list(map(int, input().split()))
      # print(N,K)
      # print(scores)
      scores.sort()  # 정렬 해주고
      sum_ls = []  # 최대값 K개 넣을 리스트 만들고
      for i in range(K):
          sum_ls.append(scores.pop()) # 정렬해둿으니까 뒤에서부터 큰 수 K개
                              # pop해서 리스트에 넣어주고
      # print(sum_ls)

      result = 0 # 결과값 변수
      for j in range(len(sum_ls)): # 리스트에 넣은 개수만큼 반복하면서
          result += sum_ls.pop() # 결과값에 누적해서 더해주기

      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  농작물 수확하기(2805) ⇒ 범위 문제</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      arr = [list(map(int, input())) for _ in range(N)]
      benefit = 0

      G = N//2
      for i in range(N):
          if i &lt;= G:
              for j in range(G-i, G+i+1):
                  benefit += arr[i][j]
          else:
              for j in range(i-G, N-i+G):
                  benefit += arr[i][j]
      print(f&#39;#{tc} {benefit}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  정곤이의 단조 증가하는 수(6190) </p>
</li>
<li><p>정곤이</p>
<pre><code class="language-python">  # sol 1
  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      numbers = list(map(int, input().split()))
      multis = []
      for i in range(N):
          for j in range(i+1, N):
              multi = numbers[i]*numbers[j]
              multis.append(str(multi))

      danjo = []
      for k in multis:
          LEN = len(k)
          if LEN &lt; 2:
              continue

          check = True # 단조 증가하는지 체크
          for a in range(LEN-1):
              if k[a] &gt; k[a+1]: # 앞의 자리가 뒤 자리 보다 크게 되면
                  check = False # check 변환 그러면서
                  break # 바로위 for문 탈출
          if check: # 방금 포문 아무 이상없이 한바꾸 돌았네 ?
              danjo.append(int(k)) # 그럼 dan 리스트에 i이놈 정수로 바까서 ean에 넣어줘

      if danjo:
          result = max(danjo)  # max doesn&#39;t work in empty list
          print(f&#39;#{tc} {result}&#39;)
      else:
          print(f&#39;#{tc} -1&#39;)
  ------------------------------------------------------------------------------------

  # sol2
  T = int(input())
  for tc in range(1, T+1):
      N = int(input())
      numbers = list(map(int, input().split()))
      multis = []
      for i in range(len(numbers)-1):
          for j in range(i+1, len(numbers)):
              multi = numbers[i]*numbers[j]
              multi_list = list(map(int, str(multi)))
              multi_len = len(multi_list)
              # print(multi_list)  # [8] / [1, 4] / [2, 0] / [2, 8] / [4, 0] / [7, 0]
              check = True
              for a in range(multi_len - 1):
                  if multi_list[a] &gt; multi_list[a+1]:
                      check = False
                      break
              else:
                  multis.append(multi)

      result = int(max(multis))
      if multis:
          print(f&#39;#{tc} {result}&#39;)
      else:
          print(f&#39;#{tc} -1&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  GNS(1221)</p>
</li>
<li><p>GNS</p>
<pre><code class="language-python">  numbers = [&#39;ZRO&#39;, &#39;ONE&#39;, &#39;TWO&#39;, &#39;THR&#39;, &#39;FOR&#39;, &#39;FIV&#39;, &#39;SIX&#39;, &#39;SVN&#39;, &#39;EGT&#39;, &#39;NIN&#39;]

  T = int(input())
  for _ in range(1, T+1):
      tc, L = input().split()
      num_ls = list(input().split())
      # sort_ls = sorted(num_ls, reverse=True)
      ls = []
      N = len(num_ls)
      for i in range(N):
          ls.append(numbers.index(num_ls[i]))

      ls.sort()

      for j in range(N):
          ls[j] = numbers[ls[j]]

      print(tc)
      print(*ls)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  회문1(1215) = 외우기</p>
</li>
<li><p>회문1</p>
<pre><code class="language-python">  T = 10
  for tc in range(1, T+1):
      K = int(input())
      N = 8
      arr = [input() for _ in range(N)]
      # print(arr)
      cnt = 0  # 회문개수 세려고
      for i in range(N):
          for j in range(N - K + 1): # 회문의 길이가 K라서
              for p in range(K // 2):# 찾아야 하는 회문길의의 절반만큼 기준잡아서
                  if arr[i][j + p] != arr[i][j + K - 1 - p]: #  가로
                      break  # for p, j부터 시작하는 구간은 회문이 아님
              else:   # for이 끝나고 실행되는 행
                      # 근데 만약 break가 실행된 상태면 이거 실행 안됨
                  cnt += 1
              for p in range(K // 2):
                  if arr[j + p][i] != arr[j + K - 1 - p][i]: # 세로
                      break  # for p, j부터 시작하는 구간은 회문이 아님
              else:
                  cnt += 1
      print(f&#39;#{tc} {cnt}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  회문2(1216)</p>
</li>
<li><p>회문2</p>
<pre><code class="language-python">  T = 10
  N = 100
  for _ in range(1, T+1):
      tc = int(input())
      matrix = [input() for _ in range(N)]
      length = 0
      # 회문의 길이 긴것부터 가져와서 l로
      for l in range(N, 0, -1):
          for i in range(N):
              for j in range(N-l+1):
                  for k in range(l//2):
                      if matrix[i][j+k] != matrix[i][j+l-1-k]:
                          break
                  else:
                      length = max(l, length)
                  for p in range(l//2):
                      if matrix[j+p][i] != matrix[j+l-1-p][i]:
                          break
                  else:
                      length = max(l, length)
      print(f&#39;#{tc} {length}&#39;)

  ====================================================================================
  T = 10
  N = 100

  for _ in range(1, T+1):
      tc = int(input())
      pallin = [input() for _ in range(N)]
      # print(pallin)
      long = 1

      for K in range(N, 0, -1): # K의 길이를 긴 것부터 뽑아와서 설정해주고
          for i in range(N):
              for j in range(N-K+1):
                  for k in range(K//2):
                      check = True
                      if pallin[i][j+k] != pallin[i][j+K-1-k]:
                          check = False
                          break
                  if check:
                      # 설정해둔 K랑 long이랑 비교해서 가장 긴 회문길이 구하기
                      long = max(long, K) 

                  for p in range(K//2):
                      check = True
                      if pallin[j+p][i] != pallin[j+K-1-p][i]:
                          check = False
                          break
                  if check:
                      long = max(long, K)
      print(f&#39;#{tc} {long}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  진기의 최고급 붕어빵(1860)</p>
</li>
<li><p>붕어빵</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  제공할 수 있으면 &#39;Possible&#39;
  아니라면 &#39;Impossible&#39;
  &#39;&#39;&#39;

  T = int(input())
  for tc in range(1, T+1):
      # N손님수, M초마다 K개 생산
      N, M, K = map(int, input().split())
      # print(N, M, K)

      # N명이 각각 도착하는 시간
      visited_time = list(map(int, input().split()))
      visited_time.sort()  # 도착시간 순으로 정렬
      result = &#39;Possible&#39;
      for i in range(N):
          # 1초에 K//M씩 생산하니까
          # i+1 번째 손님이 방문한 시간이
          # i 번째 손님이 방문한 시간까지의 붕어빵 생산량보다 커버리면
          # 붕어빵이 없어서 제공할 수가 없으니까
          # 아래와 같이 조건문을 달아준다.
          if i+1 &gt; visited_time[i]//M*K:
              result = &#39;Impossible&#39;
              break
      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  기차사이의 파리(6019)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  for tc in range(1, T+1):
      D, A, B, F = map(int, input().split())
      # A와 B는 D/(A+B)시간이면 만난다
      time = D/(A+B)

      # 파리의 이동거리은 D/(A+B)를 파리의 속력이랑 곱하면 된다
      result = time*F
      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  Ladder1(1210)</p>
</li>
<li><p>ladder1 ⇒ 다시 한번 보자</p>
<pre><code class="language-python">  # 하, 좌, 우
  dx = [1, 0, 0]
  dy = [0, -1, 1]

  def search(x,y):
      #들린 지점은 1로 표시해서 다시 돌아가지 않게 만들기 위함
      visited = [[0]*100 for _ in range(100)]
      original_y = y  # 출발지점의 x좌표
      visited[x][y] = 1

      while x != 99:  # 마지막 행까지 갈 동안
          for k in range(3):  # 하, 좌, 우 방향 조사하면서
              ni = x + dx[k]
              nj = y + dy[k]
              # ni,nj가 범위 안에 있고 갈 수 있는 길이며, 들린적이 없으면 가야지
              if 0 &lt;= ni &lt; N and 0 &lt;= nj &lt; N and ladder[ni][nj] and visited[ni][nj] == 0:
                  x, y = ni, nj  # 그리고 거기를 기점으로 또 serch 해야함
                  visited[ni][nj] = 1   # 들렀음을 표시해주자

      if ladder[x][y] == 2: # 2가 적혀있는 도착점에 다다르면
          return original_y    # 출발위치의 x좌표인 y를 반환
      else:
          return &quot;실패&quot;

  T = 10
  N = 100
  for _ in range(1, T+1):
      tc = int(input())
      ladder = [list(map(int, input().split())) for _ in range(N)]
      # print(ladder)
      for i in range(N):
          if ladder[0][i] == 1:
              result = search(0, i)
          if result != &quot;실패&quot;:
              break

      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  Ladder2(1211)</p>
</li>
<li><p>ladder2 ⇒ 다시 한번 보자</p>
<pre><code class="language-python">  # sol_1
      # 하, 좌, 우
  dx = [0, 0, 1]
  dy = [1, -1, 0]

  def check(x, y):
      visited = [[0] * 100 for _ in range(100)]
      original = y
      visited[x][y] = 1
      cnt = 0
      while x != 99:
          for k in range(3):
              ni = x + dx[k]
              nj = y + dy[k]
              if 0 &lt;= ni &lt; N and 0 &lt;= nj &lt; N and ladder[ni][nj] and visited[ni][nj] == 0:
                  x, y = ni, nj
                  visited[ni][nj] = 1
                  cnt += 1
                  break
      return [cnt, original]

  T = 10
  N = 100
  for _ in range(1, T+1):
      tc = int(input())
      ladder = [list(map(int, input().split())) for _ in range(N)]
      distance = 987654321  # 가장 짧은 이동거리를 구하기 위해 비교할 초기값 설정
      ans_y = 0   # 시작점인 x좌표 구하기 위해 비교할 초기값 설정

      for i in range(N):
          if ladder[0][i] == 1:  # 첫번째 행의 값이 1이면 시작지점
              dis, y_cordi = check(0, i)  # 이동거리와, 그때의 x 좌표를 반환한다
              # print(dis, y_cordi)
              if distance &gt; dis:  # 가장 짧은 이동거리를 찾는다
                  distance = dis  # 그 때의 거리와
                  ans_y = y_cordi # 그 때의 시작점 x좌표를 구한다.
      print(f&#39;#{tc} {ans_y}&#39;)
  ----------------------------------------------------------------------------------
  # sol_2
  # 하, 좌, 우
  dx = [0, 0, 1]
  dy = [1, -1, 0]

  def check(x, y):
      visited = [[0] * 100 for _ in range(100)]
      original = y
      visited[x][y] = 1
      cnt = 0
      while x != 99:
          for k in range(3):
              ni = x + dx[k]
              nj = y + dy[k]
              if 0 &lt;= ni &lt; N and 0 &lt;= nj &lt; N and ladder[ni][nj] and visited[ni][nj] == 0:
                  x, y = ni, nj
                  visited[ni][nj] = 1
                  cnt += 1
                  break

      return [cnt, original]  # 이동거리와,  좌표값을 리스트에 넣어서 반환한다.

  T = 10
  N = 100
  for _ in range(1, T + 1):
      tc = int(input())
      ladder = [list(map(int, input().split())) for _ in range(N)]
      cnt_list = []  # check 함수에서 반환되는 리스트 넣을 리스트 만들어두기

      for i in range(N): # N크기의 사다리라서 그 길이만큼 순회하면서
          if ladder[0][i] == 1:  # 첫번째 행의 값이 1이면 시작지점이다
              # 그때의 이동거리와, 좌표값리스트를 구하기 위한 check함수 호출 및 cnt_list에 담기
              cnt_list.append(check(0, i))

      cnt_list.sort()  # 기본정렬은 리스트의 리스트 첫번째 값을 기준으로 오름차순 정렬된다.
      result = cnt_list[0][1] # 정렬해뒀으니까 제일 앞에 있는 것의 이동거리가 제일 작을 것이고
                              # 그때의 x좌표를 result에 할당한다.
      print(f&#39;#{tc} {result}&#39;)
  ----------------------------------------------------------------------------------
  # sol_3
  for tc in range(1, 11):
      input()
      MAP = [list(map(int, input().split())) for _ in range(100)]

      MIN = float(&#39;inf&#39;)
      res = -1
      for start in range(100):
          if MAP[0][start] == 1:
              col = start
              row = 0
              cnt = 0

              while row &lt; 99:
                  cnt += 1

                  # 오른쪽으로 이동
                  if col &lt; 99 and MAP[row][col+1] == 1:
                      while col &lt; 99 and MAP[row][col+1] == 1:
                          col += 1
                          cnt += 1
                  # 왼쪽으로 이동
                  elif col &gt; 0 and MAP[row][col-1] == 1:
                      while col &gt; 0 and MAP[row][col-1] == 1:
                          col -= 1
                          cnt += 1
                  row += 1
              if MIN &gt; cnt:
                  MIN = cnt
                  res = start
      print(f&#39;#{tc} {res}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  행렬찾기(1258)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  for tc in range(1, T+1):
      n = int(input())
      arr = [list(map(int, input().split())) for _ in range(n)]
      ls = []
      for i in range(n):
          for j in range(n):
              if arr[i][j] != 0:
                  x, y = j, i

                  while x &lt; n and arr[i][x] != 0:
                      x += 1

                  while y &lt; n and arr[y][j] != 0:
                      y += 1

                  if arr[i][j] != 0:  # 요조건은 위에 이미 있어서 안해두 댐
                      ls.append((y-i, x-j))

                  for a in range(i, y):
                      for b in range(j, x):
                          arr[a][b] = 0

          ls.sort(key=lambda a: (a[0]*a[1], a[0]))

      print(f&#39;#{tc}&#39;, len(ls), end=&#39; &#39;)
      for x,y in ls:
          print(x, y, end=&#39; &#39;)
      print()</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  러시아 국기 같은 깃발(4613)</p>
</li>
<li><p>러시아</p>
<pre><code class="language-python">  T = int(input())
  for tc in range(1, T+1):
      N, M = map(int, input().split())
      arr = [input() for _ in range(N)]

      mx = 0
      for i in range(N-2):
          for j in range(i+1, N-1):
              cnt = 0
              for s in range(i+1):
                  cnt += arr[s].count(&#39;W&#39;)
              for s in range(i+1, j+1):
                  cnt += arr[s].count(&#39;B&#39;)
              for s in range(j+1, N):
                  cnt += arr[s].count(&#39;R&#39;)
              mx = max(mx, cnt)
      print(f&#39;#{tc} {N*M-mx}&#39;)</code></pre>
</li>
</ul>
<hr>
<hr>
<ul>
<li><p><input checked="" disabled="" type="checkbox">  상호의 배틀필드(1873)</p>
</li>
<li><p>배틀필드</p>
<pre><code class="language-python">  import sys
  # sys.stdin = open(&#39;input.txt&#39;)

  T = int(input())

  for tc in range(1, T + 1):
      H, W = map(int, input().split())
      MAP = [list(input()) for _ in range(H)]
      N = int(input())
      comm = input()

      for i in range(H):
          for j in range(W):
              if MAP[i][j] in &#39;&lt;&gt;^v&#39;:
                  row = i
                  col = j
                  break

      for i in range(len(comm)):
          t_row = row
          t_col = col

          if comm[i] == &#39;U&#39;:
              MAP[t_row][t_col] = &#39;^&#39;
              if t_row-1 &gt;= 0 and MAP[t_row-1][t_col] == &#39;.&#39;:
                  MAP[t_row-1][t_col] = &#39;^&#39;
                  MAP[t_row][t_col] = &#39;.&#39;
                  row -= 1

          elif comm[i] == &#39;R&#39;:
              MAP[t_row][t_col] = &#39;&gt;&#39;
              if t_col+1 &lt; W and MAP[t_row][t_col+1] == &#39;.&#39;:
                  MAP[t_row][t_col+1] = &#39;&gt;&#39;
                  MAP[t_row][t_col] = &#39;.&#39;
                  col += 1

          elif comm[i] == &#39;L&#39;:
              MAP[t_row][t_col] = &#39;&lt;&#39;
              if t_col -1 &gt;= 0 and MAP[t_row][t_col-1] == &#39;.&#39;:
                  MAP[t_row][t_col-1] = &#39;&lt;&#39;
                  MAP[t_row][t_col] = &#39;.&#39;
                  col -= 1

          elif comm[i] == &#39;D&#39;:
              MAP[t_row][t_col] = &#39;v&#39;
              if t_row+1 &lt; H and MAP[t_row+1][t_col] == &#39;.&#39;:
                  MAP[t_row+1][t_col] = &#39;v&#39;
                  MAP[t_row][t_col] = &#39;.&#39;
                  row += 1

          elif comm[i] == &#39;S&#39;:
              if MAP[t_row][t_col] == &#39;^&#39;:
                  if t_row -1 &gt;= 0:
                      for u in range(t_row-1, -1, -1):
                          if MAP[u][t_col] == &#39;*&#39;:
                              MAP[u][t_col] = &#39;.&#39;
                              break
                          elif MAP[u][t_col] == &#39;#&#39;:
                              break

              elif MAP[t_row][t_col] == &#39;&gt;&#39;:
                  if t_col + 1 &lt; W:
                      for r in range(t_col + 1, W):
                          if MAP[t_row][r] == &#39;*&#39;:
                              MAP[t_row][r] = &#39;.&#39;
                              break
                          elif MAP[t_row][r] == &#39;#&#39;:
                              break

              elif MAP[t_row][t_col] == &#39;v&#39;:
                  if t_row + 1 &lt; H:
                      for d in range(t_row +1, H):
                          if MAP[d][t_col] == &#39;*&#39;:
                              MAP[d][t_col] = &#39;.&#39;
                              break
                          elif MAP[d][t_col] == &#39;#&#39;:
                              break

              elif MAP[t_row][t_col] == &#39;&lt;&#39;:
                  if t_col - 1 &gt;= 0:
                      for l in range(t_col - 1, -1, -1):
                          if MAP[t_row][l] == &#39;*&#39;:
                              MAP[t_row][l] = &#39;.&#39;
                              break
                          elif MAP[t_row][l] == &#39;#&#39;:
                              break

      print(f&#39;#{tc} {&quot;&quot;.join(MAP[0])}&#39;)
      for k in range(1, H):
          print(&quot;&quot;.join(MAP[k]))</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  문제 제목 붙이기(7087) ⇒ 파이썬 제출 안됨</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())

  for tc in range(1, T+1):
      cnt = 0
      N = int(input())
      ls = []
      for _ in range(N):
          ls.append(input())
          ls.sort()
          # print(ls)
          log = 0
          for i in range(len(ls)-1):
              if log == 0:
                  if ord(ls[i][0]) == ord(ls[i+1][0]):
                      cnt += 1
                      log = 1
                  if ord(ls[i][0]) + 1 == ord(ls[i+1][0]):
                      cnt += 1
                  else:
                      break
              else:
                  if ord(ls[i][0]) + 1 == ord(ls[i+1][0]):
                      cnt += 1
                  else:
                      break

      print(f&#39;#{tc} {cnt}&#39;)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  영준이의 카드 카운팅(4047)</p>
</li>
<li><p><input disabled="" type="checkbox">  퍼팩트 셔플(3499)</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  패턴 마디의 길이(2007)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())
  cnt = 0 # 마디의 길이를 출력할거다

  for tc in range(1, T+1):
      sentence = list(input())
      # print(sentence)
      # N = len(sentence)
      madi = 0
      for i in range(1, 11):
          if sentence[:i] == sentence[i:i*2]:
              madi = i
              break
      print(f&#39;#{tc} {madi}&#39;)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  간단한 369게임(1926)</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  자기방으로 돌아가기(4408)</p>
</li>
<li><p>자기방</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  겹치는 만큼 기다려야하니까 가장 많이 겹치는 만큼이 최소 걸리는 시간이 되겠다!!
  &#39;&#39;&#39;

  T = int(input())
  for tc in range(1, T+1):
      N = int(input())  # 학생 수
      arr = [list(map(int, input().split())) for _ in range(N)]

      # for _ in range(N):
      #     go, to = map(int, input().split()) 9# 현재 방과 돌아갈 방
      #     print(go,to)
      # print(arr)

      cnt = [0] * 201         # 방사이 공간을 지나는 사람수를 기록할 복도
      for a, b in arr:        # arr에서 두개 꺼낼건데 a &lt;= b라는 보장이 없음에 주의!!
                              # 복도번호 = (방번호 + 방번호%2) // 2
          a = (a + a % 2)//2
          b = (b + b % 2)//2
          for i in range(min(a, b), max(a, b)+1):  # 둘 중 작은데서 출발해서 둘중 큰곳으로 도착
              cnt[i] += 1
      print(f&#39;#{tc} {max(cnt)}&#39;)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  재밌는 오셀로 게임</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  18575</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  T = int(input())

  di = [-1,0,1,0]
  dj = [0,1,0,-1]

  for tc in range(1, T +1):
      N = int(input())
      arr = [list(map(int, input().split())) for _ in range(N)]

      max_sum = 0
      min_sum = 987654321
      for i in range(N):
          for j in range(N):
              point = arr[i][j]
              for k in range(4):
                  for l in range(1, N):
                      ni = i + di[k]*l
                      nj = j + dj[k]*l
                      if 0 &lt;= ni &lt; N and 0 &lt;= nj &lt; N:
                          point += arr[ni][nj]

              if max_sum &lt;= point:
                  max_sum = point
              if min_sum &gt;= point:
                  min_sum = point
      result = max_sum - min_sum
      print(f&#39;#{tc} {result}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  당근 포장하기(16811)</p>
</li>
<li><p>sol</p>
<pre><code class="language-python">  def check(N, ls): # 당근의 크기를 입력하면 모든 조건을 확인하는 프로그램
      &#39;&#39;&#39;
      당근 3개 =&gt; 소,중,대 상자에 든 당근의 개수 차이 = 0 소 1 중 1 대 1 씩 들어갔으니까
      당근 5개  &gt; 소 3 중 1 대 1 = 당근의 개수 차이 2
          그런데 2개 초과하는 상자 잇으니까 조건 만족 x
      당근 8개
      &#39;&#39;&#39;
      L = int(N/2) # L초과하는 당근이 있으면 안됨
      ls.sort()
      min_chai = 987654321  # 포장개수차이 최소값 초기값 설정
      for i in range(N-2):
          for j in range(i+1, N-1):
              if ls[i] != ls[i+1] and ls[j] != ls[j+1]:
                  small = i+1
                  middle = j-i
                  large = N-1-j
                  if small &lt;= L and middle &lt;= L and large &lt;= L:
                      if min_chai &gt;= (max(small, middle, large) - min(small, middle, large)):
                          min_chai = max(small, middle, large) - min(small, middle, large)
      return min_chai

  T = int(input()) # 수확횟수
  for tc in range(1, T+1):
      N = int(input()) # 수확한 당근의 개수 3
      C = list(map(int, input().split())) # 당근의 크기 1 2 3
      # C.sort() # 당근을 크기 순으로 정렬
      # min_v = 1000 # 포장별 최소 개수 차이, 포장 불가인 경우 -1
      # for i in range(N-2):
      #     for j in range(i+1, N-1):
      #         if C[i] != C[i+1] and C[j] != C[j+1]: # 같은 크기 사이에 경계를 두면 안돼
      #             small = i + 1   # 소 상자에 들어간 당근 개수
      #             middle = j-i    # 중 상자에 들어간 당근 개수
      #             large = N-1-j   # 대 상자에 들어간 당근 개수
      #             if 0 &lt; small &lt;= N//2 and 0 &lt; middle &lt;= N//2 and 0 &lt; large &lt;= N//2:
      #                 if min_v &gt; (max(small, middle, large) - min(small, middle, large)):
      #                     min_v = max(small, middle, large) - min(small, middle, large)
      res = check(N,C)
      if res == 987654321:
          print(f&#39;#{tc} -1&#39;)
      else:
          print(f&#39;#{tc} {res}&#39;)</code></pre>
</li>
</ul>
<h2 id="백준">백준</h2>
<ul>
<li><p><input checked="" disabled="" type="checkbox">  스위치_켜고_끄기</p>
</li>
<li><p><input disabled="" type="checkbox">  주사위_쌓기</p>
</li>
<li><p><input disabled="" type="checkbox">  창고_다각형</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  일곱_난쟁이(2309)</p>
</li>
<li><p>난쟁이</p>
<pre><code class="language-python">  K = 100
  S = 0
  ls = []
  for i in range(9):
      ls.append(int(input()))

  S = sum(ls)
  find = S - K
  ls.sort()
  a = 0
  b = 0

  N = len(ls)
  for j in range(N-1):
      for k in range(j+1, N):
          if ls[j] + ls[k] == find:
              a = ls[j]
              b = ls[k]
              # print(a, b) = 15, 25
              # print(type(a)) -&gt; int

  for f in ls:
      if f != a and f != b:
          print(f)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  참외밭</p>
</li>
<li><p><input disabled="" type="checkbox">  직사각형</p>
</li>
<li><p>2527</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  직사각형을 만드는 방법</p>
</li>
<li><p>8320</p>
<pre><code class="language-python">  N = int(input())

  # [1] 가능한 경우를 모두 순회
  ans = 0
  for i in range(1, N+1):
      for j in range(i, N+1):
          if i*j &lt;= N:
              ans += 1
  print(ans)

  # [2] 몫 연산을 통해서 처리
  ans = N
  for i in range(2, N):
      n = N // i - (i-1)
      if n &lt; 1:
          break
      ans += n
  print(ans)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  수열</p>
</li>
<li><p>2559</p>
<pre><code class="language-python">  # N = 온도측정한 전체 날짜의 수, K = 합구하기 위한 연속적인 날짜의 수
  N, K = map(int, input().split())
  degrees = list(map(int, input().split())) # 매일 측정한 온도
  result = [] # 온도의 합을 구해서 넣어둘 리스트
  result.append(sum(degrees[0:K])) # 0번째부터 K-1번째까지 먼저 합해서 넣어준다음
  for i in range(N-K): # K개만큼 더해야하니까 인덱스 번호 N에서 K 빼준 범위로 설정
     result.append(result[i]-degrees[i]+degrees[i+K])
     # 더한거에서 젤 앞에꺼 빼고 그다음 하나 더해주기(한칸씩 뒤로 가는겨)
  print(max(result)) # 리스트에 넣어둔 것들 중 가장 큰값 프린트 하기</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  색종이(2563)</p>
</li>
<li><p>색종이</p>
<pre><code class="language-python">  N = int(input())

  matrix = [[0]*102 for _ in range(102)] # 색종이 표시할 배열

  for _ in range(N):
      a, b = map(int, input().split())
      for i in range(a,a+10):
          for j in range(b, b+10):
              matrix[i][j] = 1

  result = 0
  for k in matrix:
      result += sum(k)  # matrix 안의 k리스트들의 합을 result에 누적시켜 더해주면
                          # 넓이(1로 채워져 있는 곳)이 나온다
  print(result)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  색종이(10163)</p>
</li>
<li><p>10163</p>
<pre><code class="language-python">  def count(arr):
      cnt = 0
      for ls in arr:
          for k in range(1, len(ls)):
              if ls[k-1] != ls[k]:
                  cnt += 1
      return cnt

  N = int(input())
  tmp = [[0]*102 for _ in range(102)]
  for _ in range(N):
      a, b = map(int, input().split())
      for i in range(a, a+10):
          for j in range(b, b+10):
              tmp[i][j] = 1

  # tmp2 = list(zip(*tmp))  # 전치행렬 # 튜플형태로 행렬이 전치됨
  tmp2 = list(map(list, zip(*tmp)))  # 수정 필요할 시의 전치행렬 # 리스트 형태로 전치됨

  result = count(tmp) + count(tmp2)
  print(result)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  경비원</p>
</li>
<li><p><input disabled="" type="checkbox">  빙고</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  줄_세우기</p>
</li>
<li><p>2605</p>
<pre><code class="language-python">  N = int(input()) # 학생의 수
  numbers = list(map(int, input().split()))
  alst = [n for n in range(1, N+1)]
  # print(alst) # [1, 2, 3, 4, 5]

  for i in range(N): # i위치의 학생을 순서대로 이동처리
      n, t = numbers[i], alst[i] # 앞으로 이동할 칸 수, 학생번호
      # 순차적으로 덮어씌우기
      # 나한테 전에꺼를 집어넣기
      # 끝난다음에는 alst[i-n]번째에 t 넣어주기
      for j in range(i, i-n, -1):
          alst[j] = alst[j-1]
      alst[i-n] = t
  print(*alst)</code></pre>
</li>
<li><p>10431</p>
<pre><code class="language-python">  P = int(input())
  for tc in range(1, P+1):
      lst = list(map(int, input().split()))[1:]
      cnt = 0
      for i in range(1, 20):
          for j in range(i): # i의 이전 값들을 비교할것
              if lst[i] &lt; lst[j]: # 더 큰애들이 앞에 서있으면
                  cnt += 1 # 카운트 증가

      print(f&#39;{tc} {cnt}&#39;)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  종이자르기</p>
</li>
<li><p>2628 - idea</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  가장 큰 종이 조각의 넓이 ?
  바깥 둘레에서 잘라야하는 열과 행의 번호를
  각각 리스트에 담아서
  자르면 나오는 길이가지고
  가장 긴 길이 두개 곱하면 가장 큰 색종이 넓이 구할 수 있음 
  &#39;&#39;&#39;
  # 종이의 가로, 세로
  W, H = map(int, input().split())
  # [1] 가능한 가로/세로 자르는 위치를 저장 후 정렬
  w_ls = [0, H]
  h_ls = [0, W]
  N = int(input()) # 잘라야 하는 점선의 개수

  for _ in range(N):
      t, n = map(int, input().split())
      if t == 0:
          w_ls.append(n)
      else:
          h_ls.append(n)
  w_ls.sort()
  h_ls.sort()
  # print(w_ls)
  # [2] 가장 긴 길이 찾기
  w_mx = 0
  for i in range(1, len(w_ls)):
      w_mx = max(w_mx, w_ls[i] - w_ls[i-1])

  h_mx = 0
  for i in range(1, len(h_ls)):
      h_mx = max(h_mx, h_ls[i] - h_ls[i-1])

  print(w_mx*h_mx)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  수_이어가기</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  직사각형_네개의_합집합의_면적_구하기</p>
</li>
<li><p>2669</p>
<pre><code class="language-python">  arr = [[0]*102 for _ in range(102)]
  for _ in range(4):
      a, b, c, d = map(int, input().split())
      for i in range(b, d):
          for j in range(a, c):
              arr[i][j] = 1
  cnt = 0
  for k in range(102):
      for l in range(102):
          if arr[k][l] == 1:
              cnt += 1

  print(cnt)</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  자리배정</p>
</li>
<li><p>10157</p>
<pre><code class="language-python">  C, R = map(int, input().split())
  K = int(input())

  if R*C &lt; K: # 배정이 불가능한 경우 0
      print(0)
  else: # 배정하면서 K가 되면 그 때 좌표 출력
      di, dj = [1, 0, -1, 0], [0, 1, 0, -1]
      # 주변을 1로 둘러싸면 : 범위체크 필요없음
      arr = [[1]*(C+2)] + [[1] + [0]*C + [1] for _ in range(R)] + [[1]*(C+2)]

      ci, cj, dr = 1, 1, 0
      for n in range(1, K):
          arr[ci][cj] = n
          ni, nj = ci + di[dr] , cj + dj[dr]
          if arr[ni][nj] == 0: # 비어있으니 이동가능
              ci, cj = ni, nj
          else:   # 범위밖 또는 이미 채워진경우
              dr = (dr+1)% 4
              ci, cj = ci+di[dr], cj+dj[dr]
      print(f&#39;{cj} {ci}&#39;)</code></pre>
</li>
<li><p><input disabled="" type="checkbox">  개미</p>
</li>
<li><p><input checked="" disabled="" type="checkbox">  방_배정</p>
</li>
<li><p>13300</p>
<pre><code class="language-python">  &#39;&#39;&#39;
  여학생 = 0
  남학생 = 1
  &#39;&#39;&#39;
  def count(arr):
      grade = [0] * 7  # 학년 별로 몇명인지 세보자
      # ls = [] #
      for i in arr:   # 성별로 구분해서 학년만 넣어둔 리스트를 순회하면서
          grade[i] += 1 # 그 학년을 인덱스번호로 활용해서 cnt 증가시켜주기
          # print(grade)
      result = 0 # 방 몇개필요한지 구할 결과값변수 초기화
      for k in grade: # 학년별로 몇명인지 누적해서 구해둔 grade리스트 순회하면서
          if k % K == 0:  # 한방에 배정할 수 있는 최대 인원수로 나눈 값이 딱 떨어지면
              result += k//K  # 그 나눗셈 몫만큼의 방을 더해주면 됨
              # print(result)
          else:   # 안나눠 떨어지면 그 안나눠 떨어진 사람을 위해서
              result += k//K + 1  # 방 하나 추가 배정해 주면 됨
      return result # 누적된 방이 몇 개 필요한지에 대한 result값 반환하기

  # N = 수학여행에 참가하는 학생 수
  # K = 한 방에 배정할 수 있는 최대 인원 수
  N, K = map(int, input().split())
  cnt_S0 = []
  cnt_S1 = []

  for _ in range(N):
      S, Y = map(int, input().split())  # 성별 S / 학년 Y
      # print(S, Y)
      if S == 1: # 성별 1일경우
          # cnt_S1.append([S, Y]) # 의 성별과 학년 넣어주기
          cnt_S1.append(Y) # 아니지, 학년만 넣어주자 성별은 노났으니까
      elif S == 0: # 성별 2일경우
          # cnt_S0.append([S, Y])
          cnt_S0.append(Y)

  a = count(cnt_S1) # 성별 남자일 경우의 필요 방개수
  # print(a)
  b = count(cnt_S0)   # 성별 여자일 경우의 필요한 방개수
  ans = a+b # 더해서 결과값
  print(ans)

  &#39;&#39;&#39;
  print(cnt_S0)
  print(cnt_S1)
  [1, 2, 2, 3, 6, 5] # 성별 여자인 경우의 학년
  [1, 1, 2, 3, 4, 3, 3, 5, 5, 6] # 성별 남자인 경우의 학년&#39;&#39;&#39;</code></pre>
</li>
<li><p><input checked="" disabled="" type="checkbox">  딱지놀이</p>
</li>
<li><p>14696</p>
<pre><code class="language-python">  N = int(input())  # 딱지놀이의 총 라운드 수
  for _ in range(N):
      A = list(input().split())
      B = list(input().split())
      a_len = int(A[0])
      b_len = int(B[0])
      a_ls = A[1:]
      b_ls = B[1:]

      # 인덱스 이용해서 카운트 해주자(1,2,3,4 입력해주기위해서 *5)
      one_cnt = [0] * 5
      two_cnt = [0] * 5

      for i in range(a_len):
          one_cnt[int(a_ls[i])] += 1
      for j in range(b_len):
          two_cnt[int(b_ls[j])] += 1

      # 4,3,2,1 역순 순회하면서 누가 이기는지 판단하기
      result = &#39;&#39;
      for k in range(4, 0, -1):
          if one_cnt[k] &gt; two_cnt[k]:
              result = &#39;A&#39;
              break
          elif one_cnt[k] &lt; two_cnt[k]:
              result = &#39;B&#39;
              break
          else:
              result = &#39;D&#39;
      print(result)</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[State Management]]></title>
            <link>https://velog.io/@turtle_hw/State-Management</link>
            <guid>https://velog.io/@turtle_hw/State-Management</guid>
            <pubDate>Mon, 13 Nov 2023 00:57:08 GMT</pubDate>
            <description><![CDATA[<h1 id="1-state-management">1. State Management</h1>
<blockquote>
<p>상태관리</p>
</blockquote>
<ul>
<li>Vue 컴포넌트는 이미 반응형 상태를 관리하고 있음</li>
<li><strong>상태 === 데이터</strong></li>
</ul>
<h2 id="컴포넌트-구조의-단순화">컴포넌트 구조의 단순화</h2>
<ul>
<li>상태(State) : 앱 구동에 필요한 기본 데이터</li>
<li>뷰(View) : 상태를 선언적으로 매핑하여 시각화</li>
<li>기능(Actions) : 뷰에서 사용자 입려겡 대해 반응적으로 상태를 변경할 수 있게 정의된 동작<blockquote>
<p>&quot; 단방향 데이터 흐름&quot;의 간단한 표현</p>
</blockquote>
</li>
</ul>
<h3 id="상태-관리의-단순성이-무너지는-시점">상태 관리의 단순성이 무너지는 시점</h3>
<ul>
<li><p>여러 컴포넌트가 상태를 공유할 때</p>
<ol>
<li><p>여러 뷰가 동일한 상태에 종속되는 경우</p>
<ul>
<li>공유 상태를 공통 조상 컴포넌트로 &quot;끌어올린&quot; 다음 props로 전달하는 것</li>
<li>하지만 계층 구조가 깊어질 경우 비효율적, 관리가 어려워 짐</li>
</ul>
</li>
<li><p>서로 다른 뷰의 기능이 동일한 상태를 변경시켜야 하는 경우</p>
<ul>
<li>발신(emit)된 이벤트를 통해 상태의 여러 복사본을 변경 및 동기화 하는 것</li>
<li>마찬가지로 관리의 패턴이 깨지기 쉽고 유지 관리할 수 없는 코드가 됨 </li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="해결책">해결책</h3>
<ul>
<li>각 컴포넌트의 공유 상태를 추출하여, 전역에서 참조할 수 있는 저장소에서 관리</li>
<li>컴포넌트 트리는 하나의 큰 &quot;뷰&quot;가 되고 모든 컴포넌트는 트리 계층 구조에 관계 없이 상태에 접근하거나 기능을 사용할 수 있음</li>
<li>Vue의 공식 상태 관리 라이브러리 === <code>&#39;Pinia&#39;</code></li>
</ul>
<hr>
<h1 id="2-state-management-libararypinia">2. State management libarary(Pinia)</h1>
<blockquote>
<p><strong>Vue의 공식 상태 관리 라이브러리</strong></p>
</blockquote>
<h2 id="pinia-구성-요소">Pinia 구성 요소</h2>
<h3 id="1-store">1. store</h3>
<ul>
<li>중앙 저장소</li>
<li>모든 컴포넌트가 공유하는 상태, 기능 등이 작성됨</li>
</ul>
<h3 id="2-state">2. state</h3>
<ul>
<li>반응형 상태(데이터)</li>
<li>ref() === state</li>
</ul>
<h3 id="3-getters">3. getters</h3>
<ul>
<li>계산된 값</li>
<li>computed() === getters</li>
</ul>
<h3 id="4-actions">4. actions</h3>
<ul>
<li>메서드</li>
<li>function() === actions</li>
</ul>
<h3 id="5-plugin">5. plugin</h3>
<ul>
<li>애플리케이션의 상태 관리에 필요한 추가 기능을 제공하거나 확장하는 도구나 모듈</li>
<li>애플리케이션의 상태 관리를 더욱 간편하고 유연하게 만들어주며 패키지 매니저로 설치 이후 별도 설정을 통해 추가됨 </li>
</ul>
<blockquote>
<p>Pinia 구성 요소 종합</p>
</blockquote>
<ul>
<li>Pinia는 store라는 저장소를 가짐</li>
<li>sotre는 state, getters, actions으로 이루어지며 
각각 <strong>ref(), computed(), function()</strong>과 동일함</li>
</ul>
<h2 id="pinia-구성-요소-활용">Pinia 구성 요소 활용</h2>
<h3 id="state">State</h3>
<ul>
<li>store 인스턴스로 state에 접근하여 직접 읽고 쓸 수 있음</li>
<li>만약 store에 state를 정의하지 않았다면 컴포넌트에서 새로 추가할 수 없음</li>
</ul>
<h3 id="getters">Getters</h3>
<ul>
<li>store의 모든 getters를 state처럼 직접 접근 할 수 있음</li>
</ul>
<h3 id="actions">Actions</h3>
<ul>
<li>store의 모든 actions를 직접 접근 및 호출할 수 있음</li>
<li>getters와 달리 state 조작, 비동기, API 호출이나 다른 로직을 진행할 수 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Router]]></title>
            <link>https://velog.io/@turtle_hw/Router</link>
            <guid>https://velog.io/@turtle_hw/Router</guid>
            <pubDate>Thu, 09 Nov 2023 00:01:04 GMT</pubDate>
            <description><![CDATA[<h1 id="1-routing">1. Routing</h1>
<ul>
<li>네트워크에서 경로를 선택하는 프로세스</li>
<li><blockquote>
<p>웹 애플리케이션에서 다른 페이지 간의 전환과 <code>경로</code>를 관리하는 기술</p>
</blockquote>
</li>
</ul>
<h2 id="ssr-에서의-routing">SSR 에서의 Routing</h2>
<ul>
<li>서버가 사용자가 방문한 URL 경로를 기반으로 응답을 전송</li>
<li>링크를 클릭하면 브라우저는 서버로부터 THML 응답을 수신하고 새 HTML로 전체 페이지를 다시 로드</li>
<li>SPA 에서 routing은 브라우저의 클라이언트 측에서 수행</li>
<li>클라이어트 측 JavaScript가 새 데이터를 동적으로 가져와 전체 페이지를 다시 로드하지 않음</li>
<li>페이지는 1개이지만, 링크에 따라 여러 컴포넌트를 렌더링하여 마치 여러 페이지를 사용하는 것처럼 보이도록 해야 함</li>
</ul>
<p><strong>만약 routing이 없다면</strong></p>
<ul>
<li>유저가 URL을 통한 페이지의 변화를 감지할 수 없음</li>
<li>페이지가 무엇을 렌더링 중인지에 대한 상태를 알 수 없음<ul>
<li>URL이 1개이기 때문에 새로 고침 시 처음 페이지로 되돌아감</li>
<li>링크를 공유할 시 첫 페이지만 공유 가능</li>
</ul>
</li>
<li>브라우저의 뒤로 가기 기능을 사용할 수 없음</li>
</ul>
<h1 id="2-vue-router">2. Vue Router</h1>
<blockquote>
<p>Vue  공식 라우터 (The official Router for Vue.js)
<a href="https://router.vuejs.kr/">공식 라우터</a></p>
</blockquote>
<ul>
<li>Vite로 프로젝트 생성 시 Router 추가 </li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/b802d81c-a0fb-4f75-9d7e-007f4326b656/image.png" alt=""></p>
<ul>
<li>서버 실행 후 Router로 인한 프로젝트 변화 확인
<img src="https://velog.velcdn.com/images/turtle_hw/post/81f995a7-d32a-455e-b9ec-5e9ac4dda247/image.png" alt=""></li>
</ul>
<p>-&gt; Home, About 링크에 따라 변경되는 URL과 새로 렌더링 되는 화면
<img src="https://velog.velcdn.com/images/turtle_hw/post/0d2c48fe-21b8-421e-819e-2ac0e99574b5/image.png" alt=""></p>
<h2 id="vue-프로젝트-구조-변화">Vue 프로젝트 구조 변화</h2>
<h3 id="1-appvue-코드-변화">1. App.vue 코드 변화<img src="https://velog.velcdn.com/images/turtle_hw/post/fa38abfd-ce8d-462a-8b17-02ab44365944/image.png" alt=""></h3>
<h3 id="2-router--views-폴더-생성">2. router &amp; views 폴더 생성<img src="https://velog.velcdn.com/images/turtle_hw/post/43a161af-8636-4808-a81f-42ec0cddbebf/image.png" alt=""></h3>
<h2 id="routerlink">RouterLink</h2>
<ul>
<li><p>페이지를 다시 로드하지 않고 RUL을 변경하고 URL 생성 및 관련 로직을 처리 
<img src="https://velog.velcdn.com/images/turtle_hw/post/4bbfd98c-f0f2-46fe-9827-34e84fb3952c/image.png" alt=""></p>
</li>
<li><p>HTML의 a태그를 렌더링</p>
</li>
</ul>
<h2 id="routerview">RouterView</h2>
<ul>
<li>URL 에 해당하는 컴포넌트를 표시(<code>&lt;RouterView /&gt;</code>)</li>
<li>어디에나 배치하여 레이아웃에 맞출 수 있음</li>
</ul>
<h2 id="routerindexjs">router/index.js</h2>
<ul>
<li>라우팅에 관련된 정보 및 설정이 작성 되는 곳</li>
<li>router에 <code>URL(라우트)과 컴포넌트</code>를 매핑(연결)</li>
<li>Django의 urls.py와 유사한 구조를 가지고 있음
  (주소, 이름, 컴포넌트 연결)</li>
</ul>
<h2 id="views">views</h2>
<p>RouterView 위치에 렌더링 할 컴포넌트를 배치
기존 components 폴더와 기능적으로 다른 것은 없으며 단순 분류의 의미로 구성됨
-&gt; 일반 컴포넌트와 구분하기 위해 컴포넌트 이름을 View로 끝나도록 작성하는 것을 권장<img src="https://velog.velcdn.com/images/turtle_hw/post/c4b598e0-3966-4631-8908-e49300dbf14f/image.png" alt=""></p>
<hr>
<h2 id="basic-routing">Basic Routing</h2>
<h2 id="라우팅-기본">라우팅 기본</h2>
<ol>
<li>index.js에 라우터 관련 설정 작성(주소, 이름, 컴포넌트)
<img src="https://velog.velcdn.com/images/turtle_hw/post/fa1dbd1c-ae9a-4767-9fec-524418f12532/image.png" alt=""></li>
</ol>
<pre><code class="language-js">//index.js
const router = createRouter({
    routes: [
      {
          path: &#39;/&#39;,
          name: &#39;home&#39;,
          component: HomeView
        },
        ...
      ]
   })    </code></pre>
<ol start="2">
<li>RouterLink의 <code>to</code>속성으로 index.js에서 정의한 주소 속성 값(path)을 사용</li>
</ol>
<h2 id="named-routes">Named Routes</h2>
<ul>
<li><p>경로에 이름을 지정하는 라우팅</p>
</li>
<li><p>name 속성 값에 경로에 대한 이름을 지정
<img src="https://velog.velcdn.com/images/turtle_hw/post/3fed28e7-5a13-4e6d-b373-19e751b376d3/image.png" alt=""></p>
</li>
<li><p>경로에 연결하려면 RouterLink에 v-bind를 사용해 &#39;to&#39; prop 객체로 전달</p>
</li>
</ul>
<blockquote>
<h3 id="named-routes-장점">Named Routes 장점</h3>
</blockquote>
<ul>
<li>하드코딩 된 URL을 사용하지 않아도 됨</li>
<li>URL 입력 시 오타 방지</li>
</ul>
<hr>
<h2 id="dynamic-route-matching-with-params">Dynamic Route Matching with Params</h2>
<p><strong>매개 변수를 사용한 동적 경로 매칭</strong></p>
<ul>
<li>주어진 패턴 경로를 동일한 컴포넌트에 매핑 해야 하는 경우 활용</li>
<li>예를 들어 모든 사용자의 ID를 활용하여 프로필 페이지 url을 설계 한다면? 일정한 패턴의 URL 작성을 반복해야 함</li>
</ul>
<h2 id="매개-변수를-사용한-동적-경로-매칭-활용">매개 변수를 사용한 동적 경로 매칭 활용</h2>
<ol>
<li><p>UserView 컴포넌트 작성
<img src="https://velog.velcdn.com/images/turtle_hw/post/e917af1b-0a73-4bd4-a086-fc246a4cf75f/image.png" alt=""></p>
</li>
<li><p>UserVies 컴포넌트 라우트 등록</p>
<pre><code class="language-js"> {
   path: &#39;/user/:id&#39;,
   name: &#39;user&#39;,
   component: UserView
 }</code></pre>
</li>
</ol>
<ul>
<li>매개변수는 콜론(:)으로 표기</li>
</ul>
<ol start="3">
<li>App.view에 RouterLink 작성하기 
<img src="https://velog.velcdn.com/images/turtle_hw/post/5b06b0e5-f674-48a3-b435-6df0b7072a98/image.png" alt=""></li>
</ol>
<ol start="3">
<li>라우트의 매개변수는 컴포넌트에서 <code>$route.params</code>로 참조 가능</li>
</ol>
<ul>
<li>다만 다음과 같이 Composition API 방식으로 작성하는 것을 권장
<img src="https://velog.velcdn.com/images/turtle_hw/post/919aa130-5615-4b0b-a6ed-a7a36e9df64a/image.png" alt=""></li>
</ul>
<hr>
<h2 id="programmatic-navigation">Programmatic Navigation</h2>
<blockquote>
<p>프로그래밍 방식 네비게이션 </p>
</blockquote>
<ul>
<li>router의 인스턴스 메서드를 사용해 RouterLink로 a태그를 만드는 것처럼 프로그래밍으로 네비게이션 관련 작업을 수행할 수 있음</li>
</ul>
<ol>
<li>다른 위치로 이동하기 =&gt; router.push()</li>
<li>현재 위치 바꾸기 =&gt; router.replace()</li>
</ol>
<h2 id="routerpush">router.push()</h2>
<ul>
<li>다른 위치로 이동하기 : Navigate to a different location</li>
<li>다른 URL로 이동하는 메서드</li>
<li>새 항목을 history stack에 push하므로 사용자가 브라우저 뒤로 가기 버튼을 클릭하면 이전 URL로 이동할 수 있음</li>
<li>RouterLink를 클릭했을 때 내부적으로 호출되는 메서드이므로 RouterLink를 클릭하는 것은 router.push()를 호출하는 것과 같음
<img src="https://velog.velcdn.com/images/turtle_hw/post/628820f7-631b-4405-8fe4-71d0578d0cfe/image.png" alt=""></li>
</ul>
<h3 id="routerpush활용">router.push()활용</h3>
<ul>
<li>UserView 컴포넌트에서 HomeView 컴포넌트로 이동하는 버튼 만들기<pre><code class="language-js">import { userRoute, useRouter } from &#39;vue-router&#39;
</code></pre>
</li>
</ul>
<p>const router = useRouter()</p>
<p>const goHome = function() {
     router.push({ name: &#39;home&#39; })
 }</p>
<pre><code>참고 : https://router.vuejs.org/guide/essentials/navigation.html

``` jsx
// literal string path
router.push(&#39;/users/alice&#39;)

//object with path
router.push({ path: &#39;/users/alice&#39; })

//named route with params to let the router build the url
router.push({ name: &#39;user&#39;, params: { username: &#39;alice&#39; } })

//with query, resulting in /register?plan=private
router.push({ path: &#39;/register&#39;, query: {plan: &#39;private&#39; } })
</code></pre><h2 id="routerrelace">router.relace()</h2>
<ul>
<li>현재 위치 바꾸기 : Replace current location</li>
<li>push 메서드와 달리 history stack 에 새로운 항목을 push하지 않고 다른 URL로 이동 (=== 이동 전 URL로 뒤로 가기 불가)
<img src="https://velog.velcdn.com/images/turtle_hw/post/ba639d2c-3e72-4cd0-9391-fd9e6ede189e/image.png" alt=""></li>
</ul>
<h1 id="3-navigation-guard">3. Navigation Guard</h1>
<blockquote>
<p>Vue router를 통해 특정 URL에 접근할 때 다른 URL로 redirect를 하거나 취소하여 네비게이션을 보호
<strong>ex)</strong> 인증 정보가 없으면 특정 페이지에 접근하지 못하게 함</p>
</blockquote>
<h2 id="종류">종류</h2>
<blockquote>
</blockquote>
<h3 id="1-globally-전역-가드">1. Globally (전역 가드)</h3>
<ul>
<li>애플리케이션 전역에서 동작</li>
<li>index.js에서 정의</li>
</ul>
<h2 id="routerbeforeeach">router.beforeEach()</h2>
<ul>
<li>다른 URL로 <code>이동하기 직전</code>에 실행되는 함수</li>
<li>Global Before Guards</li>
</ul>
<h3 id="routerbeforeeach-구조">router.beforeEach 구조</h3>
<blockquote>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/bc4fedbd-913f-4ab7-b7eb-a06382d0d389/image.png" alt=""></p>
<ul>
<li>to : 이동할 URL 정보가 담긴 Route 객체</li>
<li>from : 현재 RUL 정보가 담긴 Route 객체</li>
<li>선택적 반환(return) 값<ol>
<li><strong>false</strong></li>
<li><strong>Route Locaion</strong></li>
</ol>
</li>
</ul>
</blockquote>
<p>__false __
    - 현재 내비게이션을 취소
    - 브라우저 URL이 변경된 경우(사용자가 수동으로 또는 뒤로 버튼을 통해) from 경로의 URL로 재설정</p>
<p><strong>Route Lacation</strong></p>
<ul>
<li>router.push()를 호출하는 것처럼 경로 위치를 전달하여 다른 위치로 redirect
=&gt; return이 없다면 &#39;to&#39; URL Route 객체로 이동</li>
</ul>
<h3 id="routerbeforeeach-예시">router.beforeEach 예시</h3>
<ol>
<li>전역 가드 beforeEach 작성</li>
<li>HomeView에서 UserView로 이동 후 각 인자 값 출력 확인하기 </li>
</ol>
<ul>
<li>to 에는 이동할 URL인 user 라우트에 대한 정보가, 
from에는 현재 URL인 home 라우트에 대한 정보가 들어있음</li>
</ul>
<h3 id="routerbeforeeach-활용">router.beforeEach 활용</h3>
<ul>
<li>사전 준비 : LoginView 컴포넌트 작성 및 라우트 등록
<img src="https://velog.velcdn.com/images/turtle_hw/post/bbe17fb4-c101-44b8-a7a2-7224c763e469/image.png" alt=""><img src="https://velog.velcdn.com/images/turtle_hw/post/05bd7a41-22cb-4c6e-b103-28c09da9753e/image.png" alt=""></li>
</ul>
<ul>
<li>&quot;Login이 되어있지 않다면 페이지 진입을 막고 Login 페이지로 이동시키기&quot;</li>
<li><blockquote>
<p>어떤 RouterLink를 클릭해도 LoginView 컴포넌트만 볼 수 있음</p>
</blockquote>
</li>
<li>만약 로그인이 되어있지 않고(1), 이동하는 주소 이름이  login이 아니라면(2) login 페이지로 redirect<img src="https://velog.velcdn.com/images/turtle_hw/post/87251db7-a732-4273-b125-855aaa36d8d7/image.png" alt=""></li>
</ul>
<blockquote>
</blockquote>
<h3 id="2-per-route-라우터-가드">2. Per-route (라우터 가드)</h3>
<ul>
<li>특정 route 에서만 동작</li>
<li>index.js의 각 routes에 정의</li>
</ul>
<h2 id="routerbeforeenter">router.beforeEnter()</h2>
<ul>
<li>route에 <code>진입했을 때만</code> 실행되는 함수</li>
<li>매개변수, 쿼리 값이 변경될 때는 실행되지 않고 다른 경로에서 탐색할 때만 실행됨</li>
</ul>
<h3 id="routerbeforeenter-구조">router.beforeEnter 구조</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/1eb6feca-0e3e-4a39-80b4-8d30705e3bcd/image.png" alt=""></p>
<ul>
<li>routes 객체에서 정의</li>
<li>함수의 to, from, 선택 반환인자는 beforeEach와 동일</li>
</ul>
<h3 id="routerbeforeenter-예시">router.beforeEnter 예시</h3>
<ol>
<li>라우터 가드 beforeEnter 작성</li>
<li>HomeView에서 UserView로 이동 후 각 인자 값 출력 확인하기</li>
</ol>
<ul>
<li>to 에는 이동할 URL인 user 라우트에 대한 정보가, from 에는 현재 URL인 home 라우트에 대한 정보가 들어있음</li>
<li>다른 경로에서 user 라우트를 탐색했을 때 실행된 것
<img src="https://velog.velcdn.com/images/turtle_hw/post/445eb757-9f72-4779-875e-f42841740506/image.png" alt=""></li>
</ul>
<h3 id="routerbeforeenter-활용">router.beforeEnter 활용</h3>
<p>&quot;이미 로그인 한 상태라면 LoginView 진입을 막고 HomeView로 이동 시키기&quot; (전역 가드 활용 코드는 주석 처리 후 진행)</p>
<ul>
<li>이미 로그인 상태라면 HomeView로 이동</li>
<li>로그인 상태가 아니라면 LoginView로 이동
<img src="https://velog.velcdn.com/images/turtle_hw/post/d98a5004-6814-40fd-8cba-18c1e47122cd/image.png" alt=""></li>
</ul>
<blockquote>
</blockquote>
<h3 id="3-in-component-컴포넌트-가드">3. In-component (컴포넌트 가드)</h3>
<ul>
<li>특정 컴포넌트 내에서만 동작</li>
<li>컴포넌트 Script에 정의</li>
</ul>
<h2 id="in-component-guard">In-component Guard</h2>
<h3 id="onbeforerouteleave">onBeforeRouteLeave</h3>
<ul>
<li>현재 라우트에서 다른 라우트로 이동하기 전에 실행</li>
<li>사용자가 <code>현재 페이지</code>를 <code>떠나는</code> 동작에 대한 로직을 처리</li>
</ul>
<p><strong>사용자가 UserView를 떠날 시 팝업 창 출력하기</strong>
<img src="https://velog.velcdn.com/images/turtle_hw/post/f0a206a8-240b-49a3-ad1d-a7eeb84c717e/image.png" alt=""></p>
<pre><code class="language-js">// UserView.vue
import {onBeforeRouteLeave} from &#39;vue-router&#39;

onBeforeRouteLeave((to, from) =&gt; {
   const answer = window.confirm(&#39;정말 떠나실 건가요?&#39;)
     if (answer === false) {
         return false
     }
 })</code></pre>
<h3 id="onbeforerouteupdate">onBeforeRouteUpdate</h3>
<ul>
<li>이미 렌더링된 컴포넌트가 <code>같은 라우트</code> 내에서 업데이트 되기 전에 실행</li>
<li>라우트 업데이트 시 추가적인 로직을 처리</li>
<li>UserView 페이지에서 다른 id를 가진 User의 Userview 페이지로 이동하기
<img src="https://velog.velcdn.com/images/turtle_hw/post/b09be667-17e0-422a-87a0-12476941db10/image.png" alt=""></li>
</ul>
<pre><code class="language-jsx">import { onBeforeRouteUpdate } from &#39;vue-router&#39;
&lt;button @click=&quot;routeUpdate&quot;&gt;100번 유저 페이지&lt;/button&gt;

const routeUpdate = function() {
   router.push({name:&#39;user&#39;, params: {id: 100} })
}

onBeforeRouteUpdate((to, from) =&gt; {
   userId.value = to.params.id
})</code></pre>
<blockquote>
<h3 id="만약-onbeforerouteupdate-를-사용하지-않았다면">만약 onBeforeRouteUpdate 를 사용하지 않았다면</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/56c9b995-2e51-48a1-a68f-567b2b7763ab/image.png" alt=""></p>
</blockquote>
<ul>
<li>onBeforeRouteUpdate에서 userId를 변경하지 않으면 userId는 갱신되지 않음</li>
<li>컴포넌트가 재사용되었기 때문</li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<h2 id="lazy-loading-routes">Lazy Loading Routes<img src="https://velog.velcdn.com/images/turtle_hw/post/85343f5d-dac4-46cd-9d12-cdcd5f4e5720/image.png" alt=""></h2>
<ul>
<li>첫 빌드 시 해당 컴포넌트를 로드 하지 않고,</li>
<li><em><code>해당 경로를 처음으로 방문할 때만 컴포넌트를 로드</code>*</em> 하는 것<ul>
<li>앱을 빌드할 때 앱의 크기에 따라 페이지 로드 시간이 길어질 수 있기 때문</li>
</ul>
</li>
<li>기존에 “정적 가져오기 방식” 을 “동적 가져오기 방식” 으로 변경과 같음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Component State Flow]]></title>
            <link>https://velog.io/@turtle_hw/Component-State-Flow</link>
            <guid>https://velog.io/@turtle_hw/Component-State-Flow</guid>
            <pubDate>Wed, 08 Nov 2023 01:53:58 GMT</pubDate>
            <description><![CDATA[<h1 id="1-passing-props">1. Passing Props</h1>
<ul>
<li>동일한 사진 데이터가 한 화면에 다양한 위치에서 여러 번 출력되고 있음</li>
<li>하지만 해당 페이지를 구성하는 컴포넌트가 여러 개라면 각 컴포넌트가 개별적으로 동일한 데이터를 관리해야 할까?</li>
<li>그렇다면 사진을 변경해야 할 대 모든 커모넌트에 대해 변경 요청을 해야 함</li>
<li><blockquote>
<p>공통된 부모 컴포넌트에서 관리하자
<img src="https://velog.velcdn.com/images/turtle_hw/post/d142097d-7ceb-4049-96d2-e85dc24f7df7/image.png" alt=""> 부모는 자식에게 데이터를 전달(Pass Props)하며, 자식은 자신에게 <code>일어난 일</code>을 부모에게 <code>알림</code>(Emit event) - 직접적으로 전달하는 것은 아님!</p>
</blockquote>
</li>
</ul>
<h2 id="props">Props</h2>
<ul>
<li>부모 컴포넌트로부터 자식 컴포넌트로 데이터를 전달하는데 사용되는 속성</li>
</ul>
<h2 id="one-way-data-flow">One-Way Data Flow</h2>
<ul>
<li>모든 props는 자식 속성과 부모 속성 사이에 <code>하향식 단방향 바인딩</code>을 형성(one-way-down binding)</li>
</ul>
<h3 id="props-특징">Props 특징</h3>
<ul>
<li>부모 속성이 업데이트 되면 자식으로 흐르지만 그 반대는 안됨</li>
<li>즉, 자식 컴포넌트 내부에서 props를 <code>변경하려고 시도해서는 안되며</code> 불가능</li>
<li>또한, 부모 컴포넌트가 업데이트될 때마다 자식 컴포넌트의 모든 props가 최신 값으로 업데이트 됨</li>
<li><blockquote>
<p>부모 컴포넌트에서만 변경하고 이를 내려 받는 자식 컴포넌트는 자연스럽게 갱신</p>
</blockquote>
</li>
</ul>
<p><strong>단방향인 이유</strong></p>
<ul>
<li>하위 컴포넌트가 실수로 상위 컴포넌트의 상태를 변경하여 앱에서의 데이터 흐름을 이해하기 어렵게 만드는 것을 방지하기 위함</li>
</ul>
<blockquote>
<h2 id="사전준비">사전준비</h2>
</blockquote>
<ol>
<li>vue 프로젝트 생성</li>
<li>초기 생성된 컴포넌트 모두 삭제(App.vue제외)</li>
<li>src/assets 내부 파일 모두 삭제</li>
<li>main.js 해당 코드 삭제<pre><code class="language-js">import &#39;./assets/main.css&#39; // 삭제</code></pre>
</li>
</ol>
<h3 id="app--parent--parentchild-컴포넌트-관계-작성">APP &gt; Parent &gt; ParentChild 컴포넌트 관계 작성</h3>
<table>
<thead>
<tr>
<th>1. App 컴포넌트 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/c9af3d5b-b8c4-469f-ab54-de8b26822b89/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>2. Parent 컴포넌트 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b2c6c63d-94af-42b5-8953-590bcdb14c56/image.png" alt=""></td>
</tr>
</tbody></table>
<ol start="3">
<li><p>ParentChild 컴포넌트 작성</p>
<pre><code>&lt;template&gt;
&lt;div&gt;

&lt;/div&gt;
&lt;/template&gt;
</code></pre></li>
</ol>
<script setup>

</script>

<style scoped>

</style>
<pre><code>---

## Props 선언
- 부모 컴포넌트에서 보낸 props를 사용하기 위해서는 자식 컴포넌트에서 명시적인 props 선언이 필요

### Props 작성
&gt; 부모 컴포넌트 Parent에서 자식 컴포넌트 ParentChild에 보낼 props 작성![](https://velog.velcdn.com/images/turtle_hw/post/4bac0b71-d69d-4ba4-b7c2-168edbeaf458/image.png)![](https://velog.velcdn.com/images/turtle_hw/post/19d30105-204c-4bb6-b5d1-99f4a6beaa95/image.png)




## Props 선언 2가지 방식
### 1. 문자열 배열을 사용한 선언
- defineProps()를 사용하여 props 를 선언
![](https://velog.velcdn.com/images/turtle_hw/post/1df6b701-605b-479c-b0ca-4531b23410e3/image.png)



### 2. 객체를 사용한 선언
- 객체 선언 문법의 각 객체 속성의 키는 props의 이름이 되며, 객체 속성의 값은 값이 될 데이터의 타입에 해당하는 생성자 함수(Number, String..)여야 함
- 객체 선언 문법 사용 권장
![](https://velog.velcdn.com/images/turtle_hw/post/0eb80810-35ed-4360-bd47-1d9173a6058b/image.png)


---

## prop 데이터 사용
- 템플릿에서 반응형 변수와 같은 방식으로 활용
![](https://velog.velcdn.com/images/turtle_hw/post/d9e4ec10-21f5-4278-a0f0-ff3c94589939/image.png)

- props를 객체로 반환하므로 필요한 경우 JavaScript 에서 접근 가능
![](https://velog.velcdn.com/images/turtle_hw/post/10f5e387-9cab-4c92-9abf-0b9ce0eb9a96/image.png)


### 한 단계 더 prop 내려 보내기 
- ParentChild 컴포넌트를 부모로 갖는 ParentGrandChild 컴포넌트 생성 및 등록
```jsx
&lt;template&gt;
  &lt;div&gt;
    {{ myMsg }}
    &lt;ParentGrandChild my-msg=&quot;message&quot; /&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import ParentGrandChild from &#39;@/components/ParentGrandChild.vue&#39;
&lt;/script&gt;</code></pre><p><img src="https://velog.velcdn.com/images/turtle_hw/post/a2717ba5-19d0-47f2-88bd-5955d64e3817/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>ParentChild 컴포넌트에서 Parent로부터 받은 prop인 myMsg를 ParentGrnadChild에게 전달</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/00cf420c-ff87-41f1-b111-3a6fed5ff010/image.png" alt=""></td>
</tr>
</tbody></table>
<pre><code>&lt;template&gt;
  &lt;div&gt;
    &lt;p&gt; {{ myMsg }}&lt;/p&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
defineProps({
  myMsg: String,
})

&lt;/script&gt;

&lt;style scoped&gt;

&lt;/style&gt;</code></pre><hr>
<h2 id="props-세부사항">Props 세부사항</h2>
<h3 id="1-props-name-casingprops-이름-컨벤션">1. Props Name Casing(Props 이름 컨벤션)</h3>
<ul>
<li>선언 및 템플릿 참조 시 =&gt; camelCase
<img src="https://velog.velcdn.com/images/turtle_hw/post/c24dc657-3cc6-4498-bbf2-cb744e772e1b/image.png" alt=""></li>
</ul>
<table>
<thead>
<tr>
<th>자식 컴포넌트로 전달 시 =&gt; kebab-case</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/26c7b720-e675-4ceb-b7d1-3150628804de/image.png" alt=""></td>
</tr>
</tbody></table>
<p>-&gt; 기술적으로 camelCase도 가능하나 HTML 속성 표기법과 동일하게 kebab-case로 표기할 것을 권장</p>
<h3 id="2-static-props--dynamic-props">2. Static Props &amp; Dynamic Props</h3>
<ul>
<li>지금까지 작성한 것은 Static(정적) props</li>
<li>v-bind 를 사용하여 동적으로 할당된 props를 사용할 수 있음</li>
</ul>
<ol>
<li><p>Dynamic props 정의
<img src="https://velog.velcdn.com/images/turtle_hw/post/f31223c2-61e0-410e-a82b-bd11810008b3/image.png" alt=""></p>
</li>
<li><p>Dynamic props 선언 및 출력
<img src="https://velog.velcdn.com/images/turtle_hw/post/ad7152d7-486e-4ef8-9c54-6f06fc42354e/image.png" alt=""></p>
</li>
</ol>
<hr>
<h1 id="2-component-events">2. Component Events</h1>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/5afa8a27-4b6a-485a-bed5-6a59eae8fa1d/image.png" alt=""></p>
<p>💡 부모는 자식에게 데이터를 전달(Pass Props)하며, 자식은 자신에게 일어난 일을 부모에게 알림(Emit event) 
<code>부모가 prop 데이터를 변경하도록 소리쳐야 한다</code></p>
<h2 id="emit">$emit()</h2>
<ul>
<li>자식 컴포넌트가 이벤트를 발생시켜 부모 컴포넌트로 데이터를 전달하는 역할의 메서드</li>
<li><strong><code>$</code></strong> 표기는 Vue 인스턴스나 컴포넌트 내에서 제공되는 전역 속성이나 메서드를 식별하기 위한 접두어</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/3b844639-8788-454c-b93f-51e88cb6a27d/image.png" alt=""></p>
<ul>
<li>event<ul>
<li>커스텀 이벤트 <code>이름</code> -&gt; 부모가 캐치</li>
</ul>
</li>
<li>args<ul>
<li><code>추가 인자</code></li>
</ul>
</li>
</ul>
<h2 id="event-발신-및-수신emitting-and-listening-to-events">Event 발신 및 수신(Emitting and Listening to Events)</h2>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/4f64dceb-92a4-4962-a8ca-485109522f95/image.png" alt=""></p>
<ul>
<li><p>$emit을 사용하여 템플릿 표현식에서 직접 사용자 정의 이벤트를 발신</p>
<pre><code class="language-js">&lt;button @click=$emit(&#39;someEvent&#39;)&quot;&gt; 클릭 &lt;/button&gt;</code></pre>
</li>
<li><p>그러면 부모는 v-on을 사용하여 수신할 수 있음</p>
<pre><code class="language-js">&lt;ParentComp @some-event=&quot;someCallback&quot; /&gt;</code></pre>
</li>
</ul>
<h3 id="이벤트-발신-및-수신하기">이벤트 발신 및 수신하기</h3>
<ul>
<li>ParentChild 에서 someEvent 라는 이름의 사용자 정의 이벤트를 발신</li>
</ul>
<pre><code class="language-jsx">&lt;button @click=&quot;$emit(&#39;someEvent&#39;)&quot;&gt;클릭&lt;/button&gt;</code></pre>
<ul>
<li>ParentChild의 부모 Parent는 <code>v-on</code>을 사용하여 발신된 이벤트를 수신</li>
<li>수신 후 처리할 로직 및 콜백함수 호출
<img src="https://velog.velcdn.com/images/turtle_hw/post/9fb5ba25-37f3-4b98-b120-f8ab8865e940/image.png" alt=""></li>
</ul>
<h2 id="emit-이벤트-선언">emit 이벤트 선언</h2>
<ul>
<li>defineEmits() 를 사용하여 명시적으로 발신할 이벤트를 선언할 수 있음</li>
<li>script 에서 $meit 메서드를 접근할 수 없기 때문에 defineEmits() 는 $emit 대신 사용할 수 있는 동등한 함수를 반환</li>
</ul>
<pre><code class="language-jsx">&lt;script setup&gt;
const emit = defineEmits([&#39;someEvent&#39;, &#39;myFocus&#39;])
const buttonClick = function () {
    emit(&#39;someEvent&#39;)
}
&lt;/script&gt;</code></pre>
<h2 id="이벤트-선언하기">이벤트 선언하기</h2>
<p>이벤트 선언 방식으로 추가 버튼 작성 및 결과 확인
<img src="https://velog.velcdn.com/images/turtle_hw/post/99d59497-c626-43e4-a125-65e2f28fd43b/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/60041007-72db-4d99-a045-ce5ace1c0023/image.png" alt=""></p>
<pre><code class="language-js">&lt;!-- ParentChild.vue --&gt;
&lt;script setup&gt;
const emit = defineEmits([&#39;someEvent&#39;])
const buttonClick = function () {
    emit(&#39;someEvent&#39;)
}
&lt;/script&gt;

&lt;button @click=&quot;buttonClick&quot;&gt;클릭&lt;/button&gt;</code></pre>
<hr>
<h2 id="event-인자">Event 인자</h2>
<ul>
<li>이벤트 발신 시 추가 인자를 전달하여 값을 제공할 수 있음<h3 id="이벤트인자-전달하기">이벤트인자 전달하기</h3>
ParentChild에서 이벤트를 발신하여 Parent로 추가 인자 전달하기<pre><code>&lt;!-- ParentChild.vue --&gt;
const emit = defineEmits([&#39;someEvent&#39;, &#39;emitArgs&#39;])
const emitArgs= function () {
  emit(&#39;emitArgs&#39;,1,2,3)
}
</code></pre></li>
</ul>
<p>&lt;button @click=&quot;emitArgs&quot;&gt;추가 인자 전달</button></p>
<pre><code>ParentChild에서 발신한 이벤트를 Parent에서 수신</code></pre><!-- Parent.vue -->
<p>&lt;ParentChild
  @some-event=&quot;someCallback&quot;
  @emit-args=&quot;getNumbers&quot;
  my-msg=&quot;message&quot;
  :dynamic-props=&quot;name&quot;
/&gt;</p>
<p>const getNumbers=function (...args) {
  console.log(args)
  console.log(<code>ParentChild가 전달한 추가인자 ${args}를 수신했어요</code>)
}</p>
<pre><code>Event 세부사항
----------

### Event Name Casing

*   선언 및 발신 시 ( -&gt; camelCase)
![](https://velog.velcdn.com/images/turtle_hw/post/b6a4734a-6f09-4a8e-980e-8b49a9cc6e50/image.png)

*   부모 컴포넌트로 수신 시 ( -&gt; kebab-case)
![](https://velog.velcdn.com/images/turtle_hw/post/865f83b4-16fc-4c95-bb00-aabe09f42cf5/image.png)

---

### emit 이벤트 실습

&gt; 최하단 컴포넌트 ParentGrandChild에서 Parent 컴포넌트의 name 변수 변경 요청하기
![](https://velog.velcdn.com/images/turtle_hw/post/5f8f85a2-b224-4c74-a547-a4074451e486/image.png)

---

- ParentGrandChild에서 이름 변경을 요청하는 이벤트 발신
![](https://velog.velcdn.com/images/turtle_hw/post/a5cfbfcb-7c57-408e-a897-efc11a252faa/image.png)
![](https://velog.velcdn.com/images/turtle_hw/post/b5df862c-2418-4a5f-b6a8-6a2390a0d57f/image.png)

---

- 이벤트 수신 후 이름 변경을 요청하는 이벤트 발신
![](https://velog.velcdn.com/images/turtle_hw/post/d648e12b-1925-4e0a-b6dd-759a8d965f98/image.png)

---


- 이벤트 수신 후 이름 변수 변경 메서드 호출
- 해당 변수를 prop 으로 받는 모든 곳에서 자동 업데이트
![](https://velog.velcdn.com/images/turtle_hw/post/e9470b7b-e629-415b-80e1-47e829edca6d/image.png)
```js
const updateName = function() {
  name.value = &#39;Bella&#39;
}</code></pre><h1 id="참고">참고</h1>
<h2 id="정적--동적-props-주의사항">정적 &amp; 동적 props 주의사항</h2>
<blockquote>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/f60413f5-2e38-491f-8b86-2aae7e65e7bd/image.png" alt=""></p>
<ul>
<li>첫 번째는 정적 props로 문자열로써의 &quot;1&quot;을 전달</li>
</ul>
</blockquote>
<ul>
<li>두 번째는 동적 props로 숫자로써의 1을 전달</li>
</ul>
<h3 id="prop-선언을-객체-선언-문법으로-권장하는-이유">Prop 선언을 객체 선언 문법으로 권장하는 이유</h3>
<ul>
<li>prop에 타입을 지정하는 것은 컴포넌트를 가독성이 좋게 문서화하는데 도움이 되며, 다른 개발자가 잘못된 유형을 전달할 때에 브라우저 콘솔에 경고를 출력하도록 함</li>
<li>추가로 prop에 대한 <strong>유효성 검사</strong> 로써 활용 가능  <a href="https://vuejs.org/guide/components/props.html#prop-validation">https://vuejs.org/guide/components/props.html#prop-validation</a></li>
</ul>
<h3 id="emit-이벤트도-객체-선언-문법으로-작성-가능">emit 이벤트도 객체 선언 문법으로 작성 가능</h3>
<hr>
<ul>
<li>props 타입 유효성 검사와 유사하게 emit 이벤트 또한 객체 구문으로 선언 된 경우 유효성을 검사할 수 있음</li>
<li><a href="https://vuejs.org/guide/components/events.html#events-validation">https://vuejs.org/guide/components/events.html#events-validation</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Basic Syntax(2)]]></title>
            <link>https://velog.io/@turtle_hw/Basic-Syntax-02</link>
            <guid>https://velog.io/@turtle_hw/Basic-Syntax-02</guid>
            <pubDate>Mon, 06 Nov 2023 02:58:17 GMT</pubDate>
            <description><![CDATA[<h1 id="1-computed-property">1. Computed Property</h1>
<h2 id="computed">computed()</h2>
<ul>
<li><p>계산된 속성을 정의하는 함수</p>
</li>
<li><p>미리 계산된 속성을 사용하여 템플릿에서 표현식을 단순하게 하고 불필요한 반복 연산을 줄임</p>
</li>
<li><p>computed 기본 예시, 적용</p>
</li>
</ul>
<pre><code>&lt;body&gt;
      &lt;div id=&quot;app&quot;&gt;
        &lt;h2&gt;남은 할 일&lt;/h2&gt;
            // 1번째 방법
        &lt;p&gt;{{ restOfTodos }}&lt;/p&gt;
            // 메서드 활용방법
        &lt;p&gt; {{ getRestofTodos() }}&lt;/p&gt;
      &lt;/div&gt;

      &lt;script src=&quot;&lt;https://unpkg.com/vue@3/dist/vue.global.js&gt;&quot;&gt;&lt;/script&gt;
      &lt;script&gt;
    // computed 적용
        const { createApp, ref, computed } = Vue

        const app = createApp({
          setup() {
          // 할 일이 남았는지 여부에 따라 다른 메시지 출력하기
            const todos = ref([
              { text: &#39;Vue 실습&#39; },
              { text: &#39;자격증 공부&#39; },
              { text: &#39;TIL 작성&#39; }
            ])
            const restOfTodos = computed(() =&gt; {
              return todos.value.length &gt; 0 ? &#39;아직 남았다&#39; : &#39;퇴근!&#39;
            })

            const getRestofTodos = function () {
              return todos.value.length &gt; 0 ? &#39;아직 남았다&#39; : &#39;퇴근!&#39;
            }

            return {
              todos,
              restOfTodos,
              getRestofTodos
            }
          }
        })

        app.mount(&#39;#app&#39;)
      &lt;/script&gt;
    &lt;/body&gt;</code></pre><ul>
<li>반응성 데이터를 포함하는 복잡한 로직의 경우 computed를 활용하여 미리 값을 계산</li>
</ul>
<h3 id="computed-특징">computed 특징</h3>
<ul>
<li>반환되는 값은 computed ref 이며 일반 refs와 유사하게 계산된 결과를 .value로 참조할 수 있음(템플릿에서는 자동으로 wrapping 되기 때문에 .value 생략 가능)</li>
<li>computed 속성은 의존된 반응형 데이터를 자동으로 추적</li>
<li>의존하는 데이터가 변경될 때만 재평가<ul>
<li>restOftodos의 계산은 todos에 의존하고 있음</li>
<li>따라서 todos가 변경될 때만 resOftodos가 업데이트 됨
<img src="https://velog.velcdn.com/images/turtle_hw/post/6f786049-0e85-45ce-9cd0-8fdecb6dc244/image.png" alt=""></li>
</ul>
</li>
</ul>
<h2 id="computed-vs-methods">Computed vs Methods</h2>
<blockquote>
<p>computed  속성 대신 method 로도 동일한 기능을 정의할 수 있음</p>
</blockquote>
<ul>
<li>두 가지 접근 방식은 실제로 완전히 동일
<img src="https://velog.velcdn.com/images/turtle_hw/post/a3f0a0eb-bcf5-4797-9b6d-9b59e9ae1e6b/image.png" alt=""></li>
</ul>
<h3 id="computed-와-method의-차이">computed 와 method의 차이</h3>
<ul>
<li>computed 속성은 의존된 반응형 데이터를 기반으로 캐시 된다. ( 매번 재평가하지 않는다)</li>
<li>의존하는 데이터가 변경된 경우에만 재평가됨</li>
<li>즉, 의존된 반응형 데이터가 변경되지 않는 한 이미 계산된 결과에 대한 여러 참조는 다시 평가할 필요 없이 이전에 계산된 결과를 즉시 반환</li>
<li>💡 반면, method 호출은 다시 렌더링이 발생할 때마다 항상 함수를 실행</li>
</ul>
<blockquote>
<p><strong>캐시(Cache)</strong></p>
</blockquote>
<ul>
<li>데이터나 결과를 일시적으로 저장해두는 임시 저장소</li>
<li>이후에 같은 데이터나 결과를 다시 계산하지 않고 빠르게 접근할 수 있도록 함
ex. 웹 페이지의 캐시 데이터 -&gt; 페이지 일부 데이터를 브라우저 캐시에 저장 후 같은 페이지에 다시 요청 시 모든 데이터를 다시 응답 받는 것이 아닌 캐시 된 데이터를 사용하여 더 빠르게 웹 페이지를 렌더링</li>
</ul>
<h3 id="computed-와-method-의-적절한-사용처">computed 와 method 의 적절한 사용처</h3>
<p><strong>computed</strong></p>
<ul>
<li>의존하는 데이터에 따라 결과가 바뀌는 계산된 속성을 만들 때 유용</li>
<li>동일한 의존성을 가진 여러 곳에서 사용할 때 계산 결과를 캐싱하여 중복 계산 방지<blockquote>
<p>의존된 데이터가 변경되면 자동으로 업데이트 </p>
</blockquote>
</li>
</ul>
<p><strong>method</strong></p>
<ul>
<li>단순히 특정 동작을 수행하는 함수를 정의할 때 사용</li>
<li>데이터에 의존하는지 여부와 관계없이 항상 동일한 결과를 반환하는 함수 <blockquote>
<p>호출해야만 실행됨
💡 무조건 computed만 사용하는 것이 아니라 사용목적과 상황에 맞게 computed와 method를 적절히 조합하여 사용</p>
</blockquote>
</li>
</ul>
<hr>
<h1 id="2-conditional-rendering">2. Conditional Rendering</h1>
<h2 id="conditional-rendering">Conditional Rendering</h2>
<h2 id="v-if">v-if</h2>
<ul>
<li><p>표현식의 T/F를 기반으로 요소를 조건부로 렌더링</p>
</li>
<li><p>&#39;v-else&#39; directive를 사용하여 v-if 에 대한 else 블록을 나타낼 수 있음</p>
<pre><code class="language-js">  const app = createApp({
    setup() {
      const isSeen = ref(true)

      return {
        isSeen,
      }
    }
  })</code></pre>
</li>
</ul>
<pre><code class="language-js">   &lt;!-- if else --&gt;
    &lt;p v-if=&quot;isSeen&quot;&gt;true일때 보여요&lt;/p&gt;
    &lt;p v-else&gt;false일때 보여요&lt;/p&gt;
    &lt;button @click=&quot;isSeen = !isSeen&quot;&gt;토글&lt;/button&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/38243a43-2eaa-413c-adab-d00f5d46f16a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/20d49e9e-6bb9-47aa-a880-9350edd7a1a4/image.png" alt=""></p>
<ul>
<li>다른 것들은 아예 렌더링도 되지 않았음을 볼 수 있음</li>
</ul>
<pre><code class="language-js">&lt;!-- else if --&gt;
    &lt;div v-if=&quot;name === &#39;Alice&#39;&quot;&gt;Alice입니다&lt;/div&gt;
    &lt;div v-else-if=&quot;name === &#39;Bella&#39;&quot;&gt;Bella입니다&lt;/div&gt;
    &lt;div v-else-if=&quot;name === &#39;Cathy&#39;&quot;&gt;Cathy입니다&lt;/div&gt;
    &lt;div v-else&gt;아무도 아닙니다.&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/e2b28293-0072-4613-88df-743d461f5cc6/image.png" alt=""></p>
<ul>
<li>다른 것들은 아예 렌더링도 되지 않았음을 볼 수 있음</li>
</ul>
<hr>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/e0b88c58-c33a-473c-b4b6-41be7d2bfc6f/image.png" alt="">
<strong>HTML <code>&lt;template&gt;</code> element</strong></p>
<ul>
<li>페이지가 로드될 때 렌더링 되지 않지만 JavaScript를 사용하여 나중에 문서에서 사용할 수 있도록 하는 HTML을 보유하기 위한 메커니즘</li>
<li>보이지 않는 wraaper 역할</li>
</ul>
<hr>
<h2 id="v-if-vs-v-show">v-if vs v-show</h2>
<ul>
<li>둘다 조건부 렌더링이라는 공통점!</li>
<li><em>v-show*</em></li>
<li>표현식 값의 T/F를 기반으로 요소의 가시성(visibility)을 전환</li>
</ul>
<pre><code class="language-js">    &lt;!-- v-show --&gt;
    &lt;div v-show=&quot;isShow&quot;&gt;v-show&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/4fc10d09-dafd-4daf-bb47-012b53f0fee0/image.png" alt=""></p>
<blockquote>
<p>v-show는 <code>display: none</code> 으로 렌더링은 한다!!</p>
</blockquote>
<blockquote>
<p><strong>v-if(Cheap initial load, expensive toggle)</strong></p>
</blockquote>
<ul>
<li>초기 조건이 false인 경우 아무 작업도 수행하지 않음</li>
<li>토글 비용이 높음</li>
</ul>
<blockquote>
<p><strong>v-show(Expensive initial load, cheap toggle)</strong></p>
</blockquote>
<ul>
<li>초기 조건에 관게 없이 항상 렌더링</li>
<li>초기 렌더링 비용이 더 높음</li>
<li>토글이 되어있는 상태에서는 싸게 먹힌다<blockquote>
</blockquote>
=&gt; 무언가를 매우 자주 전환해야 하는 경우에는 v-show를 , 
실행중에 조건이 변경되지 않는 경우에는 v-if 를 권장</li>
</ul>
<hr>
<h1 id="3-list-rendering">3. List Rendering</h1>
<ul>
<li>반복 가능한 애들 렌더링</li>
</ul>
<h2 id="v-for">v-for</h2>
<ul>
<li>소스 데이터(Array, Object, number, string, lterable)를 기반으로 요소 또는 템플릿 블록을 여러 번 렌더링</li>
<li>v-for는 <code>alias in expression</code> 형식의 특수 구문을 사용하여 반복되는 현재 요소에 대한 별칭(alias)을 제공</li>
</ul>
<ul>
<li>인덱스(객체에서는 키)에 대한 별칭을 지정할 수 있음</li>
<li>위치는 지정되어있음</li>
<li>alias를 하나만 하면 =&gt; 값이 출력되고</li>
<li>두개를 한다 -&gt; 값과 키가 출력되고</li>
<li><blockquote>
<p>세개를 쓰면 인덱스까지도 출력이 된다. </p>
</blockquote>
</li>
</ul>
<hr>
<p><strong>배열 반복</strong></p>
<pre><code class="language-jsx">    &lt;div v-for=&quot;(item, index) in myArr&quot;&gt;
      {{ index }} // {{item.name}}
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/14564a55-b3e0-49a2-b563-223bcf5cf5cb/image.png" alt=""></p>
<hr>
<p><strong>객체 반복</strong></p>
<pre><code class="language-jsx">    &lt;div v-for=&quot;(value, key, index) in myObj&quot;&gt;
      {{ index }} // {{key}} // {{value}}
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/bf678baf-600e-4055-b585-e1757b658fc9/image.png" alt=""></p>
<hr>
<p><strong>여러 요소에 대한 v-for 적용</strong></p>
<ul>
<li>template 요소에 v-for를 사용하여 하나 이상의 요소에 대해 반복 렌더링 할 수 있음<pre><code class="language-jsx">&lt;!-- v-for on &lt;template&gt; --&gt;
  &lt;ul&gt;
    &lt;template v-for=&quot;item in myArr&quot;&gt;
      &lt;li&gt; {{ item.name }}&lt;/li&gt;
      &lt;li&gt; {{item.age}} &lt;/li&gt;
      &lt;hr&gt;
    &lt;/template&gt;
  &lt;/ul&gt;</code></pre>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/bedc1cdd-18ae-4d62-8cdb-59cad330b52a/image.png" alt=""></p>
<hr>
<p><strong>중첩된 v-for</strong></p>
<ul>
<li>각 v-for 범위는 상위 범위에 접근 할 수 있음<pre><code class="language-jsx">  &lt;!-- nested v-for --&gt;
  &lt;ul v-for=&quot;item in myInfo&quot;&gt;
    &lt;li v-for=&quot;friend in item.friends&quot;&gt;
      {{item.name}} - {{ friend }}
    &lt;/li&gt;
  &lt;/ul&gt;</code></pre>
<img src="https://velog.velcdn.com/images/turtle_hw/post/9ca40685-04b0-492b-8294-98979ddb5db5/image.png" alt=""></li>
</ul>
<hr>
<h3 id="v-for-with-key">v-for with key</h3>
<blockquote>
<p>반드시 v-for 와 key를 함께 사용한다</p>
</blockquote>
<ul>
<li><p>내부 컴포넌트의 상태를 일관되게 유지</p>
</li>
<li><p>데이터의 예측 가능한 행동을 유지(Vue 내부 동작 관련)</p>
</li>
<li><p>key는 반드시 각 요소에 대한 고유한 값을 나타낼 수 있는 식별자여야 함
<img src="https://velog.velcdn.com/images/turtle_hw/post/1c25fd0b-8734-46fa-9dd6-c3f34d4b156e/image.png" alt=""></p>
</li>
<li><p>키를 각각의 요소에 연결시켜줌</p>
</li>
</ul>
<hr>
<h3 id="v-for-with-v-if">v-for with v-if</h3>
<p><strong>&gt; 동일 요소에 함께 사용하지 않는다!!</strong></p>
<ul>
<li>동일 요소에서 v-if가 v-for보다 우선순위가 더 높기 때문</li>
<li><blockquote>
<p>v-if 조건은 v-for 범위의 변수에 접근할 수 없음</p>
</blockquote>
</li>
</ul>
<p><strong>문제상황1</strong></p>
<ul>
<li>todo 데이터 중 이미 처리 한(isComplete === true) todo 만 출력하기</li>
<li>아래와 같이 하면 오류가 난다.</li>
<li>아직 todo가 반복돌면서 나오기 때문에 정의되지 않았다고 함</li>
</ul>
<pre><code class="language-jsx">    &lt;!-- [Bad] v-for with v-if --&gt;
    &lt;ul v-for=&quot;todo in todos&quot; v-if=&quot;!todo.isComplete&quot; :key=&quot;todo.id&quot;&gt;
      &lt;li&gt;
        {{todo.name}}
      &lt;/li&gt;
    &lt;/ul&gt;</code></pre>
<p><strong>해결법</strong></p>
<ol>
<li>computed를 활용해 필터링 된 목록을 반환하여 반복하도록 설정</li>
</ol>
<pre><code class="language-jsx">  const completeTodos = computed(() =&gt; {
          return todos.value.filter((todo) =&gt; !todo.isComplete)
        })

 &lt;li v-for=&quot;todo in completeTodos&quot; :key=&quot;todo.id&quot;&gt;
        {{todo.name}}
      &lt;/li&gt;</code></pre>
<ol start="2">
<li>템플릿태그를 이용해서 둘의 위치를 따로 분리시키는 방법도 있음
<img src="https://velog.velcdn.com/images/turtle_hw/post/294d1c49-3423-4c2c-979d-caa1caa308c1/image.png" alt=""></li>
</ol>
<hr>
<h1 id="4-watchers">4. Watchers</h1>
<h2 id="watch">watch()</h2>
<ul>
<li>반응형 데이터를 감시하고, 감시하는 데이터가 변경되면 콜백 함수를 호출</li>
<li>리턴에는 템플릿에서 쓰일 것들만 넣는다. </li>
</ul>
<blockquote>
<h3 id="구조">구조<img src="https://velog.velcdn.com/images/turtle_hw/post/31a48d19-a43c-45e8-b444-f012cdc546e8/image.png" alt=""></h3>
<p><strong>variable</strong> - 감시하는 변수 
<strong>newValue</strong> - 감시하는 변수가 변화된 값 / 콜백 함수의 첫번째 인자
<strong>oldValue</strong> - 콜백 함수의 두번째 인자 </p>
</blockquote>
<h3 id="1-감시하는-변수에-변화가-생겼을-때-기본-동작-확인하기">1. 감시하는 변수에 변화가 생겼을 때 기본 동작 확인하기</h3>
<pre><code class="language-jsx">const countWatch = watch(count, (newValue, oldValue) =&gt; {
    console.log(`newValue: ${newValue}, oldValue: ${oldValue}`)
})
</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/f073c8df-d968-49ec-beba-df70ae7c8d9a/image.png" alt=""></p>
<h3 id="2-감시하는-변수에-변화가-생겼을-때-연관-데이터-업데이트하기">2. 감시하는 변수에 변화가 생겼을 때 연관 데이터 업데이트하기</h3>
<pre><code class="language-jsx">const messageWatch = watch(message, (newValue, oldValue) =&gt; {
    messageLength.value = newValue.length
})</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/dc246b0a-156f-4c3f-b0ad-fe35b953281f/image.png" alt=""></p>
<hr>
<h3 id="computed와-watchers">Computed와 Watchers</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/d070ee08-9b65-4a80-b697-993ba01a6e8f/image.png" alt=""></p>
<p><strong>★ computed와 watch 모두 의존(감시)하는 원본 데이터를 직접 변경하지 않음!!</strong></p>
<hr>
<h1 id="5-lifecycle-hooks">5. Lifecycle Hooks</h1>
<ul>
<li>Vue 인스턴스의 생애주기 동안 특정 시점에 실행되는 함수</li>
<li>개발자가 특정 단계에서 의도하는 로직이 실행될 수 있도록 함</li>
</ul>
<ol>
<li>Vue 컴포넌트 인스턴스가 초기 렌더링 및 DOM 요소 생성이 완료된 후 특정 로직을 수행하기 <blockquote>
<p>onMounted = 앱이 템플릿에 마운트되었을때(연결되었을때) 출력됨 </p>
</blockquote>
<pre><code class="language-js">onMounted(() =&gt; {
       console.log(&#39;mounted&#39;)
     })</code></pre>
</li>
</ol>
<ol start="2">
<li>반응형 데이터의 변경으로 인해 컴포넌트의 DOM이 업데이트된 후 특정 로직을 수행하기<blockquote>
<p>onupdated = 업데이트 되엇을 때!!
<img src="https://velog.velcdn.com/images/turtle_hw/post/54d7e3b1-0cc5-43a1-9033-3e3929ccd522/image.png" alt=""></p>
</blockquote>
</li>
</ol>
<h2 id="lifecycle-hooks-특징">Lifecycle Hooks 특징</h2>
<ul>
<li>Vue 는 Lifecycle Hooks에 등록된 콜백 함수들을 인스턴스와 자동으로 연결</li>
<li>이렇게 동작하려면 hooks 함수들은 반드시 동기적으로 작성되어야 함</li>
<li>인스턴스 생애 주기의 여러 단계에서 호출되는 다른 hooks 도 있으며, 가장 일반적으로 사용되는 것은 onMounted, onUpdated, onUnmounted</li>
</ul>
<hr>
<h1 id="6-vue-style-guide">6. Vue Style Guide</h1>
<p><a href="https://ko.vuejs.org/style-guide/">스타일 가이드</a></p>
<h1 id="참고">참고</h1>
<ul>
<li>computed의 반환 값은 의존하는 데이터의 파생된 값</li>
<li>일종의 snapshot이며 의존하는 데이터가 변경될 때마다 새 snapshot이 생성됨</li>
<li>snapshot을 변경하는 것은 의미가 없으므로 계산된 반환 값은 읽기 전용으로 취급되어야 하며 변경되어서는 안됨</li>
<li>대신 새 값을 얻기 위해서는 의존하는 데이터를 업데이트 해야 함</li>
</ul>
<table>
<thead>
<tr>
<th>computed에서 reverse() 및 sort() 사용시 원본 배열을 변경하기 때문에 복사본을 만들어서 진행해야 함</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/3b2999e2-3f70-4bbe-96f9-e922c7b0805d/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<table>
<thead>
<tr>
<th>배열의 인덱스를 v-for의 key로 사용하지 말 것</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/f9060379-e987-484f-a439-4f6897210d38/image.png" alt=""></td>
</tr>
<tr>
<td>- 인덱스는 식별자가 아닌 배열의 항목 위치만 나타내기 때문에 Vue가 DOM을 변경 할 때 (끝이 아닌 위치에 새 항목이 배열에 삽입되면) 여러 컴포넌트간 데이터 공유 시 문제가 발생</td>
</tr>
<tr>
<td>- 직접 고유한 값을 만들어내는 메서드를 만들거나 외부 라이브러리 등을 활용하는 등 식별자 역할을 할 수 있는 값을 만들어 사용</td>
</tr>
</tbody></table>
<h4 id="v-for와-배열-배열-변경-감지">v-for와 배열-&#39;배열 변경 감지&#39;</h4>
<ul>
<li>수정 메서드 (원본 배열 수정)<ul>
<li>Vue는 반응형 배열의 변경 메소드가 호출 되는 것을 감지하여, 필요한 업데이트를 발생시킴<ul>
<li>push(), pop(), shift(). unshift(), splice(), sort(), reverse()</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>배열 교체<ul>
<li>원본 배열을 수정하지 않고 항상 새 배열을 반환</li>
<li>filter(), concat(), clice()</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ Basic Syntax(1)]]></title>
            <link>https://velog.io/@turtle_hw/Basic-Syntax1</link>
            <guid>https://velog.io/@turtle_hw/Basic-Syntax1</guid>
            <pubDate>Thu, 02 Nov 2023 06:06:24 GMT</pubDate>
            <description><![CDATA[<h1 id="1-template-syntax">1. Template Syntax</h1>
<hr>
<ul>
<li>DOM을 기본 구성 요소 인스턴스의 데이터에 선언적으로 바인딩할 수 있는 HTML 기반 템플릿 구문을 사용</li>
</ul>
<h2 id="template-syntax-종류">Template Syntax 종류</h2>
<h3 id="1-text-interpolation">1) Text Interpolation</h3>
<ul>
<li>데이터 바인딩의 가장 기본적인 형태</li>
<li>이중 중괄호 구문(콧수염 구문)을 사용</li>
<li>콧수염 구문은 해당 구성 요소 인스턴스의 msg 속성 값으로 대체</li>
<li>msg 속성이 변경될 때마다 업데이트 됨</li>
</ul>
<h3 id="2-raw-html">2) Raw HTML</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/4472dcbb-881a-4d1f-aafa-72211d5cb604/image.png" alt=""></p>
<h3 id="3-attribute-bindings">3) Attribute Bindings</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/05db4ca1-e906-4cab-bb54-6795db28b947/image.png" alt=""></p>
<h3 id="4-javascript-expressions">4) JavaScript Expressions</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/3cdcd4b0-78a5-453b-9118-37658291331b/image.png" alt=""></p>
<ul>
<li>Vue는 모든 데이터 바인딩 내에서 JavaScript 표현식의 모든 기능을 지원</li>
<li>Vue 템플릿에서 JavaScript 표현식을 사용할 수 있는 위치<ol>
<li>콧수염 구문 내부</li>
<li>모든 directive 의 속성 값(v-로 시작하는 특수 속성)</li>
</ol>
</li>
</ul>
<blockquote>
<h4 id="expressions-주의사항">Expressions 주의사항</h4>
</blockquote>
<ul>
<li>각 바인딩에는 하나의 단일 표현식만 포함될 수 있음<ul>
<li>표현식은 값으로 평가할 수 있는 코드 조각(return 뒤에 사용될 수 있는 코드여야 함)
<img src="https://velog.velcdn.com/images/turtle_hw/post/8c726e4b-cbcc-4a4f-8858-5a9449df31e0/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<h2 id="directive">Directive</h2>
<ul>
<li>&#39;v-&#39; 접두사가 있는 특수 속성</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>Directive의 속성 값은 단일 JavaScript 표현식이어야 함 (v-for, v-on 제외)</li>
<li>표현식 값이 변경될 때 DOM 에 반응적으로 업데이트를 적용(자동화)
<img src="https://velog.velcdn.com/images/turtle_hw/post/ee286d1a-f1e5-4b3a-8ead-4cb451c69cab/image.png" alt="">ex. v-if는 seen 표현식의 값을 T/F 기반으로 <code>&lt;p&gt;</code>요소를 제거/삽입(출력할것이냐 말것이냐)(렌더링 할것이냐 말것이냐)</li>
</ul>
<blockquote>
<h3 id="전체-구문">전체 구문</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/ec994f69-ddc1-4c7e-be27-efe000933a78/image.png" alt=""></p>
</blockquote>
<ul>
<li>Argument(인자)는 앞에 Name이 뭐냐에 따라서 달라짐</li>
<li>v-on은 이벤트 감지하는 애라서 뒤에 인자들이 전부 이벤트의 이름들이다. </li>
<li>.으로 시작하는 구문 = 수식어(Modifiers) 도 있는 애가 있고 없는 애가 있다. </li>
<li>.prevent =&gt; prevnet Default 의 기능 들어가있음 (앞에 있는 이벤트의 기본 동작을 취소시키는 것)</li>
<li>&quot;onSubmit&quot; =&gt; 이 함수를 호출하겠다. </li>
</ul>
<h2 id="directive---arguments">Directive - Arguments</h2>
<ul>
<li><p>일부 directive는 directive 뒤에 콜론(:)으로 표시되는 인자를 사용할 수 있음</p>
</li>
<li><p>아래 예시의 href는 HTML a 요소의 href 속성 값을 myUrl 값에 바인딩하도록 하는 v-bind의 인자
<img src="https://velog.velcdn.com/images/turtle_hw/post/e2763c52-3a25-4f26-adf1-5a3fb772d125/image.png" alt=""></p>
</li>
<li><p>아래 예시의 click은 이벤트 수신할 이벤트 이름을 작성하는 v-on의 인자
<img src="https://velog.velcdn.com/images/turtle_hw/post/d8044e94-a810-4097-870c-d46b0375c735/image.png" alt=""></p>
</li>
</ul>
<h2 id="directive---modifiers">Directive - Modifiers</h2>
<ul>
<li>.(dot)로 표시되는 특수 접미사로, directive가 특별한 방식으로 바인딩 되어야 함을 나타냄</li>
<li>chaining 가능하다</li>
<li>새로고침 안되게 하는 예를 들어 .prevent는 발생한 이벤트에서 event.preventDefault()를 호출하도록 v-on에 지시하는 modifier
<img src="https://velog.velcdn.com/images/turtle_hw/post/c72c783c-fe78-4f09-8180-171b19c2a9de/image.png" alt=""></li>
</ul>
<blockquote>
<p>built-in Directives
v-text / v-show / v-if / v-for / ... /
<a href="https://vuejs.org/api/built-in-directives.html">https://vuejs.org/api/built-in-directives.html</a></p>
</blockquote>
<hr>
<h1 id="2-dynamically-data-binding">2. Dynamically data binding</h1>
<h4 id="v-bind---하나-이상의-속성-또는-컴포넌트-데이터를-표현식에-동적으로-바인딩"><a href="https://vuejs.org/api/built-in-directives.html#v-bind">v-bind</a> - 하나 이상의 속성 또는 컴포넌트 데이터를 표현식에 동적으로 바인딩</h4>
<h3 id="v-bind-사용처">v-bind 사용처</h3>
<h3 id="1-attribute-bindings">1. Attribute Bindings<img src="https://velog.velcdn.com/images/turtle_hw/post/302639e0-29a6-462f-81d0-f575ae659b9b/image.png" alt=""></h3>
<table>
<thead>
<tr>
<th>v-bind shortand(약어) : &#39;:&#39; (colon)</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/0730c331-f56b-4a9c-b685-1dde0bf271e9/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<ul>
<li><strong>Dynamic attribute name (동적 인자 이름)</strong><ul>
<li>대괄호로 감싸서 directive argument에 JavaScript 표현식을 사용할 수도 있음</li>
<li>JavaScript 표현식에 따라 동적으로 평가된 값이 최종 argument 값으로 사용됨
<img src="https://velog.velcdn.com/images/turtle_hw/post/f29cacd7-90c0-4d56-8580-e29b16454e63/image.png" alt=""></li>
<li>대괄호 안에 작성하는 이름은 반드시 소문자로만 구성 가능
(브라우저가 속성 이름을 소문자로 강제 변환)</li>
</ul>
</li>
</ul>
<h3 id="2-class-and-style-bindings">2. Class and Style Bindings</h3>
<ul>
<li>클래스와 스타일은 모두 속성이므로 v-bind를 사용하여 다른 속성과 마찬가지로 동적으로 문자열 값을 할당할 수 있음</li>
<li>그러나 단순히 문자열 연결을 사용하여 이러한 값을 생성하는 것은 번거롭고 오류가 발생하기 쉬움</li>
<li>Vue는 클래스 및 스타일과 함께 v-bind를 사용할 때 객체 또는 배열을 활용한 개선 사항을 제공</li>
</ul>
<h3 id="class-and-style-bindings가-가능한-경우">Class and Style Bindings가 가능한 경우</h3>
<h3 id="11-binding-html-classes---binding-to-objects">1.1. Binding HTML Classes - Binding to Objects</h3>
<ul>
<li>객체를 :class에 전달하여 클래스를 동적으로 전환할 수 있음</li>
</ul>
<table>
<thead>
<tr>
<th>isActive의 T/F에 의해 active 클래스의 존재가 결정됨</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/58e9d038-6b20-4d79-94b3-afc3994efc99/image.png" alt=""></td>
</tr>
</tbody></table>
<ul>
<li>객체에 더 많은 필드를 포함하여 여러 클래스를 전환할 수 있음<ul>
<li>:class directive를 일반 클래스 속성과 함께 사용 가능<pre><code class="language-js">const isAtive = ref(true)
const hasInfo = ref(true)
</code></pre>
</li>
</ul>
</li>
</ul>
<div class="static" :class="{active: isAtive, 'text-primary': hasInfo}">Text</div>        
```

<ul>
<li>반드시 inline 방식으로 작성하지 않아도 됨<pre><code class="language-js">// ref는 반응 객체의 속성으로 액세스되거나 변경될 때 자동으로 unwrap
const classObj = ref({
 active: isAtive
&#39;text-primary&#39;: hasInfo,
})
</code></pre>
</li>
</ul>
<div class="static" :class="classObj">Text</div>
```

<h3 id="12-binding-html-classes--binding-to-arrays">1.2. Binding HTML Classes -Binding to Arrays</h3>
<ul>
<li>:class를 배열에 바인딩하여 클래스 목록을 적용할 수 있음<pre><code class="language-js">const activeCalss = ref(&#39;active&#39;)
const infoClass = ref(&#39;text-primary&#39;)
</code></pre>
</li>
</ul>
<div :class="[activeCalss, infoClass]">Text</div>
```

<ul>
<li>배열 구문 내에서 객체 구문 사용
<img src="https://velog.velcdn.com/images/turtle_hw/post/cf2dadba-275c-4e0b-bc7c-ddd40a5137dd/image.png" alt=""></li>
</ul>
<hr>
<h3 id="21-binding-inline-styles---binding-to-objects">2.1. Binding Inline Styles - Binding to Objects</h3>
<ul>
<li><code>:style</code>은 JavaScript 객체 값에 대한 바인딩을 지원(HTML sytle 속성에 해당)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/d36f0368-f189-480d-b214-5b5b2928d112/image.png" alt=""></p>
<ul>
<li>실제 CSS에서 사용하는 것처럼 <code>:style</code>은 kebab-cased 키 문자열도 지원 ( 단, camelCase 작성을 권장 )
<img src="https://velog.velcdn.com/images/turtle_hw/post/13b3bbe4-49c2-418a-8df9-d2cfcea1af62/image.png" alt=""></li>
</ul>
<ul>
<li>템플릿을 더 깔끔하게 작성하려면 스타일 객체에 직접 바인딩하는 것을 권장<pre><code class="language-js">const styleObj = ref({
  color: activeColor,
  fontSize: fontSize.value + &#39;px&#39;
})
</code></pre>
</li>
</ul>
<div :style="styleObj">Text</div>
```


<h3 id="22-binding-inline-styles---binding-to-arrays">2.2. Binding Inline Styles - Binding to Arrays</h3>
<ul>
<li>여러 스타일 객체의 배열에 <code>:style</code>을 바인딩할 수 있음</li>
</ul>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/turtle_hw/post/8e8abc80-2256-4c83-9133-48662f3a21d4/image.png" alt=""></th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/8cf5c329-ca88-40f3-ac44-2ce268c8bf7e/image.png" alt=""></td>
</tr>
</tbody></table>
<ul>
<li>작성한 객체는 병합되어 동일한 요소에 적용</li>
</ul>
<hr>
<h1 id="3-event-handling">3. Event Handling</h1>
<h2 id="v-on">v-on</h2>
<ul>
<li>DOM 요소에 이벤트 리스너를 연결 및 수신</li>
</ul>
<h2 id="v-on-구성">v-on 구성</h2>
<blockquote>
<pre><code class="language-js">v-on:event=”handler”</code></pre>
</blockquote>
<pre><code>- handler 종류
    1. Inline handlers : 이벤트가 트리거 될 때 실행 될 JavaScript 코드
    2. Method handlers : 컴포넌트에 정의된 메서드 이름
- v-on shorthand ( 약어 )
    - __`@`__
&gt; ```js
@event=’handler’</code></pre><h3 id="1-inline-handlers">1. Inline handlers</h3>
<ul>
<li>Inline handlers는 주로 간단한 상황에 사용
<img src="https://velog.velcdn.com/images/turtle_hw/post/99988857-7b72-40d8-8161-45d37b9c127b/image.png" alt=""></li>
</ul>
<h3 id="2-method-handlers">2. Method Handlers</h3>
<ul>
<li><p>Inline handlers로는 불가능한 대부분의 상황에서 사용
<img src="https://velog.velcdn.com/images/turtle_hw/post/dce4c1d0-d71f-489d-ae3e-eaf722958b77/image.png" alt=""></p>
</li>
<li><p>Method Handlers는 이를 트리거하는 기본 DOM Event 객체를 자동으로 수신</p>
</li>
</ul>
<blockquote>
<h4 id="inline-handlers에서의-메서드-호출">Inline Handlers에서의 메서드 호출</h4>
</blockquote>
<ul>
<li>메서드 이름에 직접 바인딩하는 대신 Inline Handlers에서 메서드를 호출할 수도 있음</li>
<li>이렇게 하면 기본 이벤트 대신 사용자 지정 인자를 전달할 수 있음
<img src="https://velog.velcdn.com/images/turtle_hw/post/2e42cf1d-6b4d-4e6a-ac7c-6608613030db/image.png" alt=""></li>
</ul>
<blockquote>
<h4 id="inline-handlers에서의-event-인자에-접근하기">Inline Handlers에서의 event 인자에 접근하기</h4>
</blockquote>
<ul>
<li>Inline Handlers에서 원래 DOM 이벤트에 접근하기</li>
<li>$event 변수를 사용하여 메서드에 전달
<img src="https://velog.velcdn.com/images/turtle_hw/post/eb18bcbc-a088-4a0e-8e06-e30fcb065f5d/image.png" alt=""></li>
</ul>
<blockquote>
<h3 id="event-modifiers">Event Modifiers</h3>
</blockquote>
<ul>
<li>Vue는 v-on에 대한 Event Modifiers를 제공해 event.preventDefault()와 같은 구문을 메서드에서 작성하지 않도록 함</li>
<li>stop, prevent, self 등 다양한 modifiers를 제공</li>
<li>메서드는 DOM 이벤트에 대한 처리보다는 데이터에 관한 논리를 작성하는 것에 집중할 것
<img src="https://velog.velcdn.com/images/turtle_hw/post/700d2f9f-34ed-4243-8489-0acc9a9a2893/image.png" alt="">
💡  Modifiers는 chained 되게끔 작성할 수 있으며, 이때는 작성된 순서로 실행되기 때문에 작성 순서에 유의</li>
</ul>
<blockquote>
<h4 id="key-modifiers">Key Modifiers</h4>
</blockquote>
<ul>
<li>Vue는 키보드 이벤트를 수신할 때 특정 키에 관한 별도 modifiers를 사용할 수 있음<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>key가 Enter일 때만 onSubmit 이벤트를 호출하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/fbac2c8c-66f9-41a3-8ef4-bcede5e85d54/image.png" alt=""></td>
</tr>
</tbody></table>
</li>
</ul>
<hr>
<h1 id="4-form-input-bindings">4. Form Input Bindings</h1>
<ul>
<li>form을 처리할 때 사용자가 input에 입력하는 값을 실시간으로 JavaScript 상태에 동기화해야 하는 경우 ( <strong>양방향 바인딩</strong> )</li>
</ul>
<h2 id="v-bind와-v-on을-함께-사용">v-bind와 v-on을 함께 사용</h2>
<ul>
<li>v-bind를 사용하여 input 요소의 value 속성 값을 입력 값으로 사용</li>
<li>v-on 을 사용하여 input 이벤트가 발생 할 때마다 input 요소의 value값을 별도 반응형 변수에 저장하는 핸들러를 호출
<img src="https://velog.velcdn.com/images/turtle_hw/post/0bcd9a43-51de-4364-b76e-a4bfc41c3fad/image.png" alt=""></li>
</ul>
<hr>
<h2 id="v-model">v-model</h2>
<ul>
<li>form input 요소 또는 컴포넌트에서 양방향 바인딩을 만듦</li>
</ul>
<h3 id="v-model-사용">v-model 사용</h3>
<ul>
<li>form input 요소 또는 컴포넌트에서 양방향 바인딩을 만듦</li>
</ul>
<ul>
<li>v-model을 사용하여 사용자 입력 데이터와 반응형 변수를 실시간 동기화</li>
</ul>
<blockquote>
<p>💡 IME가 필요한 언어(한,중,일 등)의 경우 v-model이 제대로 업데이트 되지 않음</p>
<ul>
<li>해당 언어에 대해 올바르게 응답하려면 v-bind와 v-on 방법을 사용해야함</li>
</ul>
</blockquote>
<blockquote>
<p><strong>IME ( Input Method Editor)</strong>
    - 사용자가 입력 장치에서 기본적으로 사용할 수 없는 문자(비영어권 언어)를 입력할 수 있드록  하는 운영 체제 구성 프로그램
    - 일반적으로 키보드 키보다 자모가 더 많은 언어에서 사용해야 함</p>
<blockquote>
<p>IME가 동작하는 방식과 Vue의 양방향 바인딩(v-model) 동작 방식이 상충하기 때문에 한국어 입력 시 예상대로 동작하지 않았던 것</p>
</blockquote>
</blockquote>
<h3 id="v-model과-다양한-입력input-양식">v-model과 다양한 입력(input) 양식</h3>
<ul>
<li>v-model은 단순 text input 뿐만 아니라 Checkbox, Radio, Select 등 다양한 타입의 사용자 입력 방식과 함께 사용 가능</li>
</ul>
<h3 id="checkbox-활용">Checkbox 활용</h3>
<pre><code class="language-html">// 1. 단일 체크박스와 boolean 값 활용
&lt;input type=&quot;checkbox&quot; id=&quot;checkbox&quot; v-model=&quot;checked&quot;&gt;

// 2. 여러 체크박스와 배열 활용
&lt;input type=&quot;checkbox&quot; id=&quot;alice&quot; value=&quot;Alice&quot; v-model=&quot;checkedNames&quot;&gt;
</code></pre>
<ul>
<li>해당 배열에는 현재 선택된 체크박스의 값이 포함됨</li>
</ul>
<h3 id="select-활용">Select 활용</h3>
<ul>
<li>select에서 v-model 표현식의 초기 값이 어떤 option과도 일치하지 않는 경우 select 요소는 &quot;선택되지 않은(unselected)&quot; 상태로 렌더링 됨</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/1f9909bf-b236-4988-b809-2f37719bba2c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Introduction of Vue]]></title>
            <link>https://velog.io/@turtle_hw/Introduction-of-Vue</link>
            <guid>https://velog.io/@turtle_hw/Introduction-of-Vue</guid>
            <pubDate>Tue, 31 Oct 2023 16:42:03 GMT</pubDate>
            <description><![CDATA[<h1 id="front-end-development">Front-end Development</h1>
<ul>
<li>웹사이트와 웹 애플리케이션의 사용자 인터페이스(UI)와 사용자 경험(UX)을 만들고 디자인하는 것</li>
<li><blockquote>
<p>HTML, CSS, JavaScript 등을 활용하여 사용자가 직접 상호작용하는 부분을 개발</p>
</blockquote>
</li>
</ul>
<h2 id="client-side-frameworks">Client-side frameworks</h2>
<ul>
<li>클라이언트 측에서 UI와 상호작용을 개발하기 위해 사용되는 JavaScript 기반 프레임워크</li>
</ul>
<h2 id="spasingle-page-application">SPA(Single Page Application)</h2>
<ul>
<li>페이지 한 개로 구성된 웹 애플리케이션</li>
<li>웹 애플리케이션의 초기 로딩 후 새로운 페이지 요청 없이 동적으로 화면을 갱신하며 사용자와 상호작용하는 웹 애플리케이션 =&gt; <code>CSR 방식</code></li>
</ul>
<blockquote>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/a43be5f5-7639-425b-998b-48a52010d739/image.png" alt=""> <strong>1. 서버로부터 필요한 모든 정적 HTML을 처음에 한번 가져옴</strong>
<strong>2. 브라우저가 페이지를 로드하면 VUe 프레임워크는 각 HTML 요소에 적절한 JavaScript 코드를 실행(이벤트에 응답, 데이터 요청 후 UI 업데이트 등)</strong></p>
<ul>
<li>ex) 페이지 간 이동 시, 페이지 갱신에 필요한 데이터만을 JSON으로 전달받아 페이지 일부 갱신</li>
<li>Google Maps, 인스타그램 등의 서비스에서 갱신 시 새로고침이 없는 이유</li>
</ul>
</blockquote>
<h2 id="client-side-renderingcsr---ssr">Client-side Rendering(CSR) &lt;-&gt; SSR</h2>
<ul>
<li>클라이언트에서 화면을 렌더링 하는 방식</li>
</ul>
<blockquote>
<ol>
<li>브라우저는 페이지에 필요한 최소한의 HTML 페이지와 JavaScript를 다운로드</li>
<li>그런 다음 JAvaScript를 사용하여 DOM을 업데이트하고 페이지를 렌더링
<img src="https://velog.velcdn.com/images/turtle_hw/post/16b7b1c5-5796-459b-bac6-4cab26133c13/image.png" alt=""></li>
</ol>
</blockquote>
<h3 id="client-side-rendering-장점">Client-side Rendering 장점</h3>
<ol>
<li><strong>빠른 속도</strong></li>
</ol>
<ul>
<li>페이지의 일부를 다시 렌더링할 수 있으므로 동일한 웹 사이트의 다른 페이지로 이동하는 것이 일반적으로 더 빠름</li>
<li>서버로 전송되는 데이터의 양을 최소화</li>
</ul>
<ol start="2">
<li><strong>사용자 경험</strong></li>
</ol>
<ul>
<li>새로고침이 발생하지 않아 네이티브 앱과 유사한 사용자 경험을 제공</li>
</ul>
<p>3.<strong>Front-end와 Back-end의 명확한 분리</strong></p>
<ul>
<li>Front-end는 UI 렌더링 및 사용자 상호 작용 처리를 담당 &amp; Back-end는 데이터 및 API 제공을 담당</li>
<li>대규모 애플리케이션을 더 쉽게 개발하고 유지 관리 가능</li>
</ul>
<h3 id="client-side-rendering-단점">Client-side Rendering 단점</h3>
<ol>
<li><strong>초기 구동속도가 느림</strong></li>
</ol>
<ul>
<li>전체 페이지를 보기 전에 약간의 지연을 느낄 수 있음</li>
<li>JavaScript가 다운로드, 구문 분석 및 실행될 때까지 페이지가 완전히 렌더링 되지 않기 때문</li>
</ul>
<ol start="2">
<li><strong>SEO(검색 엔진 최적화)문제</strong></li>
</ol>
<ul>
<li>페이지를 나중에 그려 나가는 것이기 때문에 검색에 잘 노출되지 않을 수 있음</li>
</ul>
<hr>
<h1 id="what-is-vue">What is Vue?</h1>
<ul>
<li>사용자 인터페이스를 구축하기 위한 JavaScript 프레임워크</li>
<li>2014년 발표 - Evan You</li>
</ul>
<h2 id="⭐-vue의-2가지-핵심-기능">⭐ Vue의 2가지 핵심 기능</h2>
<h3 id="1-선언적-렌더링declarative-rendering">1. 선언적 렌더링(Declarative Rendering)</h3>
<ul>
<li>HTML을 확장하는 템플릿 구문<code>{{}}</code>을 사용하여 HTML이 JavaScript 데이터를 기반으로 어떻게 보이는지 설명할 수 있음</li>
</ul>
<h3 id="2-반응형reacivity">2. 반응형(Reacivity)</h3>
<ul>
<li>JavaScript 상태 변경사항을 자동으로 추적하고 변경사항이 발생할 때 DOM을 효율적으로 업데이트</li>
</ul>
<hr>
<h2 id="vue를-사용하는-방법">Vue를 사용하는 방법</h2>
<h3 id="1-cdn-방식">1. &#39;CDN&#39; 방식</h3>
<h3 id="2-npm-방식">2. &#39;NPM&#39; 방식</h3>
<p>-&gt; CDN 방식 이후 진행 / python의 pip랑 같은 방식 / node이용</p>
<hr>
<table>
<thead>
<tr>
<th>CDN 및 Application instance 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/e0bcec59-77d9-4fa8-8b92-69e55b3ec77b/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<h3 id="aplication-instance">Aplication instance</h3>
</blockquote>
<ul>
<li>모든 Vue 애플리케이션은 createApp 함수로 새 Application instance를 생성하는 것으로 시작<pre><code>const { createApp } = Vue
const app = createApp({})</code></pre></li>
</ul>
<blockquote>
<h3 id="appmount">app.mount()</h3>
</blockquote>
<ul>
<li>컨테이너 요소에 애플리케이션 인스턴스를 탑재(연결)</li>
<li>각 앱 인스턴스에 대해 mount()는 <code>한 번만</code> 호출할 수 있음<img src="https://velog.velcdn.com/images/turtle_hw/post/423d5d38-187c-41c8-8b80-896ed99f57f5/image.png" alt=""></li>
</ul>
<hr>
<h2 id="ref">ref()</h2>
<ul>
<li>반응형 상태(데이터)를 선언하는 함수(Declaring Reactive State)</li>
<li>** 반응형을 가지는 참조 변수를 만드는 것 (ref === reactive reference)**
<img src="https://velog.velcdn.com/images/turtle_hw/post/9e7ecd84-898b-452d-b59d-4c0c3ac42573/image.png" alt=""></li>
<li>인자를 받아 <code>.value</code> 속성이 있는 ref 객체로 래핑(wrapping)하여 반환</li>
<li>ref로 선언된 변수의 값이 변경되면, 해당 값을 사용하는 템플릿에서 자동으로 업데이트</li>
<li>인자는 어떠한 타입도 가능</li>
</ul>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/turtle_hw/post/d67c2a9c-10cd-456b-b5cd-4eab7008babb/image.png" alt=""></th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/873ff293-0819-4f63-8eb0-5333d7d45aa4/image.png" alt=""></td>
</tr>
<tr>
<td>템플릿의 참조에 접근하려면 setup 함수에서 선언 및 반환 필요</td>
</tr>
<tr>
<td>템플릿에서 ref를 사용할 때는 .value를 작성할 필요 없음(automatically unwrapped</td>
</tr>
</tbody></table>
<hr>
<h2 id="vue-기본-구조">vue 기본 구조</h2>
<ul>
<li><code>createApp()</code>에 전달되는 객체는 Vue <code>컴포넌트</code>(Component)(기능의 조각이라고 생각하면 됨)</li>
<li>컴포넌트의 상태는 <code>setup()</code> 함수 내에서 선언되어야 하며 <code>객체를 반환해야 함</code></li>
</ul>
<hr>
<h2 id="템플릿-렌더링">템플릿 렌더링</h2>
<ul>
<li>반환된 객체의 속성은 템플릿에서 사용할 수 있음</li>
<li>Muctache syntax(<code>콧수염 구문</code>)를 사용하여 메시지 값을 기반으로 <code>동적</code> 텍스트를 렌더링</li>
<li>콘텐츠는 식별자나 경로에만 국한되지 않으며 유효한 JavaScript 표현식을 사용할 수 있음
<img src="https://velog.velcdn.com/images/turtle_hw/post/e4e8f8d4-b10c-44da-b869-ba918b3ccc00/image.png" alt=""></li>
</ul>
<hr>
<h2 id="event-listeners-in-vue">Event Listeners in Vue</h2>
<ul>
<li>&#39;v-on&#39; directive를 사용하여 DOM 이벤트를 수신할 수 있음(addEventListner의 역할이었음)</li>
<li>함수 내에서 refs를 변경하여 구성 요소 상태를 업데이트
<img src="https://velog.velcdn.com/images/turtle_hw/post/13a54585-b270-4063-8003-e02535a9ee84/image.png" alt=""></li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<h3 id="템플릿에서의-unwrap-시-주의사항">템플릿에서의 unwrap 시 주의사항</h3>
<p>&quot;템플릿에서의 unwrap은 ref가 최상위 속성인 경우에만 적용가능&quot;</p>
<pre><code class="language-html">const object = { id: ref(0) }
{{ object.id + 1 }}
// 다음 표현식은 어떻게 출력될까? =&gt; [object Object]1</code></pre>
<ul>
<li><p>object는 최상위 속성이지만 object.id는 그렇지 않음</p>
</li>
<li><p>표현식을 평가할 때 object.id가 unwrap 되지 않고 ref 객체로 남아있기 때문</p>
</li>
<li><p>이 문제를 해결하기 위해서는 <code>&#39;id&#39;를 최상위 속성으로 분해</code> 해야 함!!</p>
<pre><code>const { id } = object
{{ id + 1 }}</code></pre><p><img src="https://velog.velcdn.com/images/turtle_hw/post/1d944871-4642-401f-9e86-ab36ce9aed40/image.png" alt=""></p>
</li>
</ul>
<ul>
<li>단, ref가 {{}}의 최종 평가 값인 경우는 unwrap 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/0bde5ebf-b092-4a58-9c5f-2d7c90a8e411/image.png" alt=""></li>
</ul>
<hr>
<h4 id="일반-변수-대신-굳이-value가-포함된-ref가-필요한-이유는">일반 변수 대신 굳이 .value가 포함된 ref가 필요한 이유는?</h4>
<ul>
<li><p>Vue는 템플릿에서 ref 를 사용하고 나중에 ref 의 값을 변경하면 자동으로 변경사항을 감지하고 그에 따라 DOM을 업데이트 함 (&quot;의존성 추적 기반의 반응형 시스템&quot;)</p>
</li>
<li><p>Vue는 렌더링 중에 사용된 모든 ref를 추적하며, 나중에 ref가 변경되면 이를 추적하는 구성 요소에 대해 다시 렌더링</p>
</li>
<li><p>반응형 구현하기 위해서!</p>
</li>
</ul>
<h3 id="seosearch-engine-optimization">SEO(Search Engine Optimization)</h3>
<ul>
<li><p>google, bing과 같은 검색 엔진 등에 내 서비스나 제품 등이 효율적으로 검색 엔진에 노출되도록 개선하는 과정을 일컫는 작업</p>
</li>
<li><p>정보의 대상은 주로 HTML에 작성된 내용</p>
</li>
<li><p>검색 </p>
<ul>
<li>각 사이트가 운용하는 검색 엔진에 의해 이루어지는 작업</li>
</ul>
</li>
<li><p>검색 엔진</p>
<ul>
<li>웹 상에 존재하는 가능한 모든 정보들을 긁어 모으는 방식으로 동작</li>
</ul>
</li>
<li><p>최근에는 SPA, 즉 CSR로 구성된 서비스의 비중이 증가</p>
</li>
<li><p>SPA  서비스도 검색 대상으로 넓히기 위해  JS를 지원하는 방식으로 발전하는 중</p>
</li>
</ul>
<h3 id="csr--ssr">CSR &amp; SSR</h3>
<ul>
<li>CSR 과 SSR은 흑과 백이 아님<ul>
<li>내 서비스에 적합한 렌더링 방식을 적절하게 활용할 수 있어야 함</li>
</ul>
</li>
<li>SPA 서비스에서도 SSR을 지원하는 Framework가 발전하고 있음<ul>
<li>Vue의 Nuxt.js</li>
<li>React의 Next.js</li>
<li>Angular Universal</li>
</ul>
</li>
</ul>
<hr>
<h3 id="반응형-변수와-일반-변수의-비교">반응형 변수와 일반 변수의 비교</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/6edcc812-43a1-4db6-87ed-03f5bd8c5f0b/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ajax with Django]]></title>
            <link>https://velog.io/@turtle_hw/Ajax-with-Django</link>
            <guid>https://velog.io/@turtle_hw/Ajax-with-Django</guid>
            <pubDate>Tue, 31 Oct 2023 02:23:54 GMT</pubDate>
            <description><![CDATA[<p><strong>Ajax</strong></p>
<ul>
<li>JavaScript의 비동기 구조와 XML 객체를 활용해 비동기적으로 서버와 통신하여 웹 페이지의 일부분만을 업데이트하는 웹 개발 기술</li>
</ul>
<p><strong>Ajax를 활용한 클라이언트 서버 간 동작</strong></p>
<ul>
<li>클라이언트 / 서버(Django)</li>
<li>이벤트 발생 -&gt; XHR 객체 생성 및 요청 -&gt; Ajax 요청 처리 -&gt; 응답 데이터 생성 -&gt; JSON 데이터 응답 -&gt; 응답 데이터를 활용해 DOM 조작(웹 페이지의 일부분 만을 다시 로딩)</li>
</ul>
<p><strong>사전준비</strong></p>
<pre><code class="language-bash">$ python manage.py loaddata users.json articles.json</code></pre>
<h1 id="ajax-with-follow">Ajax with follow</h1>
<h4 id="1-프로필-페이지에-axios-cdn-작성">1. 프로필 페이지에 axios CDN 작성</h4>
<pre><code class="language-js">// accounts/profile.html
 &lt;script src=&quot;https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js&quot;&gt;&lt;/script&gt;</code></pre>
<h4 id="2-form-요소-선택을-위해-id-속성-지정-및-선택">2. form 요소 선택을 위해 id 속성 지정 및 선택</h4>
<table>
<thead>
<tr>
<th>action과 method 속성은 삭제(요청은 axios 로 대체되기 때문)</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/8065e197-8bee-4375-898d-038e0aaa126b/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/650a02b5-1d47-4b6f-aab9-4c46878c738f/image.png" alt=""></td>
</tr>
</tbody></table>
<h4 id="3-form-요소에-이벤트-핸들러-작성-및-submit-이벤트의-기본-동작-취소">3. form 요소에 이벤트 핸들러 작성 및 submit 이벤트의 기본 동작 취소</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/2ab468cd-fccc-4213-b182-18ff9d523704/image.png" alt=""></p>
<h4 id="4-axios-요청-작성">4. axios 요청 작성</h4>
<ol>
<li>url에 작성할 user pk는 어떻게 작성해야 할까?</li>
<li>csrftoken은 어떻게 보내야 할까?
<img src="https://velog.velcdn.com/images/turtle_hw/post/8cf11ad9-3ea5-4a24-9c60-476366546a75/image.png" alt=""></li>
</ol>
<table>
<thead>
<tr>
<th>url에 작성할 user pk 가져오기(HTML =&gt; JavaScript)</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/a2c9ad65-00b3-4f45-a621-2075bd4e5d49/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/f62776ef-5f31-4a17-9203-b519004e7eb4/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<h3 id="data--속성">&#39;data-*&#39; 속성</h3>
<ul>
<li>사용자 지정 데이터 특성을 만들어 임의의 데이터를 HTML 과 DOM 사이에서 교환 할 수 있는 방법
<img src="https://velog.velcdn.com/images/turtle_hw/post/40f1d4c4-5184-4296-9623-4fd5a1fe7f2b/image.png" alt=""></li>
</ul>
<h4 id="문서상-hidden-타입으로-존재하는-csrf-데이터를-이제는-axios-로-전송해야-함">문서상 hidden 타입으로 존재하는 csrf 데이터를 이제는 axios 로 전송해야 함</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/1eabce6e-a77d-42e2-b22a-87495703f59a/image.png" alt=""></p>
<h4 id="csrf-값을-가진-input-요소를-직접-선택-후-axios-작성하기">csrf 값을 가진 input 요소를 직접 선택 후 axios 작성하기</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/a9c8899b-cea7-4fe5-9cfa-0211951296af/image.png" alt=""></p>
<ul>
<li><p><a href="https://docs.djangoproject.com/en/4.2/howto/csrf/">https://docs.djangoproject.com/en/4.2/howto/csrf/</a></p>
</li>
<li><p>팔로우 버튼을 토글하기 위해서는 현재 상태가 팔로우인지 언팔로우인지 상태 확인 필요</p>
<h4 id="django의-view-함수에서-팔로우-여부를-파악할-수-있는-변수를-추가로-생성해-json-타입으로-응답하기">Django의 view 함수에서 팔로우 여부를 파악할 수 있는 변수를 추가로 생성해 JSON 타입으로 응답하기</h4>
</li>
</ul>
<table>
<thead>
<tr>
<th>팔로우 상태 여부를 JavaScript에게 전달할 데이터 작성</th>
</tr>
</thead>
<tbody><tr>
<td>응답은 더이상 HTML 문서가 아닌 JSON 데이터로 응답</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/1fb10860-0fea-42c8-9cd8-35b0f83d3e6b/image.png" alt=""></td>
</tr>
</tbody></table>
<h4 id="팔로우-요청-후-django-서버로부터-받은-데이터-확인하기">팔로우 요청 후 Django 서버로부터 받은 데이터 확인하기</h4>
<table>
<thead>
<tr>
<th>응답 데이터 is_followed 에 따라 팔로우 버튼을 토글하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/71e5c699-9860-4a0d-99fc-2073b5363669/image.png" alt=""></td>
</tr>
</tbody></table>
<ul>
<li>클라이언트와 서버 간 XHR 객체가 주고 받는 것을 확인하기 </li>
</ul>
<h4 id="팔로잉-수와-팔로워-수-비동기-적용">&#39;팔로잉 수와 팔로워 수 비동기 적용&#39;</h4>
<ul>
<li>해당 요소를 선택할 수 있도록 span 태그와 id 속성 작성
<img src="https://velog.velcdn.com/images/turtle_hw/post/b1281f39-eb7c-4e87-8825-183cc7f055f6/image.png" alt=""></li>
</ul>
<h4 id="각-span-태그를-선택">각 span 태그를 선택</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/e48b91ef-02da-4eea-a64a-e06fa9e6c28e/image.png" alt=""></p>
<h4 id="django-view-함수에서-팔로워-팔로잉-인원-수-연산을-진행하여-결과를-응답으로-전달">Django view 함수에서 팔로워, 팔로잉 인원 수 연산을 진행하여 결과를 응답으로 전달</h4>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/8b4c2285-78b7-45f9-bc13-c31f09486669/image.png" alt=""></p>
<ul>
<li>응답 데이터의 연산 결과를 각 태그의 인원 수 값 변경에 적용
<img src="https://velog.velcdn.com/images/turtle_hw/post/72e7b934-1784-475b-832e-108712ac7f18/image.png" alt=""></li>
</ul>
<hr>
<h1 id="ajax-with-likes">Ajax with likes</h1>
<blockquote>
<ul>
<li>Ajax 적용은 팔로우와 모두 동일</li>
</ul>
</blockquote>
<ul>
<li>but, 팔로우와 달리 좋아요 버튼이 <code>한 페이지에 여러 개</code>가 존재함</li>
</ul>
<ol>
<li>forEach()</li>
<li>querySelectorAll()</li>
</ol>
<h3 id="html-완성-부분">HTML 완성 부분</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/6eeb50b8-9893-4321-8af2-f2e56abc359c/image.png" alt=""></p>
<h3 id="view-함수-완성-부분">View 함수 완성 부분</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/0db1e7a7-0739-491b-a1dd-c6f167a5c70d/image.png" alt=""></p>
<h3 id="javascript-완성-부분">JavaScript 완성 부분</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/9efbd3a8-9b4f-4975-a2d8-378165fd81d3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Asynchronous JavaScript]]></title>
            <link>https://velog.io/@turtle_hw/Asynchronous-JavaScript</link>
            <guid>https://velog.io/@turtle_hw/Asynchronous-JavaScript</guid>
            <pubDate>Mon, 30 Oct 2023 07:03:02 GMT</pubDate>
            <description><![CDATA[<h1 id="비동기">비동기</h1>
<h2 id="--synchronous동기">- Synchronous(동기)</h2>
<ul>
<li>프로그램의 실행 흐름이 순차적으로 진행</li>
<li>하나의 작업이 완료된 후에 다음 작업이 실행되는 방식</li>
</ul>
<h3 id="synchronous-예시">Synchronous 예시</h3>
<p><strong>1. 메인 작업이 모두 수행되어야 마지막 작업이 수행됨</strong></p>
<pre><code class="language-js">print(&#39;첫번째 작업&#39;)
for i in range(10):
    print(&#39;메인 작업&#39;)
print(&#39;마지막 작업&#39;) // 위의 반복문이 종료된 후에 실행됨</code></pre>
<p><strong>2. 함수의 작업이 완료될 때까지 기다렸다가 값을 반환해야 계속 진행할 수 있음 (동기 함수)</strong></p>
<pre><code class="language-js">const makeGreeting = function (name) {
    return &#39;Hello, my name is %{name}!&#39;
 }

 const name = &#39;Alice&#39;
 const greeing = makeGreeting(name)
 console.log(greeting) // &#39;Hello, my name is Alice!&#39;</code></pre>
<h2 id="--asynchronous비동기">- Asynchronous(비동기)</h2>
<ul>
<li>프로그램의 실행 흐름이 순차적이지 않으며, 작업이 완료되기를 기다리지 않고 다음 작업이 실행되는 방식</li>
<li>작업의 완료 여부를 신경쓰지 않고 동시에 다른 작업들을 수행할 수 있음</li>
</ul>
<h3 id="asynchronous-특징">Asynchronous 특징</h3>
<ul>
<li>병렬적 수행</li>
<li>당장 처리를 완료할 수 없고 시간이 필요한 작업들은 별도로 요청을 보낸 뒤 응답이 빨리 오는 작업부터 처리</li>
<li>나중에 가더라도 먼저 일이 끝나면 돌아오게 된다. </li>
</ul>
<h3 id="asynchronous-예시">Asynchronous 예시</h3>
<ol>
<li>Gmail에서 메일 전송을 누르면 목록 화면으로 전환되지만 실제로 메일을 보내는 작업은 병렬적으로 별도로 처리됨</li>
<li>브라우저는 웹페이지를 먼저 처리되는 요소부터 그려 나가며 처리가 오래 걸리는 것들은 별도로 처리가 완료 되는대로 병렬적으로 처리</li>
</ol>
<pre><code class="language-js">const slowRequest = function(callBack){
   console.log(&#39;1. 오래 걸리는 작업 시작 ...&#39;)
   setTimeout(function () {
        callBack()
   }, 3000)
}

const myCallBack = function () {
    console.log(&#39;2. 콜백함수 실행됨&#39;)
}

slowRequest(myCallBAck)

console.log(&#39;3. 다른 작업 실행&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/310ab77c-799b-4c36-af62-ceb2077c5613/image.png" alt=""></p>
<hr>
<h1 id="javascript와-비동기">JavaScript와 비동기</h1>
<p>Single Thread 언어, JavaScrpt</p>
<blockquote>
<p>Thread 란?</p>
</blockquote>
<ul>
<li>작업을 처리할 때 실제로 작업을 수행하는 주체로, multi-thread라면 업무를 수행할 수 있는 주체가 여러 개라는 의미</li>
</ul>
<h4 id="javascript는-한번에-여러-일을-수행할-수-없다">JavaScript는 한번에 여러 일을 수행할 수 없다</h4>
<ul>
<li>JavaScript는 한 번에 하나의 일만 수행할 수 있는 Single Thread 언어로 동시에 여러 작업을 처리할 수 없음</li>
<li>즉, JavaScript는 하나의 작업을 요청한 순서대로 처리할 수 밖에 없음</li>
<li>그럼 어떻게 Single Thread인 JavaScript가 비동기 처리를 할 수 있을까?</li>
</ul>
<h2 id="javascript-runtime">JavaScript Runtime</h2>
<ul>
<li>JavaScript가 동작할 수 있는 환경(Runtime)</li>
<li>JavaScript 자체는 Single Thread 이므로 비동기 처리를 할 수 있도록 도와주는 환경이 필요</li>
<li>JavaScript에서 비동기와 관련한 작업은 &#39;브라우저&#39; 또는 &#39;Node&quot;와 같은 환경에서 처리</li>
</ul>
<h2 id="브라우저-환경에서의-javascript-비동기-처리-관련-요소">브라우저 환경에서의 JavaScript 비동기 처리 관련 요소</h2>
<h3 id="1-javascript-engine의-call-stack">1. JavaScript Engine의 Call Stack</h3>
<ul>
<li>요청이 들어올 떄마다 순차적으로 처리하는 Stack(LIFO)</li>
<li>기본적인 JavaScript의 Single Thread 작업 처리</li>
</ul>
<h3 id="2-web-api">2. Web API</h3>
<ul>
<li>JavaScript 엔진이 아닌 <code>브라우저에서</code> 제공하는 runtime 환경(JavaScript 엔진은 하나밖에 처리 못하니까)</li>
<li>시간이 소요되는 작업을 처리 (setTimeout, DOM Event(이벤트 리스너), AJAX  요청 등)</li>
</ul>
<h3 id="3-task-queue">3. Task Queue</h3>
<ul>
<li>비동기 처리된 Callback 함수가 대기하는 Queue(FIFO)</li>
<li>먼저끝나면 먼저 나감</li>
</ul>
<h3 id="4-event-loop">4. Event Loop</h3>
<ul>
<li>태스크(작업)가 들어오길 기다렸다가 태스크가 들어오면 이를 처리하고, 처리할 태스크가 없는 경우엔 잠드는, 끊임없이 돌아가는 자바스크립트 내 루프</li>
<li>Call Stack과 Task Queue를 지속적으로 모니터링</li>
<li>Call Stack이 비어 있는지 확인 후 비어 있다면, Task Queue에서 대기 중인 오래된 작업을 Call Stack으로 Push</li>
</ul>
<blockquote>
<ol>
<li>모든 작업은 <code>Call Stack</code>(LIFO)으로 들어간 후 처리된다. </li>
<li>오래 걸리는 작업이 Call Stack으로 들어오면 <code>Web API</code>로 보내 별도로 처리하도록 한다. </li>
<li>Web API에서 처리가 끝난 작업들은 곧바로 Call Stack으로 들어가지 못하고 <code>Task Queue</code>(FIFO)에 순서대로 들어간다.</li>
<li><code>Event Loop</code>(감시자 역할)가 Call Stack이 비어있는 것을 계속 체크하고 Call Stack이 빈다면 Tasck Queue에서 가장 오래된 (가장 먼저 처리되어 들어온)작업을 Call Stack으로 보낸다. </li>
</ol>
</blockquote>
<h3 id="런타임의-시각적-표현">런타임의 시각적 표현</h3>
<blockquote>
<ul>
<li>런타임 = 브라우저의 환경
console.log(&#39;Hi&#39;) =&gt; Call Stack에 conlole.log(&#39;Hi&#39;) 들어간다 -&gt; 호출되면서 빠진다 -&gt; 그러면서 Output에 &#39;Hi&#39; 출력되면서 Call Stack 비게 되고 -&gt; setTimeout() Call stack에 들어감 -&gt; 3초 기다려야해서 Web API로 넘어가게 됨(처리중) -&gt; 빠지자 마자 console.log(&#39;Bye&#39;)가 Call Stack에 들어감 -&gt; console.log(&#39;Bye&#39;)가 빠지면서, output &#39;Bye&#39; 출력 -&gt; 스택이 비고 3초가 다 경과했으면 콜스택으로 돌아가는 것이 아니라 Task Queue(대기실)로 일처리가 끝난 순서로 들어간다. Event Loop이 계속 감시하고 있음( Call stack이 비었는지 확인 ) -&gt; myFunc() 를 콜스택에 넣고 console.log&#39;Work&#39; 호출되서 빠지면서 &#39;Work&#39;출력됨 -&gt; myfunc()까지 사라지면 완료!</li>
</ul>
</blockquote>
<blockquote>
<h2 id="정리">정리</h2>
</blockquote>
<ul>
<li>JavaScript는 한 번에 하나의 작업을 수행하는 Single Thread 언어로 동기적 처리를 진행</li>
<li>하지만 브라우저 환경에서는 Web API에서 처리된 작업이 지속적으로 Task Queue를 거쳐 Event Loop에 의해 Call Stack에 들어와 순차적으로 실행됨으로써 비동기 작업이 가능한 환경이 됨</li>
</ul>
<h1 id="ajax-💛">AJAX 💛</h1>
<h4 id="asynchronous-javascript--xml">Asynchronous JavaScript + XML</h4>
<ul>
<li>JavaScript의 비동기 구조와 XML 객체를 활용해 비동기적으로 서버(ex.장고로 만든 서버)와 통신하여 웹 페이지의 일부분만을 업데이트하는 웹 개발 기술(새로고침 없이)</li>
<li>&#39;X&#39;가 XML을 의미하긴 하지만, 요즘은 더 가벼운 용량과 JavaScript의 일부라는 장점 때문에 &#39;JSON&#39;을 더 많이 사용</li>
</ul>
<h2 id="xmlhttprequest-객체">XMLHttpRequest 객체</h2>
<p>(줄여서 XHR 객체라고 함)</p>
<ul>
<li>서버와 상호작용할 때 사용하며 페이지의 새로고침 없이도 URL에서 데이터를 가져올 수 있음</li>
<li>사용자의 작업을 방해하지 않고 페이지의 일부를 업데이트</li>
<li>주로 AJAX 프로그래밍에 많이 사용됨</li>
</ul>
<blockquote>
<p>이벤트 핸들러는 비동기 프로그래밍의 한 형태</p>
</blockquote>
<ul>
<li>이벤트가 발생할 때마다 호출되는 함수(콜백 함수)를 제공하는 것</li>
<li>XMLHttpRequest(XHR)는 JavaScript를 사용하여 서버에 HTTP 요청을 할 수 있는 객체</li>
<li>HTTP 요청은 응답이 올 때까지의 시간이 걸릴 수 있는 작업이라 비동기 API이며, 이벤트 핸들러를 XHR 객체에 연결해 요청의 진행 상태 및 최종 완료에 대한 응답을 받음</li>
</ul>
<h2 id="axios">Axios</h2>
<p><a href="https://axios-http.com/">Axios 설치_CDN 사용</a></p>
<pre><code class="language-html">&lt;script src=&quot;&quot;https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js&quot;&gt;&lt;/script&gt;</code></pre>
<ul>
<li>JavaScript에서 사용되는 HTTP 클라이언트 라이브러리</li>
<li><blockquote>
<p>서버와의 HTTP 요청과 응답을 간편하게 처리할 수 있도록 도와주는 도구</p>
</blockquote>
</li>
</ul>
<h3 id="axios-구조">Axios 구조</h3>
<ul>
<li>get, post 등 여러 http request method 사용 가능</li>
<li>then 메서드를 사용해서 <code>&#39;성공하면 수행할 로직&#39;</code>을 작성</li>
<li>catch 메서드를 사용해서 <code>&#39;실패하면 수행할 로직&#39;</code>을 작성</li>
</ul>
<pre><code class="language-js">axios({
  method: &#39;post&#39;,
  url: &#39;/user/12345/&#39;,
  data: {
    firstName: &#39;Fred&#39;,
    lastName: &#39;Flintstone&#39;
  }
})
  .then(요청에 성공하면 수행할 콜백함수)
  .catch(요청에 실패하면 수행할 콜백함수)</code></pre>
<ul>
<li>고양이 사진 가져오기 실습<ul>
<li>The Cat API (<a href="https://api.thecatapi.com/v1/images/search/)%7C">https://api.thecatapi.com/v1/images/search/)|</a>
이미지를 요청해서 가져오는 작업을 비동기로 처리</li>
</ul>
</li>
</ul>
<pre><code class="language-html"> &lt;script&gt;
    const URL = &#39;https://api.thecatapi.com/v1/images/search/&#39;
    axios ({
      method: &#39;get&#39;,
      url: URL,
    })
     .then((response) =&gt; {
      console.log(response)
      console.log(response.data)
     })
     .catch((error) =&gt; {
      console.log(error)
      console.log(&#39;실패했다옹&#39;)
     })
    console.log(&#39;야옹야옹&#39;)
  &lt;/script&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/cd3b212f-0a86-4967-a435-beb54ad573d8/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>요청 후 cat api로부터 응답을 기다려야 하는 작업은 비동기로 처리하기 때문에 &#39;야옹야옹&#39; 출력 이후 응답 데이터가 출력되는 것을 확인 할 수 있음</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/e2f817b4-fa25-4785-9f42-52bb44e3d1e8/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/2dcefbdb-d703-4b0a-9c75-66b2a55568d8/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="고양이-사진-가져오기-실습-심화">고양이 사진 가져오기 실습 심화</h3>
<ol>
<li>버튼을 누르면(이벤트 리스너)</li>
<li>고양이 이미지를 요청하고(axios)</li>
<li>요청이 처리되어 응답이 오면</li>
<li>응답 데이터에 있는 이미지 주소 값을 img 태그(DOM사용)에 넣어 이미지 출력하기</li>
</ol>
<table>
<thead>
<tr>
<th>버튼작성하고 axios 동작을 콜백 함수로 작성 및 이벤트 핸들러 부착</th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>응답 데이터에서 필요한 이미지 주소 값 찾기</th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>찾은 이미지 주소를 활용해 THML img 태그 구성하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/529f8f45-922d-4eaa-bcac-a679a927877d/image.png" alt=""></td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/51bd505d-316f-4f77-8da9-88181459c46f/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>결과 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/05132e62-0c80-4c3b-9c94-3bda1fdbf6da/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<h4 id="정리-1">정리</h4>
</blockquote>
<ul>
<li>axios는 브라우저에서 비동기로 데이터 통신을 가능하게 하는 라이브러리 : 브라우저를 위해 XMLHttpRequest 생성</li>
<li>같은 방식으로 DRF 로 만든 API 서버로 요청을 보내서 데이터를 받아온 후 처리할 수 있도록 함</li>
</ul>
<hr>
<h1 id="callback과-promise">Callback과 Promise</h1>
<h2 id="비동기-콜백">비동기 콜백</h2>
<blockquote>
<p>비동기 처리의 단점</p>
</blockquote>
<ul>
<li>비동기 처리의 핵심은  Web API로 들어오는 순서가 아니라 <code>작업이 완료되는 순서에 따라 처리</code>한다는 것</li>
<li>그런데 이는 개발자 입장에서 코드의 실행 순서가 불명확하다는 단점 존재</li>
<li>이와 같은 단점은 실행 결과를 예상하면서 코드를 작성할 수 없게 함
=&gt; 콜백 함수를 사용하자!!</li>
</ul>
<ul>
<li>비동기적으로 처리되는 작업이 완료되었을 때 실행되는 함수</li>
<li>연쇄적으로 발생하는 비동기 작업을 <code>순차적으로 동작</code>할 수 있게 함</li>
<li>작업의 순서와 동작을 제어하거나 결과를 처리하는 데 사용</li>
</ul>
<h3 id="비동기-콜백의-한계">비동기 콜백의 한계</h3>
<ul>
<li>비동기 콜백 함수는 보통 어떤 기능의 실행 결과를 받아서 다른 기능을 수행하기 위해 많이 사용됨</li>
<li>이 과정을 작성하다 보면 비슷한 패턴이 계속 발생<ul>
<li>A를 처리해서 결과가 나오면, 첫 번째 callback함수를 실행하고
첫번째 callback 함수가 종료되면, 두 번째 callback함수를 실행하고
두번째 callback 함수가 종료되면, 세 번째 callback함수를 실행하고
......
&quot;콜백 지옥 &quot; 발생</li>
</ul>
</li>
</ul>
<h3 id="콜백-지옥callback-hell">콜백 지옥(Callback Hell)</h3>
<ul>
<li>비동기 처리를 위한 콜백을 작성할 때 마주하는 문제</li>
<li>코드 작성 형태가 마치 &#39;피라미드와 같다&#39;고 해서 &quot;Pyramid of doom(파멸의 피라미드)&quot;라고도 부름</li>
</ul>
<blockquote>
<h3 id="콜백-함수-정리">콜백 함수 정리</h3>
</blockquote>
<ul>
<li><p>콜백 함수는 비동기 작업을 순차적으로 실행할 수 있게 하는 반드시 필요한 로직</p>
</li>
<li><p>비동기 코드를 작성하다 보면 콜백 함수로 인한 콜백 지옥은 빈번히 나타나는 문제이며 이는 코드의 가독성을 해치고 유지 보수가 어려워 짐
-&gt; 지옥에 빠지지 않는 다른 표기 형태가 필요하다!</p>
<hr>
</li>
</ul>
<h2 id="프로미스promise">프로미스(Promise)</h2>
<ul>
<li>JavaScript에서 비동기 작업의 결과를 나타내는 객체</li>
<li>비동기 작업이 완료되었을 때 결과 값을 반환하거나, 실패 시 에러를 처리할 수 있는 기능을 제공</li>
</ul>
<blockquote>
<ul>
<li>콜백 지옥 문제를 해결하기 위해 등장한 비동기 처리를 위한 객체</li>
</ul>
</blockquote>
<ul>
<li>&quot;작업이 끝나면 실행 시켜줄게&quot; 라는 약속(Promise)</li>
<li>비동기 작업의 완료 또는 실패를 나타내는 객체</li>
<li>Promise 기반의 클라이언트가 바로 이전에 사용한 Axios  라이브러리<ul>
<li>성공에 대한 약속 <code>then()</code> / 실패에 대한 약속 <code>catch()</code></li>
</ul>
</li>
</ul>
<h3 id="비동기-콜백-vs-promise">비동기 콜백 vs Promise</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/137551bc-c315-4027-8e19-746582a54672/image.png" alt=""></p>
<hr>
<h3 id="axios-1">Axios</h3>
<ul>
<li>JavaScript에서 사용되는 &#39;Promise 기반&#39; HTTP 클라이언트 라이브러리</li>
</ul>
<blockquote>
<h2 id="👀-then--catch">👀 then &amp; catch</h2>
<h3 id="thencallback">then(callback)</h3>
</blockquote>
<ul>
<li><p>요청한 작업이 성공하면 callback 실행</p>
</li>
<li><p>callback은 이전 작업의 성공 결과를 인자로 전달 받음</p>
<blockquote>
<h3 id="catchcallback">catch(callback)</h3>
</blockquote>
</li>
<li><p>then()이 하나라도 <code>실패하면</code> callback 실행</p>
</li>
<li><p>callback은 이전 작업의 실패 객체를 인자로 전달 받음</p>
</li>
<li><p>then과 catch는 모두 항상 promise 객체를 반환</p>
</li>
<li><p>즉, 계속해서 ✔<code>chaining</code>을 할 수 있음</p>
</li>
<li><p>axios로 처리한 비동기 로직이 항상 promise 객체를 반환</p>
</li>
<li><p>then을 계속 이어 나가면서 작성할 수 있게 됨
<img src="https://velog.velcdn.com/images/turtle_hw/post/da4a265b-4b2e-43df-b790-86907b9d26f1/image.png" alt=""></p>
</li>
</ul>
<h3 id="then메서드-chaining의-목적">then메서드 chaining의 목적</h3>
<ul>
<li>비동기 작업의 <code>&#39;순차적인&#39;</code> 처리 가능</li>
<li>코드를 보다 <code>직관적이고 가독성 좋게</code> 작성할 수 있도록 도움</li>
</ul>
<blockquote>
<h3 id="then-메서드-chaining의-장점">then 메서드 chaining의 장점</h3>
<p><strong>1. 가독성</strong>
     - 비동기 작업의 순서와 의존 관계를 명확히 표현할 수 있어 코드의 가독성이 향상
<strong>2. 에러 처리</strong>
    - 각각의 비동기 작업 단계에서 발생하는 에러를 분할에서 처리 가능
<strong>3. 유연성</strong>
    - 각 단계마다 필요한 데이터를 가공하거나 다른 비동기 작업을 수행할 수 있어서 더 복잡한 비동기 흐름을 구성할 수 있음 
<strong>4. 코드 관리</strong>
    - 비동기 작업을 분리하여 구성하면 코드를 관리하기 용이</p>
</blockquote>
<h3 id="then-메서드-chaining-예시">then 메서드 chaining 예시</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/b6e63ecc-7539-4c5f-bd10-c879b84f712c/image.png" alt=""></p>
<h3 id="promise가-보장하는-것vs-비동기-콜백">Promise가 보장하는 것(vs 비동기 콜백)</h3>
<ol>
<li>콜백 함수는 JavaScript의 Event Loop가 현재 실행 중인 Call Stack을 완료하기 이전에는 절대 호출되지 않음<ul>
<li>반면 Promise callback 함수는 Event Queue에 배치되는 엄격한 순서로 호출됨</li>
</ul>
</li>
<li>비동기 작업이 성공하거나 실패한 뒤에 .then() 메서드를 이용하여 추가한 경우에도 호출 순서를 보장하며 동작</li>
<li>.then()을 여러 번 사용하여 여러 개의 callback 함수를 추가할 수 있음<ul>
<li>각각의 callback은 주어진 순서대로 하나하나 실행하게 됨</li>
<li>chaining은 Promise의 가장 뛰어난 장점</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Controlling event]]></title>
            <link>https://velog.io/@turtle_hw/Controlling-event</link>
            <guid>https://velog.io/@turtle_hw/Controlling-event</guid>
            <pubDate>Wed, 25 Oct 2023 20:11:14 GMT</pubDate>
            <description><![CDATA[<h1 id="이벤트">이벤트</h1>
<blockquote>
<p>웹에서의 이벤트</p>
</blockquote>
<ul>
<li>버튼을 클릭했을 때 팝업 창이 출력되는 것</li>
<li>마우스 커서의 위치에 따라 드래그 앤 드롭하는 것</li>
<li>사용자의 키보드 입력 값에 따라 새로운 요소를 생성하는 것
=&gt; 일상에서의 이벤트처럼 웹에서도 이벤트를 통해** 특정 동작을 수행**한다. </li>
</ul>
<h2 id="event">event</h2>
<ul>
<li>무언가 일어났다는 신호, 사건 -&gt; 모든 DOM 요소는 이러한 event를 만들어 냄<h3 id="event-object">event object</h3>
</li>
<li>DOM에서 이벤트가 발생했을 때 생성되는 객체</li>
<li>이벤트 종류 : mouse, input, keyboard, touch...</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Event">이벤트 docs</a></li>
</ul>
<blockquote>
<p>DOM 요소는 evnet를 받고 받은 event를 &#39;처리&#39;(event handler_이벤트 처리기) 할 수 있음 </p>
</blockquote>
<h2 id="event-handler">event handler</h2>
<ul>
<li>이벤트가 발생헀을 때 실행되는 함수</li>
<li><blockquote>
<p>사용자의 행동에 어떻게 반응할지를 JavaScript 코드로 표현한 것</p>
</blockquote>
</li>
</ul>
<h3 id="addeventlistenertype-handler">.addEventListener(type, handler)</h3>
<ul>
<li>대표적인 이벤트 핸들러 중 하나</li>
<li>특정 이벤트를 DOM 요소가 수신할 때마나 <code>콜백 함수</code>를 호출</li>
</ul>
<blockquote>
<pre><code class="language-script">EventTarget.addEventListener(type, handler)
 DOM 요소                    수신할 이벤트 콜백함수 ``` </code></pre>
</blockquote>
<blockquote>
<ul>
<li>DOM 요소 - a태그가 될 수도 있고  p태그가 될 수도 잇고~</li>
</ul>
</blockquote>
<ul>
<li>수신 이벤트 - 정해진 이벤트 이름들을 사용할 것</li>
<li>콜백 함수에서 동작이 수행됨, 메인코드가 작성되는 곳
=&gt; 대상(DOM요소)에 특정 EVENT(수신할 이벤트)가 발생하면, 
지정한 이벤트를 받아 할 일(콜백 함수)을 등록한다. </li>
</ul>
<h4 id="type">type</h4>
<ul>
<li>수신할 이벤트 이름</li>
<li>문자열로 작성 (ex.&#39;click)</li>
</ul>
<h4 id="handler">handler</h4>
<ul>
<li>발생한 이벤트 객체를 수신하는 콜백 함수</li>
<li>콜백 함수는 발생한 Event object를 유일한 매개변수로 받음</li>
</ul>
<table>
<thead>
<tr>
<th>addEventListener 활용 (1/2)</th>
</tr>
</thead>
<tbody><tr>
<td>버튼을 클릭하면(click이벤트) 버튼 요소 출력하기</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b92b398d-7783-459c-ac9d-015e366bda02/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<p>버튼에 이벤트 처리기를 부착하여 클릭 이벤트가 발생하면 이벤트가 발생한 버튼 정보를 출력</p>
</blockquote>
<table>
<thead>
<tr>
<th>addEventListener 활용(2/2)</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/83726693-2586-4f3a-a608-2f3cd16dae6d/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<p>요소에 addEventListenr를 부착하게 되면 내부의 this값은 대상 요소를 가리키게 됨 (evnet 객체의 currentTarget 속성 값과 동일)</p>
</blockquote>
<h4 id="addeventlistner의-콜백-함수-특징">addEventListner의 콜백 함수 특징</h4>
<ul>
<li>발생한 이벤트를 나타내는 Event 객체를 유일한 매개변수로 받음</li>
<li>아무것도 반환하지 않음</li>
<li>값을 매기기 위한 것이아니라 행동을 하기 위한 것이기 때문에 무언가를 반환하는 것이 아니다. (?)</li>
</ul>
<hr>
<h1 id="버블링bubbling">버블링(Bubbling)</h1>
<ul>
<li>핸들러는 form 요소에 할당되어 있지만 div나 p요소와 같은 중첩된 요소를 클릭해도 동작함 -&gt; div나 p를 클릭했는데 왜 form에 할당된 핸들러가 동작할까?
<img src="https://velog.velcdn.com/images/turtle_hw/post/0aa6b39d-cb6c-45d8-9539-e64ef0d928f6/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/fd07e985-2fc7-4932-8d9d-0258b4dde50d/image.png" alt=""></li>
</ul>
<blockquote>
<p><strong>한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작하는 현상</strong></p>
</blockquote>
<ul>
<li>가장 최상단의 조상 요소(document)를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작</li>
<li><blockquote>
<p>이벤트가 제일 깊은 곳에 있는 요소에서 시작해 부모 요소를 거슬러 올라가며 발생하는 것이 마치 물속 거품과 닯았음</p>
</blockquote>
</li>
</ul>
<table>
<thead>
<tr>
<th>버블링 예시</th>
</tr>
</thead>
<tbody><tr>
<td>가장 안쪽의 <code>&lt;p&gt;</code>요소를 클릭하면 p-&gt; div -&gt; form 순서로 3개의 이벤트 핸들러가 동작함</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b84038ce-1444-4112-8a09-7860445b23a4/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h4 id="이벤트가-정확히-어디서-발생했는지-접근할-수-있는-방법">이벤트가 정확히 어디서 발생했는지 접근할 수 있는 방법</h4>
<blockquote>
<p><strong>event.target</strong>  / <strong>event.currentTarget</strong></p>
</blockquote>
<h2 id="target--currenttarget-속성">&#39;target&#39; &amp; currentTarget&#39; 속성</h2>
<h3 id="target-속성">&#39;target&#39; 속성</h3>
<ul>
<li>이벤트가 발생한 가장 안쪽의 요소(target)를 참조하는 속성</li>
<li>실제 이벤트가 시작된 target 요소</li>
<li>버블링이 진행되어도 변하지 않음</li>
</ul>
<h3 id="currenttarget-속성">&#39;currentTarget&#39; 속성</h3>
<ul>
<li>&#39;현재&#39; 요소</li>
<li>항상 이벤트 핸들러가 연결된 요소만을 참조하는 속성</li>
<li><code>&#39;this&#39;와 같음</code></li>
</ul>
<table>
<thead>
<tr>
<th>&#39;target&#39; &amp; currentTarget&#39; 예시</th>
</tr>
</thead>
<tbody><tr>
<td>세 요소 중 가장 최상위 요소인 outerouter요소에만 이벤트 핸들러가 부착</td>
</tr>
<tr>
<td>각 요소를 클릭 했을 때 event의 target과 currentTarget의 차이 비교</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/077de1d5-651a-4633-80f1-fd17a75a96ae/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<p><strong>target</strong>  - 실제 이벤트가발생하는 요소를 가리킴
<strong>currentTarget</strong> - 핸들러가 연결된 outerouter요소만을 가리킴</p>
</blockquote>
<blockquote>
<ul>
<li>핸들러는 outerouter에 하나밖에 없지만 이 핸들러에서 outerouter의 내부 모든 하위 요소에서 발생하는 클릭 이벤트를 잡아내고 있음</li>
</ul>
</blockquote>
<ul>
<li>클릭 이벤트가 어디서 발생했든 상관없이 outerouter까지 이벤트가 버블링 되어 핸들러를 실행시키기 때문</li>
</ul>
<h1 id="event-handler-활용">event handler 활용</h1>
<p><strong>1. 버튼을 클릭하면 숫자를 1씩 증가해서 출력하기</strong></p>
<table>
<thead>
<tr>
<th>click 이벤트 실습 _ 버튼을 클릭하면 숫자를 1씩 증가</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/3b686e47-f36f-4163-a925-57ccff0454f9/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/75a9c37c-9a4f-45fb-9086-943f99eef398/image.png" alt=""></td>
</tr>
</tbody></table>
<p><strong>2. 사용자의 입력 값을 실시간으로 출력하기</strong></p>
<table>
<thead>
<tr>
<th>input 이벤트 실습 _  사용자의 입력 값을 실시간으로 출력하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/906ce4e7-d26a-4020-99dc-90c580cdd1e1/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/04f128c0-3215-4ffb-a1a1-3335ca93d500/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<p><strong>currentTarget 주의사항</strong></p>
</blockquote>
<ul>
<li>consol.log()로 evnet 객체를 출력할 경우 currentTarget 키의 값은 null을 가짐</li>
<li>currentTarget은 이벤트가 처리되는 동안에만 사용할 수 있기 때문</li>
<li>대신 console.log(event.currentTarget)을 사용하여 콘솔에서 확인 가능</li>
<li><blockquote>
<p>currentTarget 이후의 속성 값들은 &#39;target&#39;을 참고해서 사용하기 </p>
</blockquote>
</li>
</ul>
<p><strong>3. &#39;+&#39; 버튼을 입력하면 출력한 값의 CSS 스타일을 변경하기</strong></p>
<table>
<thead>
<tr>
<th>click &amp; input 이벤트 실습 _  사용자의 입력 값을 실시간으로 출력 + 버튼을 입력하면 출력한 값의 CSS 스타일을 변경</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b77d0e11-c2b1-4484-9894-37a2e5d91ab3/image.png" alt=""></td>
</tr>
</tbody></table>
<p><strong>4. todo 프로그램 구현</strong></p>
<table>
<thead>
<tr>
<th>Todo 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/c65d348c-c9e9-49ca-aed2-7ed999c1a9f4/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/5ae82ec4-ac96-4651-9db9-9c7366037e00/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>Todo 기능 추가</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/240004f5-cb88-4a36-a419-e478a1624701/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<ol>
<li>빈 문자열 입력 방지</li>
<li>입력이 없을 경우 경고 대화상자를 띄움</li>
</ol>
</blockquote>
<p><strong>5. 로또 번호 생성기 구현</strong>
<a href="https://lodash.com/docs/4.17.15#random">https://lodash.com/docs/4.17.15#random</a></p>
<table>
<thead>
<tr>
<th>로또 번호 생성기 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/4eb8a2c6-5d96-4bb5-b7cb-8801edece786/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="lodash"><a href="https//loadash.com/">lodash</a></h2>
<ul>
<li>모듈성, 성능 및 추가 기능을 제공하는 JavaScript 유틸리티 라이브러리 </li>
<li>array, object 등 자료구조를 다룰 때 사용하는 유용하고 간편한 함수들을 제공</li>
</ul>
<h1 id="이벤트-기본-동작-취소">이벤트 기본 동작 취소</h1>
<h2 id="preventdefault">.preventDefault()</h2>
<ul>
<li>해당 이벤트에 대한 기본 동작을 실행하지 않도록 지정</li>
</ul>
<table>
<thead>
<tr>
<th>copy 이벤트 동작 취소</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/48a9cd16-d5cf-4fcb-b35c-2de33fd0cdd8/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/17ba0ffe-525b-4197-bf84-61d43d0cf118/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>form 제출 시 새로고침 동작 취소</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/bdcf34a3-bf3f-454a-bd90-0ac5cb0a9759/image.png" alt=""></td>
</tr>
<tr>
<td></td>
</tr>
</tbody></table>
<h3 id="참고_addeventlistener에서의-화살표-함수-주의사항">참고_addEventListener에서의 화살표 함수 주의사항</h3>
<ul>
<li>화살표 함수는 자신만의 this를 가지지 않기 때문에 자신을 포함하고 있는 함수의 this를 상속받음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript_참조 자료형]]></title>
            <link>https://velog.io/@turtle_hw/JavaScript-3bsl445t</link>
            <guid>https://velog.io/@turtle_hw/JavaScript-3bsl445t</guid>
            <pubDate>Wed, 25 Oct 2023 02:21:31 GMT</pubDate>
            <description><![CDATA[<h1 id="함수">함수</h1>
<ul>
<li>Fuction : <code>참조 자료형</code>에 속하며 모든 함수는 Function object</li>
<li>참조 자료형 = &gt; 객체의 주소가 저장되는 자료형(가변, 주소가 복사)<h2 id="함수-구조">함수 구조</h2>
</li>
<li>함수의 이름 / 함수의 매개변수 / 함수의 body를 구성하는 statement </li>
<li>return 값이 없다면 undefined를 반환</li>
</ul>
<h2 id="함수-정의-2가지-방법">함수 정의 2가지 방법</h2>
<ol>
<li>선언식(function declaration)</li>
<li>표현식(function expression)</li>
</ol>
<blockquote>
<h3 id="함수-표현식-특징">함수 표현식 특징</h3>
<ul>
<li>함수 이름이 없는 &#39;익명 함수&#39;를 사용할 수 있음</li>
</ul>
</blockquote>
<ul>
<li>선언식과 달리 표현식으로 정의한 함수는 호이스팅 되지 않으므로 함수를 정의하기 전에 먼저 사용할 수 없음
<img src="https://velog.velcdn.com/images/turtle_hw/post/16fc7284-393c-465d-b345-c7c2bbdc400c/image.png" alt=""></li>
</ul>
<hr>
<h2 id="함수-선언식과-표현식-종합">함수 선언식과 표현식 종합</h2>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/1f5626c4-c32f-4393-9a88-9c421fcd9ef0/image.png" alt=""></p>
<hr>
<h2 id="매개변수-정의-방법">매개변수 정의 방법</h2>
<h3 id="1-기본-함수-매개변수">1. 기본 함수 매개변수</h3>
<ul>
<li>값이 없거나 undefined가 전달될 경우 이름 붙은 매개변수를 기본값으로 초기화
<img src="https://velog.velcdn.com/images/turtle_hw/post/27e3c93e-3d84-4c33-9b0a-d98b4e2c604f/image.png" alt=""></li>
</ul>
<h3 id="2-나머지-매개변수">2. 나머지 매개변수</h3>
<ul>
<li>가변인자(파이썬)</li>
<li>임의의 수의 인자를 &#39;배열&#39;로 허용하여 가변 인자를 나타내는 방법</li>
<li>작성 규칙<ul>
<li>함수 정의 시 나머지 매개변수 하나만 작성할 수 있음</li>
<li>나머지 매개변수는 함수 정의에서 매개변수 마지막에 위치해야 함
<img src="https://velog.velcdn.com/images/turtle_hw/post/a49f323e-7c40-41c9-a48b-02eb3453b7da/image.png" alt=""></li>
</ul>
</li>
</ul>
<h2 id="매개변수와-인자의-개수-불일치">매개변수와 인자의 개수 불일치</h2>
<ul>
<li>매개변수 개수 &gt; 인자 개수 : 누락된 인자는 undefined로 할당</li>
<li>매개변수 개수 &lt; 인자 개수 : 초과 입력한 인자는 사용하지 않음</li>
</ul>
<hr>
<h2 id="spread-syntax-">Spread syntax &#39;...&#39;</h2>
<p><code>...</code> - 전개 구문</p>
<ul>
<li>배열이나 문자열과 같이 반복 가능한 항목들을 펼치는 것(확장, 전개)</li>
<li>전개 대상에 따라 역할이 다름<ul>
<li>배열이나 객체의 요소를 개별적인 값으로 분리하거나 다른 배열이나 객체의 요소를 현재 배열이나 객체에 추가하는 등</li>
</ul>
</li>
</ul>
<ol>
<li><p>함수와의 사용</p>
<blockquote>
<p>1_1. 함수 호출 시 인자 확장 - 언패킹</p>
</blockquote>
<ul>
<li>요소 1,2,3을 각자의 위치에 맞춰서 풀어낸 것
<img src="https://velog.velcdn.com/images/turtle_hw/post/8e2d1f98-b925-4877-b867-4dd3d08b5cd2/image.png" alt="">   </li>
</ul>
<blockquote>
<p>1_2. 나머지 매개변수 (압축) - 패킹
<img src="https://velog.velcdn.com/images/turtle_hw/post/4518f877-ad40-4590-ab08-1cbf9c18a5a6/image.png" alt=""></p>
</blockquote>
</li>
<li><p>객체와의 사용(객체 파트에서 진행)</p>
</li>
<li><p>배열과의 활용(배열 파트에서 진행)</p>
</li>
</ol>
<h3 id="화살표-함수">화살표 함수</h3>
<ul>
<li>함수 표현식의 간결한 표현법</li>
</ul>
<ol>
<li>function 키워드 제거 후 매개변수와 중괄호 사이에 화살표 작성
<img src="https://velog.velcdn.com/images/turtle_hw/post/e7754f12-b57d-496c-943d-e454d97a6315/image.png" alt=""></li>
<li>함수의 매개변수가 하나 뿐이라면, 매개변수의 &#39;()&#39; 제거 가능 (단, 생략하지 않는 것을 권장)</li>
<li>함수 본문의 표현식이 한 줄이라면, &#39;{}&#39;와 &#39;return&#39; 제거 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/adc73445-078d-403c-8917-bdb785f79eed/image.png" alt=""></li>
</ol>
<blockquote>
<p>화살표 함수 심화
<img src="https://velog.velcdn.com/images/turtle_hw/post/323b9a55-d519-4ffa-aa48-efd5ef861f64/image.png" alt=""></p>
</blockquote>
<hr>
<h1 id="객체">객체</h1>
<h2 id="object">Object</h2>
<ul>
<li>키로 구분된 데이터 집합을 저장하는 자료형(data collection)</li>
</ul>
<h2 id="객체-구조-및-속성">객체 구조 및 속성</h2>
<h3 id="객체-구조">객체 구조</h3>
<ul>
<li>중괄호를 이용해 작성</li>
<li>중괄호 안에는 key:value 쌍으로 구성된 속성(property) 를 여러 개 작성 가능</li>
<li>key는 문자형만 허용</li>
<li>value 는 모든자료형 허용</li>
</ul>
<h3 id="속성-참조">속성 참조</h3>
<ul>
<li><code>점</code>(&#39;.&#39;, chaining operator)또는 <code>대괄호</code>([])로 객체 요소 접근</li>
<li>key 이름에 띄어쓰기 같은 구분자가 있으면 대괄호 접근만 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/9c983b0f-bafb-47c2-8ab2-7c10f1416626/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/ef60cc3c-3ab2-4ed7-aeb4-87324c32a36d/image.png" alt=""></li>
</ul>
<h3 id="in-연산자">&#39;in&#39; 연산자</h3>
<ul>
<li>속성이 객체에 존재하는지 여부를 확인<pre><code class="language-html">console.log(&#39;greeting&#39; in user) // true
console.log(&#39;country&#39; in user) // false</code></pre>
</li>
</ul>
<hr>
<h2 id="객체와-함수">객체와 함수</h2>
<h3 id="method">Method</h3>
<p>: 객체 속성에 정의된 함수</p>
<ul>
<li>object.method() 방식으로 호출</li>
<li>메서드는 객체를 &#39;행동&#39;할 수 있게 함</li>
<li>&#39;this&#39; 키워드를 사용해 객체에 대한 특정한 작업을 수행할 수 있음</li>
</ul>
<h3 id="this-keyword">&#39;this&#39; keyword</h3>
<ul>
<li>함수나 메서드를 호출한 객체를 가리키는 키워드</li>
<li><blockquote>
<p>함수 내에서 객체의 속성 및 메서드에 접근하기 위해 사용
<img src="https://velog.velcdn.com/images/turtle_hw/post/a3583a66-ef7c-4a28-bd0e-8827bd5c85d6/image.png" alt=""></p>
</blockquote>
</li>
<li>JavaScript 에서 this는 함수를 &#39;호출하는 방법&#39;에 따라 가리키는 대상이 다름
<img src="https://velog.velcdn.com/images/turtle_hw/post/c608ff5a-0108-4965-90d9-45e74b7ee249/image.png" alt=""></li>
</ul>
<ol>
<li>단순 호출 시 this</li>
</ol>
<ul>
<li>가리키는 대상 =&gt; 전역 개체(document 위에 window있음)</li>
</ul>
<ol start="2">
<li>메서드 호출 시 this</li>
</ol>
<ul>
<li>가리키는 대상 =&gt; 메서드를 호출한 객체</li>
</ul>
<ol start="3">
<li>중첩된 함수에서의 this 문제점과 해결책</li>
</ol>
<table>
<thead>
<tr>
<th>문제점</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/ef782a11-dadd-4d99-8555-94ef57bec5f7/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>해결책</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/2ec15af2-cfde-4a5a-9591-2d7acc1a0dc4/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/04aa37e0-cb86-44d9-8e67-c9e44c69c1de/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="javascript-this-정리">JavaScript &#39;this&#39; 정리</h3>
<ul>
<li>JavaScript에서 &#39;this&#39;는 &#39;호출되는 방식(단순/메서드)&#39;에 따라 결정되는 현재 객체를 나타냄</li>
<li>JavaScript의 함수는 호출될 때 &#39;this&#39;를 암묵적으로 전달 받음</li>
<li>Python의 self와 Java의 this가 선언 시 값이 이미 정해지는 것에 비해 JavaScript의 this는 함수가 호출되기 전까지 값이 할당되지 않고 호출 시에 결정됨 (동적 할당이라고 한다)</li>
</ul>
<h2 id="추가-객체-문법">추가 객체 문법</h2>
<h3 id="1-단축-속성">1. 단축 속성</h3>
<ul>
<li>키 이름과 값으로 쓰이는 변수의 이름이 같은 경우, 단축 구문을 사용할 수 있다. 
<img src="https://velog.velcdn.com/images/turtle_hw/post/1653a117-105c-4107-80be-8526751b541b/image.png" alt=""></li>
</ul>
<h3 id="2-단축-메서드">2. 단축 메서드</h3>
<ul>
<li>메서드 선언 시 function 키워드 생략 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/9966f22d-a359-4ac3-b02b-aa485a1ef1f0/image.png" alt=""></li>
</ul>
<h3 id="3-계산된-속성computed-property-name">3. 계산된 속성(computed property name)</h3>
<ul>
<li>키가 대괄호([])로 둘러싸여 있는 속성</li>
<li>고정된 값이 아닌 변수 값을 사용할 수 있음
<img src="https://velog.velcdn.com/images/turtle_hw/post/0a68aefd-86d9-4a79-bce3-2d49233f196c/image.png" alt=""></li>
</ul>
<h3 id="★-4-구조-분해-할당destructing-assignment-★">★ 4. 구조 분해 할당(destructing assignment) ★</h3>
<ul>
<li><p>배열 또는 객체를 분해하여 속성을 변수에 쉽게 할당할 수 있는 문법
<img src="https://velog.velcdn.com/images/turtle_hw/post/6ef7551e-9f3b-4c1d-b1d7-8f1aba0cbd00/image.png" alt=""></p>
</li>
<li><p>&#39;함수의 매개변수&#39;로 객체 구조 분해 할당 활용 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/21c1d32f-e66e-4802-88a8-0af1bd5542b5/image.png" alt=""></p>
</li>
</ul>
<h3 id="5-object-with-전개-구문">5. Object with &#39;전개 구문&#39;</h3>
<ul>
<li>&quot;객체 <code>복사</code>&quot; : 객체 내부에서 객체 전개</li>
<li>얕은 복사에 활용 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/788a9cc4-fe8b-4ff5-b484-b0334b96f29f/image.png" alt=""></li>
</ul>
<h3 id="6-유용한-객체-메서드">6. 유용한 객체 메서드</h3>
<ul>
<li>Object.keys()</li>
<li>Object.values()
<img src="https://velog.velcdn.com/images/turtle_hw/post/0dd4c1d8-6c88-4602-8167-95532d49910a/image.png" alt=""></li>
</ul>
<h3 id="optional-chaining">Optional chaining(&#39;?.&#39;)</h3>
<ul>
<li>속성이 없는 <code>중첩 객체</code>를 에러 없이 접근할 수 있음</li>
<li>만약 참조 대상이 null 또는 undefined라면 에러가 발생하는 것 대신 평가를 멈추고 undefined를 반환
<img src="https://velog.velcdn.com/images/turtle_hw/post/01c2f91b-b348-43fd-a3d5-14b5c2bde0bc/image.png" alt=""></li>
<li>Optional chaining 이 없다면 &#39;&amp;&amp;&#39;연산자를 사용해야 함</li>
</ul>
<blockquote>
<p><strong>장점</strong></p>
</blockquote>
<ul>
<li><code>참조가 누락될 가능성이 있는 경우</code> 연결된 속성으로 접근할 때 더 짧고 간단한 표현식을 작성할 수 있음(에러 예방)</li>
<li>어떤 속성이 필요한지에 대한 보증이 확실하지 않은 경우에 객체의 내용을 보다 편리하게 탐색 할 수 있음</li>
</ul>
<blockquote>
<p><strong>주의사항</strong></p>
</blockquote>
<ol>
<li>Optional chaining은 존재하지 않아도 괜찮은 대상에만 사용해야 함(남용X)    <ul>
<li>왼쪽 평가대상이 없어도 괜찮은 경우만 선택적으로 사용
<img src="https://velog.velcdn.com/images/turtle_hw/post/6b40f640-01e7-43ed-ac96-fa5505cf03e2/image.png" alt=""></li>
</ul>
</li>
<li>Optional chaining 앞의 변수는 반드시 선언되어 있어야 함</li>
</ol>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/70fd3750-907c-4005-9aca-83c375825dc5/image.png" alt=""></p>
<h2 id="json">JSON</h2>
<ul>
<li>&#39;JavaScript Object Notation&#39;</li>
<li>Key-Value 형태로 이루어진 자료 표기법</li>
<li>JavaScript의 Object와 유사한 구조를 가지고 있지만 JSON은 형식이 있는 <code>&#39;문자열&#39;</code></li>
<li>JavaScript에서 JSON을 사용하기 위해서는 Object 자료형으로 변경해야 함</li>
</ul>
<h3 id="object---json-변환하기">Object &lt;-&gt; JSON 변환하기</h3>
<p>stringify
parse</p>
<h3 id="new-연산자">new 연산자</h3>
<ul>
<li>사용자 정의 객체 타입을 생성</li>
<li>매개변수<ol>
<li>constructor : 객체 인스턴스의 타입을 기술(명세)하는 함수<ol start="2">
<li>arguments : constructor와 함께 호출될 값 목록</li>
</ol>
</li>
</ol>
</li>
</ul>
<blockquote>
<pre><code class="language-html"> new constructor [([arguments])]```</code></pre>
</blockquote>
<hr>
<h1 id="배열">배열</h1>
<h2 id="object-1">Object</h2>
<ul>
<li>키로 구분된 데이터 집합을 저장하는 자료형 : 이제는 순서가 있는 collection이 필요</li>
</ul>
<h2 id="array">Array</h2>
<ul>
<li>순서가 있는 데이터 집합을 저장하는 자료 구조</li>
</ul>
<h2 id="배열구조">배열구조</h2>
<ul>
<li>대괄호<code>[]</code>를 이용해 작성</li>
<li>length속성을 이용해 배열에 담긴 요소가 몇 개인지 알 수 있음</li>
<li>배열 요소 자료형 : 제약 없음</li>
<li>자바스크립트에는 음수 인덱스가 없다 !!</li>
</ul>
<h2 id="배열과-메서드">배열과 메서드</h2>
<ul>
<li>push / pop : 배열 끝 요소를 추가 / 제거</li>
<li>unshift / shift : 배열 앞 요소를 추가 / 제거</li>
</ul>
<h3 id="pop">pop()</h3>
<ul>
<li>배열 끝 요소를 제거하고, 제거한 요소를 반환</li>
</ul>
<h3 id="push">push()</h3>
<ul>
<li>배열 끝에 요소를 추가</li>
</ul>
<h3 id="shift">shift()</h3>
<ul>
<li>배열 앞 요소를 제거하고, 제거한 요소를 반환</li>
</ul>
<h3 id="unshift">unshift()</h3>
<ul>
<li>배열 앞에 요소를 추가 </li>
</ul>
<hr>
<h2 id="array-helper-method-★★">Array helper method ★★</h2>
<ul>
<li>배열을 <code>순회</code>하며 <code>특정 로직을 수행</code>하는 메서드</li>
<li>메서드 호출 시 인자로 함수를 받는 것이 특징(콜백 함수)
<img src="https://velog.velcdn.com/images/turtle_hw/post/65604f7d-6345-43e7-96b1-378de7b738c1/image.png" alt=""></li>
</ul>
<blockquote>
<h3 id="foreach">forEach()</h3>
</blockquote>
<ul>
<li>인자로 주어진 함수 (콜백 함수)를 배열 요소 각각에 대해 실행</li>
<li>리턴이 없다. (undefined)</li>
<li>콜백 함수 
<code>arr.forEach(callback(item[,index[,array]]))</code><blockquote>
<blockquote>
<p>3가지 매개변수로 구성</p>
</blockquote>
</blockquote>
<ol>
<li>item : 처리할 배열의 요소</li>
<li>index : 처리할 배열 요소의 인덱스(선택 인자)</li>
<li>array : forEach를 호출한 배열(선택 인자)<blockquote>
<blockquote>
<blockquote>
<p>반환 값 : undefined</p>
</blockquote>
</blockquote>
</blockquote>
</li>
</ol>
</li>
</ul>
<h3 id="콜백-함수callback-function">콜백 함수(Callback function)</h3>
<ul>
<li>다른 함수에 인자로 전달되는 함수
-&gt; 외부 함수 내에서 호출되어 일종의 루틴이나 특정 작업을 진행<ul>
<li>배열의 요소에다가 우리가 원하는 로직을 적용시킬때 사용한다. </li>
</ul>
</li>
</ul>
<blockquote>
<h3 id="map">map()</h3>
</blockquote>
<ul>
<li>배열 내의 모든 요소 각각에 대해 함수(콜백함수)를 호출하고, 함수 호출 결과를 모아 <code>새로운 배열을 반환</code></li>
<li>반환이 있어서 리턴이 있다. </li>
<li>length ?? &lt;-여기 강의 다시보기-&gt;
<code>arr.map(callback(item[,index[,array]]))</code></li>
</ul>
<ol>
<li>item : 처리할 배열의 요소</li>
<li>index : 처리할 배열 요소의 인덱스(선택 인자)</li>
<li>array : map을 호출한 배열(선택 인자)<blockquote>
<blockquote>
<p>반환 값 : 배열의 각 요소에 대해 실행한 &#39;callback의 결과를 모은 새로운 배열&#39; -&gt; 기본적으로 forEach 동작 원리와 같지만 forEach와 달리 새로운 배열을 반환함</p>
</blockquote>
</blockquote>
</li>
</ol>
<hr>
<h3 id="python에서의-map-함수와-비교">python에서의 map 함수와 비교</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/2e5b4c65-437a-4786-a269-c623147b0f9c/image.png" alt=""></p>
<h2 id="배열-순회-종합">배열 순회 종합</h2>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/4e73a804-1e78-4590-9501-9590e7ef6c76/image.png" alt=""></p>
<ul>
<li>forEach에서 break, continue 사용 불가능</li>
</ul>
<h2 id="추가-배열-문법">추가 배열 문법</h2>
<h3 id="1-array-with-전개구문">1. Array with &#39;전개구문&#39;</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/357d3da4-7221-465c-a682-3b2de6b0a4bf/image.png" alt=""></p>
<h3 id="2-array-helper-methods">2. Array Helper Methods</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/fb36cd87-9b4b-49a7-b51b-86dc28556706/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Basic syntax of JavaScript]]></title>
            <link>https://velog.io/@turtle_hw/Basic-syntax-of-JavaScript</link>
            <guid>https://velog.io/@turtle_hw/Basic-syntax-of-JavaScript</guid>
            <pubDate>Tue, 24 Oct 2023 02:02:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>ECMAScript 2015(EX6) 이후의 명제를 따름
<a href="https://standardjs.com/rules-kokr.html">권장 스타일 가이드</a></p>
</blockquote>
<h1 id="변수">변수</h1>
<h2 id="식별자변수명-작성-규칙">식별자(변수명) 작성 규칙</h2>
<ul>
<li>반드시 문자, 달러($) 또는 밑줄(_)로 시작</li>
<li>대소문자를 구분</li>
<li>예약어 사용 불가(for, if, function 등)</li>
<li>🚩 카멜 케이스(camelCase) : 변수, 객체, 함수에 사용</li>
<li>파스칼 케이스(PascalCase) : 클래스, 생성자에 사용</li>
<li>대문자 스네이크 케이스(SNAKE_CASE) : 상수(constants)에 사용</li>
</ul>
<hr>
<h2 id="변수-선언-키워드">변수 선언 키워드</h2>
<h3 id="1-let">1. let</h3>
<ul>
<li>블록 스코프(block scope)(중괄호 사이의 영역)를 갖는 지역 변수를 선언</li>
<li>재할당 <code>가능</code></li>
<li>재선언 불가능</li>
<li>ES6에서 추가</li>
<li>초기값 없이 선언하면 undefined 라고 들어간다</li>
</ul>
<h3 id="2-const">2. const</h3>
<ul>
<li>블록 스코프를 갖는 지역 변수를 선언</li>
<li>재할당 불가능</li>
<li>재선언 불가능</li>
<li>ES6에서 추가</li>
<li>선언 시 반드시 초기값 설정 필요!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/09ede106-39b0-4df7-a7c6-d904fbed0aa1/image.png" alt=""></p>
<h3 id="3-블록-스코프block-scope">3. 블록 스코프(block scope)</h3>
<ul>
<li>if, for, 함수 등의 &#39;중괄호({}) 내부&#39;를 가리킴</li>
<li>블록 스코프를 가지는 변수는 블록 바깥에서 접근 불가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/0f619f06-f9fd-4878-b1dc-5ec10d7610d9/image.png" alt=""></li>
</ul>
<blockquote>
<p><strong>변수 선언 키워드 정리</strong></p>
</blockquote>
<ul>
<li>기본적으로 const 사용을 권장</li>
<li>재할당이 필요한 변수는 let으로 변경해서 사용</li>
</ul>
<hr>
<h1 id="데이터-타입">데이터 타입</h1>
<h2 id="1-원시-자료형primitive-type">1. 원시 자료형(Primitive type)</h2>
<p>: Number, String, Boolean, undefined, null</p>
<ul>
<li>변수에 값이 직접 저장되는 자료형(불변, 값이 복사)</li>
</ul>
<table>
<thead>
<tr>
<th>대문자로 바꾸는 메서드를 써도 변함이 없다</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/c0574b4a-d0ba-4780-ba07-0e0bc4bfb975/image.png" alt=""></td>
</tr>
</tbody></table>
<ul>
<li>변수에 할당될 때 값이 복사됨 </li>
</ul>
<table>
<thead>
<tr>
<th>-&gt; 변수 간에 서로 영향을 미치지 않음</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/34d6cac4-1723-4208-9421-8cf05773cc3a/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="1_1-number">1_1. Number</h3>
<ul>
<li>정수 또는 실수형 숫자를 표현하는 자료형</li>
</ul>
<h3 id="1_2-string">1_2. String</h3>
<ul>
<li>텍스트 데이터를 표현하느 자료형</li>
<li>&#39;+&#39;연산자를 사용해 문자열끼리 결합</li>
<li>곱셈, 나눗셈, 뺄셈 불가능</li>
</ul>
<h3 id="template-literals템플릿-리터럴">Template literals(템플릿 리터럴)</h3>
<ul>
<li>내장된 표현식을 허용하는 문자열 작성 방식</li>
<li>Backtick(``) 을 이용하여, 여러 줄에 걸쳐 문자열을 정의할 수도 있고  JavaScript의 변수를 문자열 안에 바로 연결할 수 있음</li>
<li>표현식은 <code>&#39;$&#39;</code>와 중괄호<code>(${expression})</code>로 표기</li>
<li>ES6+ 부터 지원
<img src="https://velog.velcdn.com/images/turtle_hw/post/7acc8dc9-050f-406a-af36-4d6e2ecfa908/image.png" alt=""></li>
</ul>
<hr>
<h2 id="null-과-undefined">null 과 undefined</h2>
<blockquote>
<p>값이 없음을 표현한다</p>
</blockquote>
<h3 id="1_3-null">1_3. null</h3>
<ul>
<li>변수의 값이 없음을 <code>의도적</code>으로 표현할 때 사용</li>
</ul>
<h3 id="1_4-undefined">1_4. undefined</h3>
<ul>
<li>변수 선언 이후 직접 값을 할당하지 않으면 <code>자동</code>으로 할당됨</li>
</ul>
<blockquote>
<p><strong>값이 없음에 대한 표현이  null과 undefined 2가지인 경우</strong></p>
</blockquote>
<ul>
<li>JavaScript의 설계 실수</li>
<li>null이 원시 자료형임에도 불구하고 objet로 출력되는 이유는 Javacript 설계 당시의 버그를 해결하지 않은 것</li>
<li>해결하지 못하는 이유는 이미 null 타입에 의존성을 띄고 있는 수 많은 프로그램들이 망가질 수 있기 때문(하위 호환 유지)<br><img src="https://velog.velcdn.com/images/turtle_hw/post/6c025d75-277a-4938-acea-3284dc1c91c3/image.png" alt=""></li>
</ul>
<h3 id="1_5-boolean">1_5. Boolean</h3>
<p>-&gt; true / false (소문자로 되어있음)</p>
<ul>
<li>조건문 또는 반복문에서 Boolean이 아닌 데이터 타입은 &#39;자동 형변환 규칙&#39;에 따라 true 또는 flase로 변환됨</li>
</ul>
<blockquote>
<p><strong>자동 형변환</strong>
<img src="https://velog.velcdn.com/images/turtle_hw/post/7cd63562-f3cf-4da8-bbd1-5fe1160da1d9/image.png" alt=""></p>
</blockquote>
<hr>
<h2 id="2-참조-자료형reference-type">2. 참조 자료형(Reference type)</h2>
<p>: Objects(Object, Array, Function)(객체, 배열, 함수) - 객체지향프로그램(OOP)에서의 Objects랑 다른거다 / 타입의 이름이 Object라는 것</p>
<ul>
<li>객체의 주소가 저장되는 자료형(가변, 주소가 복사)
<img src="https://velog.velcdn.com/images/turtle_hw/post/1aa1dafb-d47c-48c3-99f4-f85cdd9f0ee8/image.png" alt=""></li>
</ul>
<h1 id="연산자">연산자</h1>
<h2 id="할당-연산자">할당 연산자</h2>
<ul>
<li>오른쪽에 있는 피연산자의 평가결과를 왼쪽 피연산자에 할당하는 연산자</li>
<li>단축 연산자 지원</li>
</ul>
<h2 id="증가--감소-연산자">증가 &amp; 감소 연산자</h2>
<ul>
<li><p>증가 연산자(++)</p>
<ul>
<li>피연산자를 증가(1을 더함)시키고 연산자의 위치에 따라 증가하기 전이나 후의 값을 반환</li>
</ul>
</li>
<li><p>감소 연산자(--)</p>
<ul>
<li>피연산자를 감소(1을 뺌)시키고 연산자의 위치에 따라 감소하기 전이나 후의 값을 반환</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/d92d1fdd-0e17-44c9-9a9e-f0c5aa210b73/image.png" alt=""></p>
<blockquote>
<p><strong>+= 또는 -=와 같이 더 명시적인 표현으로 작성 하는 것을 권장</strong></p>
</blockquote>
<h2 id="비교-연산자">비교 연산자</h2>
<ul>
<li>피연산자들(숫자, 문자, Boolean 등)을 비교하고 결과 값을 boolean으로 반환하는 연산자</li>
</ul>
<h2 id="동등-연산자">동등 연산자(==)</h2>
<ul>
<li>두 피연산자가 같은 값으로 평가되는지 비교 후 boolean값을 반환</li>
<li><code>&#39;암묵적 타입 변환&#39;</code> 통해 <code>타입을 일치시킨 후</code> 같은 값인지 비교</li>
<li>두 피연산자가 모두 객체일 경우 메모리의 같은 객체를 바라보는지 판별
<img src="https://velog.velcdn.com/images/turtle_hw/post/ff226f1b-dc3a-403e-b860-c9a47d9a4884/image.png" alt=""></li>
</ul>
<h2 id="🚩-일치-연산자">🚩 일치 연산자(===)</h2>
<ul>
<li>두 피연산자의 값과 타입이 모두 같은 경우 true를 반환</li>
<li>같은 객체를 가리키거나, 같은 타입이면서 같은 값인지를 비교</li>
<li><code>엄격한 비교</code>가 이뤄지며 암묵적 타입 변환이 발생하지 않음</li>
<li>특수한 경우를 제외하고는 동등 연산자가 아닌 <code>일치 연산자 사용 권장</code>
<img src="https://velog.velcdn.com/images/turtle_hw/post/16442bdf-e94f-477e-8f35-35b2c1fceafd/image.png" alt=""></li>
</ul>
<hr>
<h2 id="논리-연산자">논리 연산자</h2>
<h3 id="and-연산">and 연산</h3>
<ul>
<li>&amp;&amp;<h3 id="or">or</h3>
</li>
<li>||<h3 id="not">not</h3>
</li>
<li>!<h3 id="단축-평가-지원">단축 평가 지원</h3>
</li>
<li>끝까지 볼필요가 없을 때 판단 중단 시키는 것</li>
<li>첫 번째 False가 나올 때, FAlse 반환 없다면 True
  false &amp;&amp; true &gt; flase(1)
  false &amp;&amp; false &gt; false(2)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/78190cca-b2cf-43a5-bb7e-fba65f1822ed/image.png" alt=""></p>
<hr>
<h1 id="조건문">조건문</h1>
<h2 id="if">if</h2>
<ul>
<li>조건 표현식의 결과값을 boolean 타입으로 변환 후 참/거짓을 판단
<img src="https://velog.velcdn.com/images/turtle_hw/post/1a95b489-d84e-449f-ac75-29cfc284b577/image.png" alt=""></li>
</ul>
<h2 id="조건-삼항-연산자">조건 (삼항) 연산자</h2>
<ul>
<li>세 개의 피연산자를 받는 유일한 연산자</li>
<li>앞에서부터 조건문, 물음표(?), 조건문이 참일 경우 실행할 표현식, 콜론(:), 조건문이 거짓일 경우 실행할 표현식이 배치<pre><code class="language-html">const person = 100
if (person &gt; 17) {
return &#39;Yes&#39;
} else {
return &#39;No&#39;
}
</code></pre>
</li>
</ul>
<p>=&gt; person &gt; 17 ? &#39;Yes&#39; : &#39;No&#39;</p>
<pre><code>

# 반복문
- while / for / for...in / for...of
## while
- 조건문이 참이면 문장을 계속해서 수행
![](https://velog.velcdn.com/images/turtle_hw/post/3a2b070b-d496-496e-85ef-de34732ea658/image.png)

## for
- 특정 조건이 거짓으로 판별될 때까지 반복
![](https://velog.velcdn.com/images/turtle_hw/post/f91f611b-979d-4f16-a828-eb6cad116030/image.png)
- 동작 원리
1. 반복문 진입 및 변수 i 선언
2. 조건문 평가 후 코드 블럭 실행
3. 코드 블록 실행 이후 i 값 증가

### for ...in
- `객체(데이터타입의 객체)`의 __`열거 가능한`__(순서 x) 속성(property)(자바스크립트에서의 key)에 대해 반복
![](https://velog.velcdn.com/images/turtle_hw/post/91eea20a-9bd2-44f6-a58c-a1787009e619/image.png)

### for ...of
- `반복 가능한` 객체(배열, 문자열 등)(순서 O -&gt; 인덱스 존재)에 대해 반복
![](https://velog.velcdn.com/images/turtle_hw/post/c582f707-ff38-453d-b75b-93fb3c7c403f/image.png)

&gt; __배열 반복과 for ...in__
- 배열의 인덱스는 정수 이름을 가진 열거 가능한 속성
(배열의 키는 인덱스 -&gt; 순서가 있는 정수)
- for ...in은 정수가 아닌 이름과 속성을 포함하여 `열거 가능한` 모든 속성을 반환 ( 순서가 없음)
- 내부적으로 for ...in은 배열의 반복자 대신 속성 열거를 사용하기 때문에 특정 순서에 따라 인덱스를 반환하는 것을 보장할 수 없음 (for ...in은 object에서만 사용)
-&gt; __인덱스의 순서가 중요한 배열에서는 사용하지 않음__
-&gt; 배열에서는 for 반복, for...of 반복을 사용


### for ...in과 for ...of
![](https://velog.velcdn.com/images/turtle_hw/post/4f86f1e9-5b43-4ee0-8d05-e3ba6580c569/image.png)

## 반복문 사용 시 const 사용 여부
- for 문
    - for (let i = 0; i &lt; arr.length; i++) {...}의 경우에는 최초 정의한 i를 &#39;재할당&#39;하면서 사용하기 때문에 const를 사용하면 에러 발생

- for ...in, for ...of
    - 재할당이 아니라, 매 반복마다 다른 속성 이름이 변수에 지정되는 것이므로 const를 사용해도 에러가 발생하지 않음
    - 단, const 특징에 따라 블록 내부에서 변수를 수정할 수 없음


## 반복문 종합
![](https://velog.velcdn.com/images/turtle_hw/post/74dff9c3-1ae1-45e4-b0a4-644e5a7df4cd/image.png)
- break, continue =&gt; 네개 다 사용 가능(연관 키워드 내용 추가)


## 참고
### 세미콜론(semicolon)
- 자바스크립트는 세미콜론을 선택적으로 사용 가능
- 세미콜론이 없으면 ASI에 의해 자동으로 세미콜론이 삽입됨
     - ASI(Automatic Semicolon Insertion, 자동 세미콜론 삽입 규칙)

- JavaScript를 만든 Brendan Eich 또한 세미콜론 작성을 반대

### 변수 선언 키워드 - &#39;var&#39;
- ES6 이전에 변수 선언에 사용했던 키워드
- 재할당 가능 &amp; 재선언 가능
- &#39;호이스팅&#39;되는 특성으로 인해 예기치 못한 문제 발생 가능
    - 따라서 ES6 이후부터는 var대신 const와 let을 사용하는 것을 권장
- 함수 스코프(function scope)를 가짐
    - 블록스코프는 중괄호자체가 중요하지만 var는 함수만 빼고 전부다 전역으로 생각함
- 변수 선언 시 var, const, let 키워드 중 하나를 사용하지 않으면 자동으로 var로 선언됨

### 함수 스코프(function scope)
- 함수의 중괄호 내부를 가리킴
- 함수 스코프를 가지는 변수는 함수 바깥에서 접근 불가능

### 호이스팅(hoisting)
- 변수를 선언 이전에 참조할 수 있는 현상
- 변수 선언 이전의 위치에서 접근 시 undefined를 반환
- JavaScript에서 변수들은 실제 실행시에 코드의 최상단으로 끌어 올려지게 되며(hoisted) 이러한 이유 때문에 var로 선언된 변수는 선언 시에 undefined 로 값이 초기화되는 과정이 동시에 발생


### NaN을 반환하는 경우 예시
1. 숫자로서 읽을 수 없음(Number(undefined))
2. 결과가 허수인 수학 계산식(Math.sqrt(-1))
3. 피연산자가 NaN(7**NaN)
4. 정의할 수 없는 계산식(0*Infinity)
5. 문자열을 포함하면서 덧셈이 아닌 계산식(&#39;가&#39;/3)
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript]]></title>
            <link>https://velog.io/@turtle_hw/JavaScript</link>
            <guid>https://velog.io/@turtle_hw/JavaScript</guid>
            <pubDate>Mon, 23 Oct 2023 03:01:46 GMT</pubDate>
            <description><![CDATA[<h1 id="history-of-javascript">History of JavaScript</h1>
<h2 id="웹-브라우저와-javascript">웹 브라우저와 JavaScript</h2>
<h3 id="웹의-탄색1990">웹의 탄색(1990)</h3>
<ul>
<li>팀 버너스리 경이 WWW, 하이퍼텍스트 시스템 고안</li>
<li>URL, HTTP 최초 설계 및 구현</li>
<li><a href="https://info.cern.ch/">초기의 웹</a>은 정적인 텍스트 페이지만을 지원</li>
</ul>
<h3 id="웹-브라우저의-대중화1993">웹 브라우저의 대중화(1993)</h3>
<ul>
<li>Netscape사의 최초 상용 웹 브라우저인 Netscape Navigator 출시</li>
<li>당시 약 90% 이상의 시장 점유율을 가짐</li>
</ul>
<h3 id="javascript의-탄생1995">JavaScript의 탄생(1995)</h3>
<ul>
<li>당시 Netscape 소속 개발자 Brandon Eich는 웹의 동적 기능 개발이란느 회사의 요구사항을 넘어 스크립트 언어 Mocha를 개발</li>
<li>이후 LiveScript로 이름을 변경했으나 당시 가장 인기있던 프로그래밍 언어인 Java의 명성에 기대보고자 JavaScript로 이름을 변경</li>
<li>JavaScript는 Metscape Navigator 2.0에 탑재되어 웹 페이지에 동적 기능을 추가하는 데 사용됨</li>
</ul>
<h3 id="javascript-파편화1996">JavaScript 파편화(1996)</h3>
<ul>
<li>Microsoft가 자체 웹 브라우저인 인터넷 익스플로러 3.0에 JavaScript와 유사한 언어인 JScript를 도입</li>
<li>이 과정에서 많은 회사들이 자체적으로 JavaScript를 독자적으로 변경하고 이를 자체 브라우저에 탑재</li>
</ul>
<h3 id="1차-브라우저-전쟁1995-2001">1차 브라우저 전쟁(1995-2001)</h3>
<ul>
<li>Microsoft는 IE를 자사 윈도우 운영체제에 내장하여 무료로 배포</li>
<li>빌 게이츠를 필두로 한 Microsoft의 공격적인 마케팅, 자금력 그리고 윈도우 운영체제 점유율 앞에 Netscape는 빠르게 몰락하기 시작</li>
<li>IE의 시장 점유율은 2002년 약 96%에 달하며 Microsoft가 승리</li>
<li>추후 Brandon Eich와 함께 Netscpae에서 나온 핵심 개발진은 모질라 재단을 설립하여 Firefox 브라우저를 출시(2003)</li>
</ul>
<h3 id="1차-브라우저-전쟁의-영향">1차 브라우저 전쟁의 영향</h3>
<ul>
<li>웹 표준의 부재로 인해 각 기어벵서 자체 표준을 확립하려는 상황이 벌어짐</li>
<li>이는 웹 개발자들에게 큰 혼란을 주었으며, 결국 웹 표준의 중요성을 인식하는 계기가 됨</li>
</ul>
<h3 id="ecmascript-출시1997">ECMAScript 출시(1997)</h3>
<ul>
<li>JavaScript의 파편화를 막기 위해 1997년 ECMA 에서 ECMAScript라는 표준 언어를 정의 </li>
<li>이때부터 JavaScript라는 ECMAScript 표준에 기반을 두고 발전하기 시작</li>
</ul>
<h3 id="2차-브라우저-전쟁2004-2017">2차 브라우저 전쟁(2004-2017)</h3>
<ul>
<li>IE 독주에 대한 Firefox의 대항 - 2008년까지 30% 점유율 차지</li>
<li>Google의 Chrome 브라우저 출시(2008)</li>
<li>Chrome은 출시 3년 만에 Firefox 의 점유율을 넘어서고 그로부터 반년 뒤 IE의 점유율을 넘어섬</li>
</ul>
<h3 id="2차-브라우저-전쟁의-영향">2차 브라우저 전쟁의 영향</h3>
<ul>
<li>웹 표준을 준수하는 Chrome의 등장으로 웹 표준의 중요성이 대두</li>
<li>웹의 기능이 크게 확장되며 웹 애플리케이션의 비약적인 발전 이끌어 감</li>
<li><blockquote>
<p>웹의 기술적 발전과 웹 표준의 중요성</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="ecmascript">ECMAScript</h2>
<blockquote>
<p>정보와 통신 시스템을 위한 국제적 표준화 기구</p>
</blockquote>
<ul>
<li>ECMA International 이 정의하고 있는 표준화된 스크립트 프로그래밍 언어 명세</li>
<li>스크립트 언어가 준수해야 하는 규칙, 세부사항 등을 제공</li>
</ul>
<h3 id="ecmascript와-javascript">ECMAScript와 JavaScript</h3>
<ul>
<li>JavaScript는 ECMAScript 표쥰을 구현한 구체적인 프로그래밍 언어</li>
<li>ECMAScript의 명세를 기반으로 하여 웹 브라우저나 Node.js와 같은 환경에서 실행됨
=&gt; ECMAScript는 JavaScript의 표준이며, 
JavaScript는 ECMAScript 표준을 따르는 구체적인 프로그래밍 언어
=&gt; ECMAScript는 언어의 핵심을 정의하고,
JavaScript는 ECMAScript 표준을 따라 구현된 언어로 사용됨</li>
</ul>
<h3 id="ecmascript의-역사">ECMAScript의 역사</h3>
<ul>
<li>ECMAScript 5(ES5) 에서 안정성과 생산성을 크게 높임(2009)</li>
<li>ECMAScript 2015(ES6)에서 객체지향 프로그래밍 언어로써 많은 발전을 이루어, 역사상 가장 중요한 버전으로 평가됨(2015)</li>
</ul>
<h3 id="javascript의-현재">JavaScript의 현재</h3>
<ul>
<li>현재는 Crhome, Firefox, Safari, Microsoft Edge 등 다양한 웹 브라우저가 출시되어 있으며, 웹 브라우저 시장이 다양화 되어있음</li>
<li>기존에 JavaScript는 브라우저에만 웹 페이지의 동적인 기능을 구현하는 데에만 사용되었음<ul>
<li>예를 들어, 사용자의 입력에 따라 웹 페이지의 내용이 동적으로 변경되거나, 애니메이션 효과가 적용되는 등의 기능</li>
</ul>
</li>
<li>이후 브라우저에서 벗어나 Node.js와 같은 서버 사이드 분야뿐만 아니라, 다양한 프레임워크와 라이브러리들이 개발되면서, 웹 개발 분야에서는 필수적인 언어로 자리잡게 됨</li>
</ul>
<hr>
<h1 id="javascript-and-dom">JavaScript and DOM</h1>
<h1 id="dom">DOM</h1>
<h2 id="개요">개요</h2>
<ul>
<li>웹 브라우저에서의 JavaScript : 웹 페이지의 동적인 기능을 구현</li>
</ul>
<h3 id="javascript-실행환경-종류">JavaScript 실행환경 종류</h3>
<table>
<thead>
<tr>
<th>실행환경 종류</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/903de6a5-0672-4f54-bc12-ba84c056b724/image.png" alt=""></td>
</tr>
<tr>
<td>alt+b 로 실행</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/0f2ec568-f14d-47e0-979e-5efa5cbd3d7c/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/c3bcf507-86d9-4e12-b05d-84153bec1657/image.png" alt=""></td>
</tr>
</tbody></table>
<blockquote>
<p><strong>The Document Object Model</strong>
웹페이지(Document)를 구조화된 객체로 제공하여 프로그래밍 언어가 페이지 구조에 접근할 수 있는 방법을 제공
-&gt; 문서 구조, 스타일, 내용 등을 변경할 수 있도록 함</p>
</blockquote>
<ul>
<li>DOM API라고 하기도 한다. </li>
</ul>
<h2 id="dom의-특징">DOM의 특징</h2>
<ul>
<li>DOM에서 모든 요소, 속성, 텍스트는 하나의 객체</li>
<li>모두 document 객체의 자식으로 구성됨(부모,자식의 관계가있다)</li>
</ul>
<h2 id="dom-tree">DOM tree</h2>
<ul>
<li>브라우저는 HTML 문서를 해석하여 DOM tree라는 객체 트리로 구조화 -&gt; 객체 간 상속 구조가 존재
<img src="https://velog.velcdn.com/images/turtle_hw/post/37f4d4c4-7e87-48d6-88b8-9a704da7b94b/image.png" alt=""></li>
</ul>
<blockquote>
<p>문서의 요소들을 <strong>&#39;<code>객체</code>&#39;</strong>로 제공하여 다른 프로그래밍 언어에서 접근하고 조작할 수 있는 방법을 제공하는 API</p>
</blockquote>
<hr>
<h2 id="document-객체">&#39;document&#39; 객체</h2>
<ul>
<li>웹 페이지 객체</li>
<li>DOM Tree의 진입점</li>
<li>페이지를 구성하는 모든 객체 요소를 포함</li>
</ul>
<table>
<thead>
<tr>
<th>HTML의 title 변경하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/23ca28f7-812a-41c5-a77c-5ff0e63122c9/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="dom-선택">DOM 선택</h2>
<h3 id="dom-조작-시-기억해야-할-것">DOM 조작 시 기억해야 할 것</h3>
<p>웹 페이지를 동적으로  만들기 == 웹 페이지를 조작하기</p>
<blockquote>
<p>조작 순서</p>
</blockquote>
<ol>
<li>조작하고자 하는 요소를 선택(또는 탐색)</li>
<li>선택된 요소의 콘텐츠 또는 속성을 조작</li>
</ol>
<hr>
<h2 id="선택-메서드">선택 메서드</h2>
<h3 id="1-documentqueryselectorselector">1. document.querySelector(selector)</h3>
<ul>
<li>요소 한 개 선택(단일)</li>
<li>제공한 선택자와 일치하는 element 한 개 선택</li>
<li><blockquote>
<p>만족하는 요소가 여러 개면, 제공한 CSS selector를 만족하는 <code>첫 번째</code> element 객체를 반환(없다면 null 반환)</p>
</blockquote>
</li>
</ul>
<h3 id="2-documentqueryselectorallselector">2. document.querySelectorAll(selector)</h3>
<ul>
<li>요소 여러 개 선택(다중)</li>
<li>제공한 선택자와 일치하는 여러 element를 선택</li>
<li><blockquote>
<p>제공한 CSS selector를 만족하는 NodeList(하나하나의 요소를 Node라고 함 <code>[대괄호]</code>로 감싸져 있음)를 반환</p>
</blockquote>
</li>
</ul>
<hr>
<table>
<thead>
<tr>
<th>DOM 선택 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/2d08a65c-470c-4634-9ca4-67e8c71d0c13/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/088836bd-ac50-4e24-85bc-5a1f033dc675/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="dom-조작">DOM 조작</h2>
<h2 id="속성attribute-조작">속성(attribute) 조작</h2>
<ol>
<li>클래스 속성 조작</li>
<li>일반 속성 조작</li>
</ol>
<h2 id="classlist-property">&#39;classList&#39; property</h2>
<ul>
<li>요소.classList</li>
<li>요소의 클래스 목록을 DOMTokenList(유사 배열) 형태로 반환</li>
</ul>
<h3 id="classlist-메서드">classList 메서드</h3>
<ul>
<li><p>element.classList.add()</p>
<ul>
<li>지정한 클래스 값을 추가</li>
</ul>
</li>
<li><p>element.classList.remove()</p>
<ul>
<li>지정한 클래스 값을 제거</li>
</ul>
</li>
<li><p>element.classList.toggle()</p>
<ul>
<li>클래스가 존재한다면 제거하고 false를 반환(존재하지 않으면 클래스를 추가하고 true 반환)</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>클래스 속성 조작 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/e386e14a-0aec-4d61-aaa4-e4d20c2a2084/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="속성-조작-메서드">속성 조작 메서드</h3>
<ul>
<li>Element.getAttribute()<ul>
<li>해당 요소에 지정된 값을 반환(조회)</li>
</ul>
</li>
<li>Element.setAttribute(name, vlaue)<ul>
<li>지정된 요소의 속성 값을 설정</li>
<li>속성이 이미 있으면 기존 값을 갱신(그렇지 않으면 지정된 이름과 값으로 새 속성이 추가)</li>
</ul>
</li>
<li>Element.removeAttribute(name)<ul>
<li>요소에서 지정된 이름을 가진 속성 제거</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>속성 조작 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/f45dca9a-3283-4f73-8f11-256cd782d733/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/5ca12d2a-433e-4d71-ab22-a7497e414c50/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="html-콘텐츠-조작">HTML 콘텐츠 조작</h2>
<h2 id="textcontent-property">&#39;textContent&#39; property</h2>
<ul>
<li>요소의 텍스트 콘텐츠를 표현
<img src="https://velog.velcdn.com/images/turtle_hw/post/0db0f160-88b4-4d99-b1f8-1d30a00d231e/image.png" alt=""></li>
</ul>
<hr>
<h2 id="dom-요소-조작">DOM 요소 조작</h2>
<h3 id="dom-요소-조작-메서드">DOM 요소 조작 메서드</h3>
<ul>
<li><p>document.createElement(tagName)</p>
<ul>
<li>작성한 tagName의 HTML요소를 생성하여 반환 <code>&lt;p&gt; &lt;/p&gt;</code></li>
</ul>
</li>
<li><p>Node.appendChild()</p>
<ul>
<li>한 Node를 특정 부모 Node의 자식 NodeList 중 마지막 자식으로 삽입</li>
<li>추가된 Node 객체를 반환</li>
</ul>
</li>
<li><p>Node.removeChild()</p>
<ul>
<li>DOM에서 자식 Node를 제거</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>DOM 요소 조작 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/dff7f5cf-084a-4af0-9fd7-6f7592dc3803/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="style-조작">style 조작</h3>
<h3 id="style-property">&#39;style&#39; property</h3>
<ul>
<li>해당 요소의 모든 style 속성 목록을 포함하는 속성</li>
</ul>
<table>
<thead>
<tr>
<th>style 조작 실습</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/060d1088-7b5a-4b73-b251-bfef9f1b2ecc/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h1 id="참고">참고</h1>
<blockquote>
<p>mdn 을 항상 참고하기</p>
</blockquote>
<h2 id="node">Node</h2>
<ul>
<li>DOM의 기본 구성 단위</li>
<li>DOM 트리의 각 부분은 Node라는 객체로 표현됨<ul>
<li>Document Node : HTML 문서 전체를 나타내는 노드</li>
<li>Element Node : HTML 요소를 나타네는 노드   ex) <code>&lt;p&gt;</code></li>
<li>Text Node : HTML 텍스트, Element Node 내의 텍스트 컨텐츠를 나타냄</li>
<li>Attribute Node : HTML 요소의 속성을 나타내는 노드 </li>
</ul>
</li>
</ul>
<h2 id="nodelist">NodeList</h2>
<ul>
<li>DOM 메서드를 사용해 선택한 Node의 목록</li>
<li>배열과 유사한 구조를 가짐</li>
<li>index로만 각 항목에 접근 가능</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[DRF2(N:1)]]></title>
            <link>https://velog.io/@turtle_hw/DRF2N1</link>
            <guid>https://velog.io/@turtle_hw/DRF2N1</guid>
            <pubDate>Thu, 19 Oct 2023 00:29:48 GMT</pubDate>
            <description><![CDATA[<h3 id="url-및-http-request-method-구성">URL 및 HTTP request method 구성</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/6a2aaa20-7362-46d5-9a57-c6f7e7e78f0c/image.png" alt=""></p>
<h1 id="drf-with-n1-relation">DRF with N:1 Relation</h1>
<h2 id="1-get-list">1. GET-list</h2>
<table>
<thead>
<tr>
<th>댓글 목록 조회를 위한 CommentSerializer 정의</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/865f4ce1-f736-4d5f-bcdc-37bf78a10f80/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>url 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/8a1e0091-4cb4-4394-9822-4bbd82f20584/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>view 함수 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/1cb690e5-1271-4243-b9ee-bf7ffc889ee3/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>GET <a href="http://127.0.0.1:8000/api/v1/comments/">http://127.0.0.1:8000/api/v1/comments/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/1d75d060-7b2b-44a0-b517-8a2ab18775b7/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="2-get-detail">2. GET-Detail</h2>
<table>
<thead>
<tr>
<th>단일 댓글 조회를 위한 url 및 view 함수 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b4b368be-29a2-409e-9dcb-3e5de4830eca/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/d25e6c44-6528-465a-b92c-b4f628a87bdd/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>GET <a href="http://127.0.0.1:8000/api/v1/comments/1/">http://127.0.0.1:8000/api/v1/comments/1/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/29e40ba8-e3eb-487f-b4ae-82b758a9c34a/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="3-post">3. POST</h2>
<table>
<thead>
<tr>
<th>단일 댓글 생성을 위한 url 및 view 함수 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/603b8399-baf5-4dcd-875a-64d208b6bff0/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/a5509094-363e-477f-bfb9-e43f3eb4dcd1/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>serailizer 인스턴스의 save() 메서드는 특정 Serializer 인스턴스를 저장하는 과정에서 추가 데이터를 받을 수 있음</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/811b51f5-0a9d-4b78-8352-4980baf24241/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>POST <a href="http://127.0.0.1:8000/api/v1/articles/1/comments/">http://127.0.0.1:8000/api/v1/articles/1/comments/</a>  응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td>상태코드 400 응답 확인</td>
</tr>
<tr>
<td>CommentSerializer 에서 외래 키에 해당하는 article field 또한 사용자로부터 입력 받도록 설정되어 있기 때문에 서버 측에서 누락되었다고 판단한 것</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b7a74f9d-9862-40ff-96d6-bfe2960ac56e/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="✔-읽기-전용-필드">✔ 읽기 전용 필드</h3>
<table>
<thead>
<tr>
<th>데이터를 전송하는 시점에 &#39;유효성 검사에서 제외시키고, 데이터 조회 시에는 출력&#39;하는 필드</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/3b28eba5-94d7-47fd-8d15-891e424f1423/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>POST <a href="http://127.0.0.1:8000/api/v1/articles/1/comments/">http://127.0.0.1:8000/api/v1/articles/1/comments/</a> 재요청</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/569a8a80-da0a-41ca-a762-c702538da81c/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h2 id="4-delete--put">4. DELETE &amp; PUT</h2>
<table>
<thead>
<tr>
<th>단일 댓글 삭제 및 수정을 위한 view 함수 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/8bde2724-fb95-4020-835f-53f809c61bed/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>DELETE <a href="http://127.0.0.1:8000/api/v1/comments/21/">http://127.0.0.1:8000/api/v1/comments/21/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/d5bd7b95-1954-4653-b13e-75b9c6266d79/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>PUT <a href="http://127.0.0.1:8000/api/v1/comments/1/">http://127.0.0.1:8000/api/v1/comments/1/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b9a30e5a-bd37-469b-8cce-477663c231fc/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h1 id="응답-데이터-재구성">응답 데이터 재구성</h1>
<h2 id="댓글-조회-시-게시글-출력-내역-변경">댓글 조회 시 게시글 출력 내역 변경</h2>
<ul>
<li>댓글 조회 시 게시글 번호만 제공해주는 것이 아닌 &#39;게시물의 제목&#39;까지 제공하기</li>
</ul>
<table>
<thead>
<tr>
<th>필요한 데이터를 만들기 위한 Serializer는 내부에서 추가 선언 가능</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/f0686dcd-11bc-49c5-b80b-057c2452eff5/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>GET <a href="http://127.0.0.1:8000/api/v1/comments/1/">http://127.0.0.1:8000/api/v1/comments/1/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/b58662b7-a351-417c-9873-286e5000f337/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h1 id="역참조-데이터-구성">역참조 데이터 구성</h1>
<blockquote>
<h3 id="article---comment-간-역참조-관계를-활용한-json-데이터-재구성">Article -&gt; Comment 간 역참조 관계를 활용한 JSON 데이터 재구성</h3>
</blockquote>
<ul>
<li>아래 2가지 사항에 대한 데이터 재구성하기</li>
</ul>
<ol>
<li>단일 게시글 조회 시 <code>해당 게시글에 작성된 댓글 목록 데이터</code>도 함께 붙여서 응답</li>
<li>단일 게시글 조회 시 <code>해당 게시글에 작성된 댓글 개수 데이터</code>도 함게 붙여서 응답</li>
</ol>
<h2 id="1-단일-게시글--댓글-목록">1. 단일 게시글 + 댓글 목록</h2>
<ul>
<li>Nested relationships<ul>
<li>모델 관계 상으로 참조하는 대상은 참조되는 대상의 표현에 포함되거나 중첩될 수 있음</li>
<li>이러한 중첩된 관계는 serializers를 필드로 사용하여 표현 가능
<img src="https://velog.velcdn.com/images/turtle_hw/post/f41fd53d-d443-4190-83e8-403978b1b979/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code class="language-python"># articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = &#39;__all__&#39;
        read_only_fields = (&#39;article&#39;,)

class ArticleSerializer(serializers.ModelSerializer):
    comment_Set = CommentSerializer(many=True, read_only = True)
    class Meta:
        model = Article
        fields = &#39;__all__&#39;</code></pre>
<table>
<thead>
<tr>
<th>GET <a href="http://127.0.0.1:8000/api/v1/articles/2/">http://127.0.0.1:8000/api/v1/articles/2/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/d84fd3ff-edb1-4949-a794-c7feda667c99/image.png" alt=""></td>
</tr>
</tbody></table>
<h2 id="2-단일-게시글--댓글-목록">2. 단일 게시글 + 댓글 목록</h2>
<table>
<thead>
<tr>
<th>댓글 개수에 해당하는 새로운 필드 생성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/fc92b3fc-ff47-448a-9b99-de5115cda8b1/image.png" alt=""></td>
</tr>
<tr>
<td>```python</td>
</tr>
<tr>
<td>class ArticleSerializer(serializers.ModelSerializer):</td>
</tr>
<tr>
<td>comment_set = CommentSerializerForArticle(many=True, read_only=True)</td>
</tr>
<tr>
<td># comment_set와 같이 역참조 매니저명은 django가 기존에 정의해놓은 것</td>
</tr>
</tbody></table>
<pre><code>comment_count = serializers.IntegerField(source=&#39;comment_set.count&#39;, read_only=True)
# &#39;comment_count&#39; 해당 변수는 내가 새롭게 정의한 것
# comment_count 변수에 할당되어야 할 값도 내가 정의 해줘야 함.
class Meta:
    model = Article
    fields = &#39;__all__&#39;</code></pre><p>```</p>
<blockquote>
<h4 id="source">&#39;source&#39;</h4>
</blockquote>
<ul>
<li>필드를 채우는데 사용할 속성의 이름</li>
<li>점 표기법(dotted notaion)을 사용하여 속성을 탐색 할 수 있음
<img src="https://velog.velcdn.com/images/turtle_hw/post/89992f4e-6b8a-4614-95c1-bd9147f8ba5a/image.png" alt=""></li>
</ul>
<table>
<thead>
<tr>
<th>GET <a href="http://127.0.0.1:8000/api/v1/articles/3/">http://127.0.0.1:8000/api/v1/articles/3/</a> 응답 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/884f2264-2b49-41c3-803d-7153f5e92d1c/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="주의-읽기-전용-필드-지정-이슈">[주의] 읽기 전용 필드 지정 이슈</h3>
<ul>
<li>특정 필드를 override 혹은 추가한 경우 read_only_fields는 동작하지 않음</li>
<li>해당 필드의 read_only 키워드 인자로 작성해야 함
<img src="https://velog.velcdn.com/images/turtle_hw/post/2053d092-12cf-4864-a042-e8e67eaa1b5d/image.png" alt=""></li>
</ul>
<hr>
<h1 id="api-문서화">API 문서화</h1>
<h2 id="openapi-specificationoas">OpenAPI Specification(OAS)</h2>
<ul>
<li>RESTful API를 설명하고 시각화하는 표준화된 방법</li>
<li><blockquote>
<p>API에 대한 세부사항을 기술할 수 있는 공식 표준</p>
</blockquote>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/fda75d9d-97be-4706-9297-51187d5d030d/image.png" alt="">
=&gt; OAS 기반 API에 대한 문서를 생성하는데 도움을 주는 오픈소스 프레임워크</p>
<table>
<thead>
<tr>
<th>설치 및 등록</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/a6da2152-1504-409a-a4dd-eadd2f991353/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/f57f8351-95de-44b7-ad24-54a326c04b08/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><a href="https://drf-spectacular.readthedocs.io/en/latest/readme.html#installation">관련 설정코드 입력(OpenAPI 스키마 자동 생성 코드</a></th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/1ff4048b-07e3-4e48-8c5c-e08f4fddf745/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>swagger, redoc 페이지 제공을 위한 url 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/5299899a-067a-46cd-a6d1-c58bbd337207/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><a href="http://127.0.0.1:8000/api/schema/swagger-ui/">http://127.0.0.1:8000/api/schema/swagger-ui/</a> 페이지 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/40a4dbb5-7ed4-468e-978d-c9b610fc24d5/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><a href="http://127.0.0.1:8000/api/schema/redoc">http://127.0.0.1:8000/api/schema/redoc</a> 페이지 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/0eda93fd-8aa9-426e-9a51-60f3e0847208/image.png" alt=""></td>
</tr>
</tbody></table>
<h4 id="oas의-핵심-이점---설계-우선-접근법">OAS의 핵심 이점 - &#39;설계 우선&#39; 접근법</h4>
<ul>
<li>API를 먼저 설계하고 명세를 작성한 후, 이를 기반으로 코드를 구현하는 방식</li>
<li>API의 일관성을 유지하고, API 사용자는 더 쉽게 API를 이해하고 사용할 수 있음</li>
<li>또한, OAS를 사용하면 API가 어떻게 작동하는지를 시각적으로 보여주는 문서를 생성할 수 있으며, 이는 API를 이해하고 테스트하는 데 매우 유용</li>
<li>이런 목적으로 사용되는 도구가 <code>Swagger-UI</code> 또는 <code>ReDoc</code></li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<h2 id="django-shortcuts-functions">Django shortcuts functions</h2>
<blockquote>
<p>render() / redirect() / get_object_or_404() / get_list_or_404()</p>
</blockquote>
<h3 id="get_object_or_404">get_object_or_404()</h3>
<ul>
<li>모델 manager objects에서 get()을 호출하지만, 해당 객체가 없을 땐 기존 DoesNotExist 예외 대신  Http404를 raise함
<img src="https://velog.velcdn.com/images/turtle_hw/post/041c247b-68b1-494a-b2c4-fb2445973bb4/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/a7ca2b49-9ee4-4574-bce2-71fc36cf768b/image.png" alt=""></li>
</ul>
<h3 id="get_list_or_404">get_list_or_404()</h3>
<ul>
<li>모델 manager objects에서 filter()의 결과를 반환하고, 해당 객체 목록이 없을 땐 Http404를 raise 함
<img src="https://velog.velcdn.com/images/turtle_hw/post/9813dd12-4569-4e36-a7d2-fe72f1ac1a89/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/ea011f2a-202a-48d8-b45e-df161004b142/image.png" alt=""></li>
</ul>
<blockquote>
<p>적용 전/후 비교 =&gt; 존재하지 않는 게시글 조회 시 이전에는 상태코드 500을 응답했지만 현재는 404를 응답</p>
</blockquote>
<blockquote>
<p><strong>왜 사용해야 할까?</strong></p>
</blockquote>
<ul>
<li>클라이언트에게 &#39;서버에 오류가 발생하여 요청을 수행할 수 없다(500)&#39;라는
원인이 정확하지 않은 에러를 제공하기보다는,
적절한 예외처리를 통해 클라이언트에게 보다 정확한 에러 현황을
전달하는 것도 매우 중요한 개발 요소 중 하나이기 때문</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django REST framework 1]]></title>
            <link>https://velog.io/@turtle_hw/Django-REST-framework-1</link>
            <guid>https://velog.io/@turtle_hw/Django-REST-framework-1</guid>
            <pubDate>Wed, 18 Oct 2023 03:02:36 GMT</pubDate>
            <description><![CDATA[<h1 id="rest-api">REST API</h1>
<h2 id="api">API</h2>
<p> Application Programming Interface</p>
<ul>
<li>애플리케이션과 프로그래밍으로 소통하는 방법</li>
<li>클라이언트-서버처럼 서로 다른 프로그램에서 요청과 응답을 받을 수 있도록 만든 체계</li>
</ul>
<h3 id="web-api">Web API</h3>
<ul>
<li>웹 서버 또는 웹 브라우저를 위한 API </li>
<li>현대 웹 개발은 하나부터 열까지 직접 개발하기보다 여러 Open API들을 활용하는 추세</li>
</ul>
<h3 id="restrepresentational-state-transfer">REST(Representational State Transfer)</h3>
<ul>
<li>여기서 상태는 데이터 </li>
<li>API Server를 개발하기 위한 일종의 소프트웨어 설계 방법론
&quot;약속(규칙X)&quot;</li>
</ul>
<h3 id="restful-api">RESTful API</h3>
<ul>
<li>REST 원리를 따르는 시스템을 RESTful하다고 부름</li>
<li>&#39;자원(데이터)을 정의&#39;하고 &#39;자원에 대한 주소를 지정&#39;하는 전반적인 방법을 서술<blockquote>
<p>각각 API구조를 작성하는 모습이 너무 다르니 약속을 만들어서 다같이 통일해서 쓰자!</p>
</blockquote>
</li>
</ul>
<h3 id="rest-api-1">REST API</h3>
<ul>
<li>REST라는 설계 디자인 약속을 지켜 구현한 API</li>
</ul>
<h2 id="rest에서-자원을-정의하고-주소를-지정하는-방법">REST에서 자원을 정의하고 주소를 지정하는 방법</h2>
<h3 id="1-자원의-식별">1. 자원의 식별</h3>
<ul>
<li>URI<h3 id="2-자원의-행위">2. 자원의 행위</h3>
</li>
<li>HTTP Methods (<code>GET</code>_게시물 달라 / <code>POST</code>_정보줄테니 만들어달라)</li>
</ul>
<h3 id="3-자원의-표현">3. 자원의 표현</h3>
<ul>
<li>JSON 데이터 </li>
<li>궁극적으로 표현되는 데이터 결과물</li>
</ul>
<hr>
<h1 id="1-자원의-식별-1">1. 자원의 식별</h1>
<h2 id="uri">URI</h2>
<blockquote>
<p>Uniform Resource Identifier (통합 자원 식별자)</p>
</blockquote>
<ul>
<li>인터넷에서 리소스(자원)를 식별하는 문자열</li>
<li>가장 일반적인 URI는 웹 주소로 알려진 URL</li>
</ul>
<h2 id="url">URL</h2>
<blockquote>
<p>Uniform Resource Locator (통합 자원 위치)</p>
</blockquote>
<ul>
<li>웹에서 주어진 리소스의 주소 -&gt; 네트워크 상에 리소스가 어디 있는지를 알려주기 위한 약속
<img src="https://velog.velcdn.com/images/turtle_hw/post/81781131-108d-4449-9bcb-ddb9010bf703/image.png" alt=""></li>
</ul>
<h3 id="schemaor-protocol">Schema(or Protocol)</h3>
<ul>
<li>브라우저가 리소스를 요청하는 데 사용해야 하는 규약</li>
<li>URL의 첫 부분은 브라우저가 어떤 규약을 사용하는지를 나타냄</li>
<li>기본적으로 웹은 THHP(S)를 요구하며 메일을 열기 위한 mailto:, 
파일을 전송하기 위한 ftp: 등 다른 프로토콜도 존재</li>
</ul>
<h3 id="domain-name">Domain Name</h3>
<ul>
<li>요청 중인 웹 서버를 나타냄</li>
<li>어떤 웹 서버가 요구되는 지를 가리키며 직접 IP 주소를 사용하는 것도 가능하지만, 사람이 외우기 어렵기 때문에(사용자 친화적이지 않음) 주로 Domain Name으로 사용</li>
<li>예를 들어 도메인 google.com 의 IP주소는 142.251.42.142</li>
<li>도메인 이름을 돈주고 산다 </li>
</ul>
<h3 id="port">Port</h3>
<ul>
<li><p>웹 서버의 리소스에 접근하는데 사용되는 기술적인 문(Gate)</p>
</li>
<li><p>HTTP 프로토콜의 표준 포트</p>
<ul>
<li>HTTP - <code>80</code></li>
<li>HTTPS - <code>443</code></li>
</ul>
</li>
<li><p>표준 포트만 생략 가능</p>
</li>
</ul>
<h3 id="path">Path</h3>
<ul>
<li>웹 서버의 리소스 경로</li>
<li>초기에는 실제 파일이 위치한 물리적 위치를 나타냈지만, 오늘날은 실제 위치가 아닌 <code>추상화</code>된 형태의 구조를 표현</li>
<li>예를 들어 /articles/create/가 실제 articles 폴더 안에 create 폴더안을 나타내는 것은 아님</li>
</ul>
<h3 id="parameters">Parameters</h3>
<ul>
<li>웹 서버에 제공하는 추가적인 데이터</li>
<li>&#39;&amp;&#39;기호로 구분되는 key-value 쌍 목록</li>
<li>서버는 리소스를 응답하기 전에 이러한 파라미터를 사용하여 추가 작업을 수행할 수 있음</li>
<li>GET 배울때 (검색 할때) 배웠음 (검색 데이터가 파라미터로 넘어갔다.)</li>
</ul>
<h3 id="anchor">Anchor</h3>
<ul>
<li>일종의 &#39;북마크&#39;를 나타내며 브라우저에 해당 지점에 있는 콘텐츠를 표시</li>
<li>fragment identifier(부분 식별자)라고 부르는 <code>#</code> 이후 부분은 서버에 전송되지 않음<pre><code class="language-text">https://docs.djangoproject.com/en/4.2/intro/install/#quick-install-guide</code></pre>
</li>
<li>위 요청에서 <code>#quick-install-guide</code>는 <code>서버에 전달되지 않고</code> 브라우저에게 해당 지점으로 이동할 수 있도록 함</li>
</ul>
<hr>
<h2 id="2-자원의-행위-1">2. 자원의 행위</h2>
<h3 id="http-request-methods">HTTP Request Methods</h3>
<ul>
<li>리소스에 대한 행위(수행하고자 하는 동작)을 정의</li>
<li><blockquote>
<p>HTTP verbs 라고도 함<img src="https://velog.velcdn.com/images/turtle_hw/post/b88d7f44-b6f6-49f3-9066-db0702f5c614/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="http-response-status-codes">HTTP response status codes</h3>
<ul>
<li>특정 HTTP 요청이 성공적으로 완료되었는지 여부를 나타냄</li>
</ul>
<blockquote>
<p>5개의 응답 그룹</p>
</blockquote>
<ul>
<li>Informational responsese(100-199)</li>
<li>Successful responses(200-299)</li>
<li>Redirection messages(300-399)</li>
<li>Client error responses(400-499)</li>
<li>Server error responses(500-599)</li>
</ul>
<hr>
<h2 id="3-자원의-표현-1">3. 자원의 표현</h2>
<p>그동안 서버가 응답(자원을 표현)했던 것 = 지금까지 Django 서버는 사용자에게 페이지(html)만 응답하고 있었음</p>
<ul>
<li>하지만 서버가 응답할 수 있는 페이지 뿐만 아니라 다양한 데이터 타입을 응답할 수 있음</li>
<li>REST API는 이 중에서도 <code>JSON</code> 타입으로 응답하는 것을 권장</li>
</ul>
<h3 id="응답-데이터-타입의-변화">응답 데이터 타입의 변화</h3>
<ol>
<li>페이지(html)만을 응답하는 서버</li>
<li>이제는 JSON 데이터를 응답하는 REST API 서버로의 변환</li>
<li>Django는 더 이상 Template 부분에 대한 역할을 담당하지 않게 되며, Front-end 와 Back-end가 구분되어 구성 됨</li>
<li>이제부터 Django를 사용해 RESTful API 서버를 구축할 것</li>
</ol>
<hr>
<table>
<thead>
<tr>
<th>python으로 json 응답받기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/ffcab5af-578d-4a2d-b01c-73e380fd5626/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h1 id="drfdjango-rest-framework">DRF(Django REST framework)</h1>
<blockquote>
<p>Django에서 Restful API 서버를 쉽게 구축할 수 있도록 도와주는 오픈소스 라이브러리</p>
</blockquote>
<h1 id="serialization--직렬화">Serialization &quot; 직렬화 &quot;</h1>
<blockquote>
<p>여러 시스템에서 활용하기 위해 데이터 구조나 객체 상태를 나중에 재구성할 수 있는 포맷(리스트/ 딕셔너리 등)으로 변환하는 과정</p>
</blockquote>
<ul>
<li>어떠한 언어나 환경에서도 나중에 다시 쉽게 사용할 수 있는 포맷으로 변환하는 과정</li>
</ul>
<h1 id="drf-with-single-model">DRF with Single Model</h1>
<blockquote>
<h2 id="postman">Postman</h2>
</blockquote>
<ul>
<li>API를 구축하고 사용하기 위한 플랫폼</li>
<li>API를 빠르게 만들 수 있는 여러 도구 및 기능을 제공<h3 id="화면구성">화면구성</h3>
<img src="https://velog.velcdn.com/images/turtle_hw/post/c7f10376-0100-4cdc-a48f-27b8e0233562/image.png" alt=""></li>
</ul>
<h3 id="url과-http-requests-methods-설계">URL과 HTTP requests methods 설계</h3>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/10c3a3bb-6e48-442c-bff4-a17a3de4494c/image.png" alt=""></p>
<hr>
<h1 id="get">GET</h1>
<h2 id="get-list">GET-List</h2>
<table>
<thead>
<tr>
<th>게시글 데이터 목록 조회하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/64d56f31-1315-44af-a2a4-5630bab98fab/image.png" alt=""></td>
</tr>
<tr>
<td>게시글 데이터 목록을 제공하는 ArticleListSerializer 정의</td>
</tr>
<tr>
<td>serializers.py의 위치나 파일명은 자유롭게 작성 가능</td>
</tr>
</tbody></table>
<h3 id="modelserializer">ModelSerializer</h3>
<ul>
<li>Django 모델과 연결된 Serializer 클래스</li>
</ul>
<table>
<thead>
<tr>
<th>url 및 view 함수 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/0f2c72cc-fb5f-4a5f-9654-453a8b69a2b7/image.png" alt=""></td>
</tr>
</tbody></table>
<h3 id="이전-view-함수와의-비교">이전 view 함수와의 비교</h3>
<ul>
<li>똑같은 데이터를 HTML에 출력되도록 페이지와 함께 응답했던 과거의 view 함수, JSON 데이터로 serialization하여 페이지 없이 응답하는 현재의 view 함수
<img src="https://velog.velcdn.com/images/turtle_hw/post/94e9a6ad-31fe-4908-a863-06e70ce8042f/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/1a902974-e165-4307-acf6-198d516a04ef/image.png" alt=""></li>
</ul>
<blockquote>
<h3 id="api_view-decorator">api_view decorator</h3>
</blockquote>
<ul>
<li>DRF view 함수에서는 필수로 작성되며 view 함수를 실행하기 전 HTTP 메서드를 확인</li>
<li>기본적으로 GET 메서드만 허용되며 다른 메서드 요청에 대해서는 405 Method Not Allowed로 응답</li>
<li>DRF view 함수가 응답해야 하는 HTTP 메서드 목록을 작성</li>
</ul>
<h2 id="get-detail">GET-Detail</h2>
<table>
<thead>
<tr>
<th>단일 게시글 데이터 조회하기</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/64d56f31-1315-44af-a2a4-5630bab98fab/image.png" alt=""></td>
</tr>
<tr>
<td>게시글 데이터 목록을 제공하는 ArticleSerializer 정의</td>
</tr>
</tbody></table>
<hr>
<table>
<thead>
<tr>
<th>url 및 view 함수 작성</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/e54c03d1-a103-47f8-a1cb-535b0a475fc5/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>응답확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/a4eb703a-c6aa-4e79-b1ac-9cc0f4ef7168/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/573aaf27-b3fc-40a9-99a5-7e9a94eaee73/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h1 id="post">POST</h1>
<ul>
<li>게시글 데이터 생성하기</li>
<li>데이터 생성 성공했을 경우 201 Created 응답</li>
<li>데이터 생성 실패했을 경우 400 Bad request 응답</li>
</ul>
<table>
<thead>
<tr>
<th>article_list view 함수 구조 변경(method에 따른 분기처리)</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/e693e97b-1231-4bf0-962e-807f63d695fd/image.png" alt=""></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>POST응답 확인 &amp; 새로 생성된 게시글 데이터 확인</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/4d65dce0-f9d1-49c4-8810-c611c6249bb3/image.png" alt=""></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/turtle_hw/post/597d6676-8412-475e-a145-358f0a3450df/image.png" alt=""></td>
</tr>
</tbody></table>
<hr>
<h1 id="delete">DELETE</h1>
<ul>
<li>게시글 데이터 삭제하기 </li>
<li>요청에 대한 데이터 삭제가 성공했을 경우는 204 No Content 응답</li>
</ul>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/turtle_hw/post/8eda4c04-e795-46c0-86c4-877d17ac994a/image.png" alt=""></th>
</tr>
</thead>
<tbody><tr>
<td>views.py</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/turtle_hw/post/2be5a9a1-991b-41e4-9f9b-4bf86a522d6e/image.png" alt=""></th>
</tr>
</thead>
<tbody><tr>
<td>DELETE <a href="http://127.0.0.1:8000/api/v1/articles/23/">http://127.0.0.1:8000/api/v1/articles/23/</a> 응답확인</td>
</tr>
</tbody></table>
<hr>
<h1 id="put">PUT</h1>
<ul>
<li>게시글 데이터 수정하기</li>
<li>요청에 대한 데이터 수정이 성공했을 경우는 200 OK 응답
<img src="https://velog.velcdn.com/images/turtle_hw/post/9d9c5818-800f-44e5-9dfb-7c8a57cb5fde/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/e05dbaf9-4118-4f62-bdb1-f54bef599dfb/image.png" alt="">
<img src="https://velog.velcdn.com/images/turtle_hw/post/439214cb-2f2c-44d2-9741-f3c15dbaabd5/image.png" alt=""></li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<h3 id="raise_exception">raise_exception</h3>
<ul>
<li>is_valid()는 유효성 검사 오류가 있는 경우 ValidationError 예외를 발생시키는 선택적 raise_exception 인자를 사용할 수 있음</li>
<li>DRF 에서 제공하는 기본 예외 처리기에 의해 자동으로 처리되며 기본적으로 HTTP 400 응답을 반환
<img src="https://velog.velcdn.com/images/turtle_hw/post/19375146-baeb-472f-8680-8d81dd8718a9/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Many to many relationships 2]]></title>
            <link>https://velog.io/@turtle_hw/NM-2</link>
            <guid>https://velog.io/@turtle_hw/NM-2</guid>
            <pubDate>Tue, 17 Oct 2023 02:21:50 GMT</pubDate>
            <description><![CDATA[<h1 id="프로필-구현">프로필 구현</h1>
<h1 id="팔로우">팔로우</h1>
<h2 id="중개-테이블">중개 테이블!!</h2>
<ul>
<li>외래키 두개를 가진 중개 테이블
User(M) - User(N)</li>
<li>0명 이상의 회원은 0명 이상의 회원과 관련</li>
<li>0명 이상의 팔로워를 가질 수 있고, 0명 이상의 다른 회원들을 팔로잉 할 수 있음</li>
</ul>
<h3 id="팔로우-기능-구현">팔로우 기능 구현</h3>
<blockquote>
<p>설계도 새로 하는데 왜 migration 할 때 뭐 안떠?
중개 테이블을 만드는 것이라서 
기존필드에 필드가 추가되는 개념이 아니다! 기존필드에 변화가 있는 것이아니라 테이블이 하나 더 생긴 것이다. </p>
</blockquote>
<h3 id="exists">.exists()</h3>
<ul>
<li>QuerySet 에 결과가 포함되어 있으면 True를 반환하고 </li>
</ul>
<h1 id="django-fixtures">Django Fixtures</h1>
<h2 id="fixtures">Fixtures</h2>
<p> -Django가 데이터베이스로 가져오는 방법을 알고 있는 데이터 모음 -&gt; 데이터베이스 구조에 맞추어 작성 되어있음</p>
<h3 id="초기-데이터의-제공">초기 데이터의 제공</h3>
<h2 id="fixtures-관련-명령어">fixtures 관련 명령어</h2>
<ol>
<li>dumpdata : 생성(데이터베이스의 모든 데이터 추출)<ul>
<li>추출한 데이터는 json 형식으로 저장 </li>
</ul>
</li>
<li>loaddata : Fixtures 데이터를 데이터베이스로 불러오기
<img src="https://velog.velcdn.com/images/turtle_hw/post/38e9e666-3888-45c0-9fab-a8d50c70bfbb/image.png" alt=""></li>
</ol>
<ul>
<li>Fixtures 파일 기본 경로<ul>
<li>app_name/fixtures/</li>
</ul>
</li>
</ul>
<ul>
<li><p>loaddata 순서 주의사항
: 한방에 쓸때는 순서 상관없지만
: 따로따로 할 때는 순서 신경써야함!!</p>
</li>
<li><p>모든 모델을 한번에 dump 할 수도 있음</p>
</li>
</ul>
<blockquote>
<p>Fixtures 파일을 직접 만들지 말 것</p>
</blockquote>
<ul>
<li>반드시 dumpdata 명령어를 사용하여 생성</li>
</ul>
<h1 id="improve-query">Improve query</h1>
<ul>
<li><p>같은 결과를 얻기 위해 DB측에 보내는 쿼리 개수를 점차 줄여 조회하기</p>
<h2 id="annotate">annotate</h2>
</li>
<li><p>주석의 의미를 가지고 있음</p>
</li>
<li><p>SQL의 GROUP BY 쿼리를 사용</p>
<h2 id="select_related">select_related</h2>
</li>
<li><p>SQL의 INNER JOIN 쿼리를 활용</p>
</li>
<li><blockquote>
<p>1:1 또는 N:1 참조 관계에서 사용</p>
</blockquote>
<h2 id="prefetch_related">prefetch_related</h2>
</li>
<li><p>M:N 또는 N:1 역참조 관계에서 사용 </p>
</li>
<li><blockquote>
<p>SQL이 아닌 Python을 사용한 JOIN을 진행</p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Many to many relationships 1]]></title>
            <link>https://velog.io/@turtle_hw/Many-to-many-relationships-1</link>
            <guid>https://velog.io/@turtle_hw/Many-to-many-relationships-1</guid>
            <pubDate>Mon, 16 Oct 2023 08:08:04 GMT</pubDate>
            <description><![CDATA[<h1 id="many-to-many-relationships">Many to many relationships</h1>
<blockquote>
<p>한 테이블의 0개 이상의 레코드가 다른 테이블의 0개 이상의 레코드와 관련된 경우 =&gt; 양쪽 모두에서 N:1 관계를 가짐</p>
</blockquote>
<p>의사와 환자 간 모델 관계 설정</p>
<ol>
<li>python manage.py sheel_plus에서 의자, 환자 코드 예시 한줄씩 붙여넣기</li>
<li>테이블 생성된 것 확인</li>
<li>N:1의 한계 상황
<img src="https://velog.velcdn.com/images/turtle_hw/post/b20b435e-0d93-4c9a-a875-a261e9f8607a/image.png" alt=""></li>
</ol>
<p>4.중계 모델</p>
<ul>
<li><p>예약 모델 생성 : 환자 모델의 외래 키를 삭제하고 별도의 예약 모델을 새로 생성 </p>
</li>
<li><p>exit로 shell_plus 종료하고 </p>
</li>
<li><p>db.sqlite3 랑 001_migarte된거 삭제(데이터베이스 초기화) 후 Migration 다시 진행 및 shell_plus 실행</p>
</li>
<li><p>예약 데이터 생성 =&gt; ex_2코드</p>
</li>
<li><p>예약 정보 조회</p>
</li>
<li><p>추가 예약 생성</p>
</li>
<li><p>예약 정보 조회 _ 1번 의사의 환자 2명 된거 조회 가능</p>
</li>
<li><p>Django 에서는 &#39;ManyToManyField&#39;로 중개모델을 자동으로 생성</p>
</li>
</ul>
<h1 id="django-manytomanyfield">Django ManyToManyField</h1>
<ul>
<li><p>환자모델에 ManyToManyField 작성
<img src="https://velog.velcdn.com/images/turtle_hw/post/acb64042-b418-4b84-8d7d-2bf5a4ddf387/image.png" alt=""></p>
</li>
<li><p>데이터베이스 초기화 후 Migration 진행 및 shell_plus 실행</p>
</li>
<li><p>생성된 중개 테이블 hospitals_patient_doctors 확인</p>
</li>
<li><p>예약 생성, 취소 진행하기</p>
</li>
</ul>
<blockquote>
<p>만약 예약 정보에 증상, 예약일 등 추가 정보가 포함되어야 한다면?</p>
</blockquote>
<h2 id="through-argument">&#39;through&#39; argument</h2>
<ul>
<li>중개 테이블에 &#39;추가 데이터&#39;를 사용해 M:N 관계를 형성하려는 경우에 사용
<img src="https://velog.velcdn.com/images/turtle_hw/post/d6cdb159-1186-4d12-9e98-0d54827c50a4/image.png" alt=""></li>
</ul>
<h1 id="좋아요">좋아요</h1>
<h2 id="articlem---usern">Article(M) - User(N)</h2>
<blockquote>
<p>0개 이상의 게시글은 0명 이상의 회원</p>
</blockquote>
<blockquote>
<ul>
<li>N:1에서의 역참조 
Article : User(N:1)
user.article_set.all()</li>
</ul>
</blockquote>
<ul>
<li>N:M에서의 역참조
Article: User(N:M)
user.article_set.all()</li>
</ul>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/5a317790-f606-4b9e-ab5c-5c416e80b7be/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/turtle_hw/post/1b96025f-fb1b-42bb-b4e3-103c6060152f/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>