<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kim-mg.log</title>
        <link>https://velog.io/</link>
        <description>mgg</description>
        <lastBuildDate>Sat, 22 Oct 2022 09:24:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kim-mg.log</title>
            <url>https://images.velog.io/images/kim-mg/profile/15de132b-ac5a-4789-a6ee-528b72396419/37352691-물과-기포-배경.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kim-mg.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kim-mg" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Java]]></title>
            <link>https://velog.io/@kim-mg/Java</link>
            <guid>https://velog.io/@kim-mg/Java</guid>
            <pubDate>Sat, 22 Oct 2022 09:24:33 GMT</pubDate>
            <description><![CDATA[<h2 id="java">Java?</h2>
<p>자바(Java)는 1995년 미국의 &#39;썬마이크로시스템즈&#39;라는 회사가 개발했다. 현재는 &#39;썬마이크로시스템즈&#39;가 &#39;오라클&#39;에 인수되어 관리 및 배포 중에 있다.</p>
<p>자바는 <strong>객체지향 언어</strong>이다.</p>
<p>J2SE(Java 2 Standard Edition), J2EE(Java 2 Enterprise Edition), JRE(Java Runtime Environment), JDK(Java Development Kit) 등 자바 플랫폼을 사용한 개발 혹은 실행을 위한 API이다.</p>
<h2 id="자바의-특징">자바의 특징</h2>
<ol>
<li>쉬운 난이도<ul>
<li>C, C++의 포인터, 다중 상속 등의 개념을 없애 문법적인 난이도를 낮췄다.</li>
</ul>
</li>
<li>Garbage Collector<ul>
<li>자동 메모리 정리 기능이 있다. 프로그램이 실행 중에 사용하지 않는 메모리를 자동으로 해제한다.</li>
</ul>
</li>
<li>JVM(Java Virtual Machine)<ul>
<li>운영체제마다 Native Language(C, C++, ...)의 실행 환경이 달라 정상적인 실행이 되지 않을 수 있다. 각 운영체제에 맞는 기계어로 Compiling 해야 한다. Java는 JVM이 중간 다리 역할을 해줌으로서 운영체제와 상관없이 프로그램을 실행시킬 수 있다.</li>
</ul>
</li>
</ol>
<h2 id="jvmjava-virtual-machine">JVM(Java Virtual Machine)</h2>
<ol>
<li>Java Virtual Machine의 약자로 자바는 JAVAC Compiler를 통해 *.class 파일로 변환되고, JVM이 *.class 파일을 실행하는 방식으로 동작한다. 따라서 JVM이 없다면 Java 프로그램을 실행시킬 수 없다.</li>
<li>JVM은 JRE(Java Runtime Environment)를 설치하면 자동으로 설치되며, JRE는 JDK를 설치하면 자동으로 설치된다. JRE에는 자바 클래스 라이브러리와 자바 클래스 로더, 자바 가상 머신 등이 포함된다.</li>
<li>자바 소스코드는 운영체제에 종속되지 않는 <strong>첫번째 Managed Language</strong>이다.</li>
<li>Managed Language는 Native Language보다 실행 속도가 느린데, 이는 <strong>실행하려는 프로그램 코드를 각 운영체제에 맞는 언어로 변환</strong>시켜 주어야 하기 때문에 번역 과정을 거치기 때문이다.</li>
</ol>
<h2 id="sdtstrict-data-type">SDT(Strict Data Type)</h2>
<ol>
<li>Strict Data Type으로 자바 또는 Managed Language의 특징이다.</li>
<li>사용하고자 하는 자료형을 엄격하게(명확하게) 명시해야 하는 룰이다. C 계열 언어에서 1 또는 0을 if 조건문과 사용할 수 있는데, 자바에서는 boolean형이 필수적으로 요구된다.</li>
</ol>
<h2 id="garbage-collector">Garbage Collector</h2>
<ol>
<li>컴퓨터 프로그램은 메모리를 사용하여 실행되는데, 이러한 과정에서 사용되지 않는 공간이 필연적으로 생기게 된다. <strong>이러한 사용되지 않는 공간을 자동으로 비워주는 기능</strong>을 Garbage Collector라고 한다.</li>
<li>C와 C++에서는 메모리의 크기를 직접 할당하고 사용하는데, 사용이 끝난 메모리를 적절하게 해제해 주어야 그 공간을 다시 사용할 수 있다. 만약 사용하고 방치된 메모리를 해제해주지 않는다면 할당할 공간이 부족해지는 <strong>Stack Overflow</strong> 오류를 만날 수 있다. 이렇게 메모리를 제대로 할당하지 않고 사용되지 않는 메모리가 방치되는 것을 <strong>Memory Leak</strong>이라 한다.</li>
<li>Garbage Collector는 프로그램의 백그라운드에서 동작하며 구간 종료 시(해당 클래스의 사용이 끝났을 시 등) 필요없는 메모리를 강제로 반환하는 기능이다.</li>
</ol>
<h2 id="popprocedure-oriented-program">POP(Procedure Oriented Program)</h2>
<ol>
<li>C, VB, PASCAL 등이 POP 개념을 사용하고 있으며, 프로그램이 시작하면 프로그래밍 된 순서대로 진행하고, 모든 순서가 종료되면 프로그램 또한 종료된다.</li>
<li>기능이 우선시되어 OOP에 비해 빠른 프로그래밍이 가능하다.</li>
<li>대부분의 함수가 프로그램 내부에서 어디서든 사용 가능한 전역 데이터를 사용하기 때문에, 데이터 접근이 용이하다.</li>
<li>데이터 접근이 유용한 만큼 보안성이 낮다.</li>
<li>데이터의 모듈화가 어렵다. 모듈화는 프로그램을 기능 단위로 분리하여 관리하기 쉽도록 하는 것인데, POP의 경우 데이터 및 기능을 추가해야 할 때 기존에 작성된 프로그램을 수정해야 하며, 프로그램의 크기가 커질수록 유지보수가 어렵다.</li>
</ol>
<h2 id="oopobject-oriented-program">OOP(Object Oriented Program)</h2>
<ol>
<li><strong>객체</strong>라는 개념을 통해 데이터 및 함수를 모듈화하여 프로그램의 <strong>유지 보수와 보안성을 강화</strong>하였다. OOP를 사용하는 언어는 JAVA, C++, C#, .NET 등이 있다.</li>
<li><strong>캡슐화</strong>
 데이터를 캡슐화(은닉화)하여, <strong>프로그램 외부에서 접근 가능한 데이터를 지정</strong>할 수 있다. 캡슐화를 통해 사용사의 편리한 사용을 돕고 데이터 보안성을 증가시킨다.</li>
<li><strong>추상화</strong>
 <strong>객체의 기본적인 틀만 만들어 놓고 사용할 수 있는 기능</strong>, 예를 들어 동물이라는 객체를 통해 개, 고양이, 돼지 등의 구체적인 객체를 만들어 사용할 수 있다.</li>
<li><strong>상속</strong>
 부모 클래스(상속해준 클래스)의 데이터 및 함수를 그대로 이어받아 사용할 수 있는 기능이다. <strong>코드의 재사용성</strong>을 높인다.</li>
<li><strong>다형성</strong>
 <strong>객체가 다양한 형태로 표현될 수 있다는 개념</strong>으로, 추상화된 객체와 같이 틀을 가진 객체가 구체화된 객체로 표현할 수 있다는 뜻이다. 동물 객체가 고양이로 지정되어 야옹을 쓸 수 있다는 뜻이다.</li>
</ol>
<h2 id="memory">Memory</h2>
<ol>
<li>Register
 CPU 내부에서 사용되는 저장공간으로, 속도가 가장 빠르지만 메모리 용량이 적다.<strong>(따로 사용되는 목적이 있었던 것 같다. 어셈블리를 공부해보자)</strong></li>
<li>Storage
 가장 큰 용량을 가지며 하드 드라이브(HDD)라고 불린다. 속도가 매우 느리다. SDD도 스토리지에 속한다.</li>
<li>Memory
 RAM이 담당하는 공간이며, 스토리지보다는 빠르지만 레지스터보다는 느리다.</li>
<li>스토리지는 CPU의 처리 속도를 맞출 수 없기 때문에 프로그램은 스토리지에 저장되어 있다가 운영체제가 프로그램을 메모리에 로드하게 되는데 이때 메모리에 로드된 프로그램의 단위를 프로세스(Process)라 한다.</li>
</ol>
<h2 id="variable변수">Variable(변수)</h2>
<pre><code class="language-java">import java.io.*;
class Main {
  public static void main(String[] args) {
    int a; //변수 선언
    a = 10; //변수 초기화(정의)
  }
}</code></pre>
<p><strong>변수란 값이 변할 수 있는 수</strong>를 의미하며 <strong>변수를 생성하고 값을 넣고 변경하는 데는 메모리가 사용</strong>된다. 변수 선언을 통해 메모리에 데이터가 저장될 수 있는 공간을 만들고, 변수 초기화(정의)를 통해 변수에 값을 넣어 값을 직접 넣지 않더라도 변수를 통해 값을 사용할 수 있다. 이 때 변수는 값이 들어가 있는 메모리 주소를 가리킨다.
변수는 사용하려는 값에 따라 정해진 데이터 타입이 존재한다. 사용하려는 값과 걸맞는 데이터 타입을 변수 선언 시 정해 주어야하며, 데이터 타입이 지정된 변수에는 해당 데이터 타입 이외의 값이 들어가는 경우 오류가 발생한다.</p>
<p><strong>변수명에 대한 규칙</strong></p>
<ol>
<li>첫 글자에는 영문자, 달러($), 언더라인(_)만 사용할 수 있다.</li>
<li>대소문자는 구별된다.</li>
<li>예약어는 사용할 수 없다.
 예약어란 자바에서 기본으로 사용하는 예약된 단어를 뜻한다.<pre><code>(this, if, class, for, abstract 등)</code></pre></li>
</ol>
<h2 id="constant상수">Constant(상수)</h2>
<pre><code class="language-java">import java.io.*;
class Main {
  public static void main(String[] args) {
    final int a = 2; //상수 선언과 동시에 초기화
    System.out.println(a);
  }
}</code></pre>
<p><strong>상수란 값이 변하지 않는 데이터 공간</strong>으로 변수 앞에 <strong>final</strong>을 붙여 사용한다. 상수로 선언된 자료형은 내부의 값을 바꿀 수 없다. 따라서 선언과 동시에 초기화되어야 한다.</p>
<h2 id="data-type자료형">Data Type(자료형)</h2>
<p>자료형은 C와 같으므로 기술하지 않겠다.</p>
<ol>
<li>integral: int, short, long</li>
<li>floating point: float, double</li>
<li>character: character</li>
<li>Boolean: boolean</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘]]></title>
            <link>https://velog.io/@kim-mg/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@kim-mg/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Thu, 22 Sep 2022 07:01:33 GMT</pubDate>
            <description><![CDATA[<p><a href="http://www.teferi.net/ps/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98">테페리넷의 알고리즘 카테고리</a>
[crucus의 알고리즘 카테고리]
(<a href="https://www.crocus.co.kr/category/Applied/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98">https://www.crocus.co.kr/category/Applied/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</a>)</p>
<p>문제를 해결하기 위한 방법, 컴퓨터가 인류의 문제해결 방식을 이해할 수 있도록 지시한 구조가 알고리즘이라고 필자는 이해한다. </p>
<p>컴퓨터는 그저 단순한 연산의 나열을 통해 매번 새로 계산할 번거로움을 줄여 주었고, 그런 방식으로도 거의 모든 수학적 연산을 해결할 수 있었지만, 큰 단위의 연산이나 복잡한 수식이 연결되는 연산의 경우는 한정된 컴퓨터의 자원으로 해결할 수 없는 문제였고, 인간보단 컴퓨터의 관점에서 연산의 효율을 극대화하여 적은 물적, 시간적 자원으로 최선의 결과를 얻어내도록 순서와 방법을 기술하는 알고리즘이 등장하게 되었다.</p>
<p>복잡한 계산을 사람의 손이 아닌 컴퓨터가 대신하는 현대에서는 보다 복잡한 계산의 결과를 얻기 위해, 그리고 보다 적은 자원으로 보다 빠른 결과를 얻기 위해 알고리즘의 영역은 발전해왔다. 컴퓨터에게 연산을 부탁하기 위한 데이터는 0과 1로 이루어져 있지만, 기술의 발전으로 숫자와 문자, 그리고 이미지와 소리에 이르러 인간이 인식할 수 있는 모든 범위의 데이터화가 진행되고 그에 따른 알고리즘의 영역도 변하게 되는데, 당면한 문제에 처리해야 할 데이터의 분류에 따라 효율적인 알고리즘 또한 바뀌게 된다.</p>
<p>개발자는 당연히 문제를 해결할 때에 효율적인 결과를 내놓아야 한다는 것을 부정할 수 없고, 그러므로 우리는 알고리즘을 학습하고 적재적소에 사용할 수 있어야 할 것이다.</p>
<p>필자는 본신의 힘만으로는 수학적 지식이나 알고리즘의 영역에 통달하기 어렵다고 판단하여, 쉽고 간단하게 정리되어 이해하기 쉬운 여러 레퍼런스의 도움을 받아 스스로의 진전에 보태기로 하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[향수 Perfume]]></title>
            <link>https://velog.io/@kim-mg/%ED%96%A5%EC%88%98-Perfume</link>
            <guid>https://velog.io/@kim-mg/%ED%96%A5%EC%88%98-Perfume</guid>
            <pubDate>Sat, 12 Mar 2022 08:47:31 GMT</pubDate>
            <description><![CDATA[<p>향수</p>
<ul>
<li>perfume은 &#39;연기를 내어 통과한다&#39;라는 라틴어인 perfumare에서 비롯.</li>
<li>향수의 기원은 종교적 의식, 곧 신과 인간과의 교감을 위한 매개체로부터 출발, 역사적으로 메소포타미아 문명과 고대 이집트 문명 시기인 약 5,000년 전으로 거슬러 올라감. 신을 신성시한 고대의 사람들은 신에게 제사를 지낼 때 몸을 청결히 하고, 향기가 풍기는 나뭇가지를 태우고, 향나무 잎으로 즙을 내어 몸에 발랐다고 한다.</li>
<li>고대의 향료는 훈향(薰香)으로서 종교 의식에 사용됨</li>
<li>몸 또는 의복에 부착하는 풍습은 모먀의 청정감과 함께 정신미화를 위하여 비롯된 것이다.</li>
</ul>
<h4 id="기원-및-고대의-기록을-모두-찾아보기보단-좀-더-향수-본질적인-내용으로-들어가고자-한다">기원 및 고대의 기록을 모두 찾아보기보단 좀 더 향수 본질적인 내용으로 들어가고자 한다.</h4>
<ul>
<li>근대적 의미의 향수는 1370년 경, &#39;오 드 트왈렛&#39;풍의 &#39;헝가리 워터&#39;의 발명이다.</li>
<li>증류 향수이며, 최초의 알코올 향수이다.</li>
</ul>
<h4 id="희석-정도에-따른-향수의-분류">희석 정도에 따른 향수의 분류</h4>
<ul>
<li>부향률 : 향수 원액과 알코올의 비율을 말하며, 부향률이 높다는 것은 원액이 더 많다는 뜻.</li>
<li>Parfum / 파르푕 : 가장 농도가 진한 것이다. 부향률이 15 ~ 40%이다.<pre><code>  (IFRA 기준으로는 대략 20%에 해당한다.)</code></pre></li>
<li>Esprit de Parfum(ESdp) / 에스프리 드 파르푕 : 오 드 퍼퓸(Eau de parfum)과<pre><code>  퍼퓸(Parfum)의 중간에 해당한다. 부향률은 15 ~ 30%이다.
  에스프리 드 퍼퓸 등급은 흔히 사용되지 않는다.</code></pre></li>
<li>Eau de Parfum(Edp) / 오 드 파르푕, Parfum de Toilette(PdT) / 파르푕 드 투왈렛 :<pre><code>  부향률은 10 ~ 20%이고 일반적으로는 15%이다. 퍼퓸 드 투왈렛은 1980년대에 많이
  쓰였으며 지금은 잘 쓰이지 않는 용어이다.</code></pre></li>
<li>Eau de Toilette(EdT) / 오 드 투왈렛 : 부항률이 5 ~ 15%이며 일반적으로는 10%이다.</li>
<li>Eau de Cologne(Edc) / 오 드 콜로뉴 : 3 ~ 8%의 부항률을 가진다. 일반적으로는 5%이다.</li>
</ul>
<p>이상 분류된 용어들 이외에도 &quot;스플래쉬&quot;, &quot;미스트&quot;, &quot;베일&quot; 혹은 다른 정확하지 않은 용어들을 사용한다. 대개 이런 제품들은 3%이하의 부향률을 가진다.</p>
<ul>
<li><p>Cologne 가 가진 세 가지 의미</p>
<ul>
<li>첫 의미이자 가장 오래된 정의로서 과일, 꽃, 나무 재료를 통해서 만들어진 시트러스에
기반한 향기 나는 물질을 말한다. 독일의 쾰른 지방에서 탄생했으며, 중성적인 혼합물을
가리키는 말로서 &quot;이것들은 기본적으로는 시트러스의 혼합물로 향기가 나지만, 향수는
아니었다.&quot;</li>
<li>20세기의 향수 회사들이 사용층을 늘리기 위한 수단으로 그리 진하지는 않은 제품에 &#39;콜롱&#39;
이라는 이름을 붙이기 시작했다. 고전적인 콜롱과는 달리 순수한 퍼퓸에 비해 가볍고, 희석된
버전이었다. 흔히 그 회사의 가장 희석된 것을 일컫는 말이었다.</li>
<li>콜로뉴라는 단어가 영어로 들어와서, 그 농도와 관련 없이 남성이 사용하는 향수를 일컫는
말이 되었다. 실제로 남성이 다른 등급의 향수를 쓰고 있다고 할지라도, &quot;그는 향수를
사용했다.&quot;라는 의미로서 &quot;콜로뉴를 사용했다.&quot;라고 쓰이게 되었다. 똑같은 문제가 &quot;파르푕&quot;
이라는 단어에도 있는데, 이것이 여성에게 판매하는 향수에 대한 일반적인 어휘가 되어,
그것이 원액 추출물에 해당하는 파르푕(퍼퓸)이 아니라고 하더라도, 그냥 &quot;파르푕&quot;이라고
사용하게 되었다.</li>
</ul>
</li>
<li><p>정확하지 않은 용어 구분
  희석 정도에 따른 향수의 분류 항목에서 볼 수 있듯이 등급에 따른 부향률의 범위가 상당히
  넓다. 이는 향수 등급이 정확하게 쓰이지 않는다느 것을 잘 보여준다.</p>
</li>
</ul>
<h4 id="지속-시간에-따른-향수-구분">지속 시간에 따른 향수 구분</h4>
<ul>
<li>Perfume / 퍼퓸 : 평균 6~7시간 정도 향이 가장 오래 감</li>
<li>Eau de Perfume / 오 드 퍼퓸 : 퍼퓸보다 조금 연해서 5~6시간 정도 지속</li>
<li>Eau de Toilette / 오 드 뚜왈렛 : 3~5시간 지속되며 대중적인 농도임</li>
<li>Eau de Cologne / 오 드 콜롱 : 가장 연한 향수 종류 축에 속하며 1~2시간 지속</li>
</ul>
<h4 id="향수-노트">향수 노트</h4>
<p>향수는 생성부터 소멸까지 단계별로 발향이 되는 특징을 지니고 있는데, 이 단계를 탑노트, 미들노트, 베이스노트로 구분하고 있다. 발향의 시작과 동시에 맡을 수 있는 향이 탑노트(Top Note), 뿌린 후 30분에서 1시간 정도 지난 뒤 시작되는 미들노트(Middle Note) 그리고 그 후 향이 사라지기 전까지 남아있는 &#39;잔향(殘香)&#39;으로 알려진 베이스노트(Base Note)로 나누어 말할 수 있다.</p>
<ul>
<li><p>Top Note : Head Note(헤드노트)라는 또 다른 명칭을 가지고 있다. 탑노트는 향수를 시향지</p>
<pre><code>  뿌린 후 발향이 될 때 느낄 수 있는 향이다. 30분 이하만 지속되는 향으로 일시적힌 향
  이라 할 수 있다. 보통은 상쾌한 시트러스 계열이나 네츄럴한 그린 계열이 많이
  사용된다.</code></pre></li>
<li><p>Middle Note : 미들노트는 향수의 &#39;Brand identity&#39;라고 한다. Heart Note(하트노트), </p>
<pre><code>  Soul Note(소울노트)라고도 불린다. 향수에서 가장 핵심적인 단계이며, 조향사가
  의도한 향이 발향되는 단계로 알려져있다. 탑노트가 끝남과 동시에 1시간 정도 지속된다.
  스파이시 계열이나 플로랄 계열과 같이 이미지와 컨셉이 명확한 향료들이 많이 사용된다.</code></pre></li>
<li><p>Base Note : Last Note(라스트노트)라고도 불리며, 또 다른 이름은 &#39;잔향&#39;이다. 향수 종류에</p>
<pre><code>  따라서 남은 시간동안 은은하게 남는다. 따로 세척이나 커버를 하지 않는다면, 피부나
  옷에 스며들 정도로 보류제 역할을 한다. 조향사에 따라 다르지만 대부분 대중적이고
  저자극적이며 성질이 약한 향들이 많이 쓰인다.</code></pre></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 're'__정규식 연산 라이브러리]]></title>
            <link>https://velog.io/@kim-mg/Python-re%EC%A0%95%EA%B7%9C%EC%8B%9D-%EC%97%B0%EC%82%B0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
            <guid>https://velog.io/@kim-mg/Python-re%EC%A0%95%EA%B7%9C%EC%8B%9D-%EC%97%B0%EC%82%B0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</guid>
            <pubDate>Thu, 30 Sep 2021 05:33:01 GMT</pubDate>
            <description><![CDATA[<p>이 문서는 점프 투 파이썬을 기본 바탕으로 작성되었다.<del>(복사하여 붙여 넣었다고 읽는다.)</del>
추후 학습하거나 깨닳은 요령이 생긴다면 최신화하는 방향으로 한다.</p>
<h1 id="0-참고자료">0. 참고자료</h1>
<p><a href="https://wikidocs.net/4308">점프 투 파이썬 - 정규표현식</a></p>
<h1 id="1-개요">1. 개요</h1>
<p><a href="https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D">정규표현식 - 위키백과</a></p>
<ul>
<li>정규표현식(정규식) : <code>특정한 규칙</code>을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어<pre><code>  컴퓨터 과학의 정규 언어로부터 유래하였으나 구현체에 따라서 정규 언어보다 더 
  넓은 언어를 표현할 수 있는 경우도 있으며, 심지어 정규 표현식 자체의 문법도
  여러 가지 존재하고 있다.</code></pre></li>
</ul>
<p>코딩을 하다보면 문자열을 조작해야 하는 경우가 생긴다. 이 때 문자열 자료형의 기능이나 내장 함수를 통해 수정하거나 관리할 수 있겠지만 특정한 단어를 찾아 바꾸거나 일정 패턴의 문자열을 제거한다던가 하는 작업엔 어려움이 따른다. 이를 해결하기 위해 정규표현식(정규식)을 사용하게 된다.</p>
<h1 id="2-정규표현식">2. 정규표현식</h1>
<h2 id="1-메타-문자">1. 메타 문자</h2>
<ul>
<li>메타문자 : 그 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자
정규표현식에서 사용하는 메타 문자(meta chracters)는 다음과 같다.<pre><code>  . ^ $ * + ? { } [ ] \ | ( )</code></pre></li>
</ul>
<h3 id="1-문자-클래스-------d-d-s-s-w-w">1. 문자 클래스 : [ ] <code>-</code> <code>^</code> <code>\d</code> <code>\D</code> <code>\s</code> <code>\S</code> <code>\w</code> <code>\W</code></h3>
<h4 id="1-문자-클래스--">1. 문자 클래스 [ ]</h4>
<ul>
<li>[  ] 문자 클래스 : <code>[ ] 사이의 문자들과 매치</code>의 의미
([ ] 사이에는 어떤 문자도 들어갈 수 있다.)<pre><code>  $$ 정규식 [abc]와 문자열과의 매치 $$
  1. &quot;a&quot; : 정규식과 일치하는 문자 &quot;a&quot;가 있으므로 매치 O
  2. &quot;before&quot; : 정규식과 일치하는 문자인 &quot;b&quot;가 있으므로 매치 O
  3. &quot;dude&quot; : 정규식과 아무것도 일치하는 것이 없으므로 매치되지 않음 X</code></pre></li>
</ul>
<h4 id="2-하이픈--">2. 하이픈 [-]</h4>
<ul>
<li>[  ] 안의 두 문자 사이에 하이픈<code>-</code>을 사용하면 두 문자 사이의 범위를 의미<pre><code class="language-markdown">  1. [a-zA-Z] : a ~ z 까지 그리고 A ~ Z 까지 모든 알파벳을 포함
  2. [0-9] : 0 ~ 9 까지의 모든 숫자</code></pre>
</li>
</ul>
<h4 id="3-서컴플렉스-">3. 서컴플렉스 [^]</h4>
<ul>
<li>[  ] 안에 <code>^</code> 메타 문자를 사용하면 반대(not)의 의미를 갖는다.<pre><code>  1. [^0-9] : 숫자가 아닌 문자만 매치</code></pre></li>
</ul>
<h4 id="4-자주-사용하는-문자-클래스-표기법">4. 자주 사용하는 문자 클래스 표기법</h4>
<ul>
<li><p>자주 사용하는 문자 클래스 : 자주 사용하는 정규식은 별도의 표기법이 존재한다.</p>
<pre><code>  $$ 자주 사용하는 문자 클래스 $$
  1. \d : 숫자와 매치, [0-9]와 동일
  2. \D : 숫자가 아닌 것과 매치, [^0-9]와 동일
  3. \s : whitespace(공백문자)와 매치, [ \t\n\r\f\v]와 동일(맨 앞은 빈 칸(&#39; &#39;)의 공백 문자)
  4. \S : whitespace가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일
  5. \w : 문자 + 숫자(alphanumeric)와 매치, [a-zA-Z0-9_]와 동일
  6. \W : 문자 + 숫자(alphanumeric)이 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일

  대문자는 소문자 표현식의 반대임을 추측할 수 있다.</code></pre></li>
</ul>
<h3 id="2-dot-">2. Dot <code>&#39;.&#39;</code></h3>
<ul>
<li><code>.</code> : 줄바꿈 문자인 <code>\n</code>을 제외한 모든 문자와 매치
(정규식 작성 시 re.DOTALL 옵션을 준다면 <code>\n</code>문자와도 매치할 수 있다.)<pre><code>  a.b = &quot;a + 모든문자 + b&quot;
  1. &quot;aab&quot; : &quot;a + a(모든문자) + b&quot;이므로 매치 O
  2. &quot;a0b&quot; : &quot;a + 0(모든문자) + b&quot;이므로 매치 O
  3. &quot;abc&quot; : &quot;a&quot;와 &quot;b&quot;사이에 어떤 문자라도 하나는 있어야 하지만 없으므로 매치되지 않음 X</code></pre></li>
<li>[.] : 문자 클래스 내에 <code>.</code>만 존재한다면 모든 문자라는 의미가 아닌 <code>.</code> 그대로를 의미<pre><code>  a[.]b = &quot;a + . + b&quot;
  1. &quot;a.b&quot; : &quot;a + . + b&quot;이므로 매치 O
  2. &quot;a0b&quot; : &quot;a + 0(. 아님) + b&quot;이므로 매치되지 않음 X</code></pre></li>
</ul>
<h3 id="3-반복-">3. 반복 <code>&#39;*&#39;</code></h3>
<ul>
<li><code>*</code> : 반복을 의미 <code>*</code> 바로 앞에 있는 문자가 0개부터 무한대로 반복될 수 있음
(반복 개수는 메모리 제한으로 2억개 정도만 가능하다고 한다.)<pre><code>  ca*t
  1. &quot;ct&quot; : &quot;a&quot;가 0번 반복되므로 매치 O
  2. &quot;cat&quot; : &quot;a&quot;가 0번 이상 반복되므로 매치(1번) O
  3. &quot;caaat&quot; : &quot;a&quot;가 0번 이상 반복되므로 매치(3번) O</code></pre></li>
</ul>
<h3 id="4-반복-">4. 반복 <code>&#39;+&#39;</code></h3>
<ul>
<li><code>+</code> : 반복을 의미 <code>+</code> 바로 앞에 있는 문자가 1개부터 무한대로 반복<pre><code>  ca+t
  1. &quot;ct&quot; : &quot;a&quot;가 0번 반복되므로 매치 X
  2. &quot;cat&quot; : &quot;a&quot;가 1번 이상 반복되므로 매치(1번) O
  3. &quot;caaat&quot; : &quot;a&quot;가 1번 이상 반복되므로 매치(3번) O</code></pre></li>
</ul>
<h3 id="5-반복-mn-">5. 반복 {m,n} <code>?</code></h3>
<ul>
<li>{m,n} : <code>m</code>번부터 <code>n</code>번까지 반복
(<code>m</code> 또는 <code>n</code>을 생략할 수 있다.)</li>
</ul>
<h4 id="1-m">1. {m}</h4>
<ul>
<li>{m} : 바로 앞에 오는 문자를 m회 반복<pre><code>  ca{2}t
  1. &quot;cat&quot; : &quot;a&quot;가 2번 반복되지 않으므로 매치 X
  2. &quot;caat&quot; : &quot;a&quot;가 2번 반복되므로 매치 O</code></pre></li>
</ul>
<h4 id="2-m-n">2. {m, n}</h4>
<ul>
<li>{m, n} : 바로 앞에 오는 문자를 m ~ n 회 반복<pre><code>  ca{2,5}t
  1. &quot;cat&quot; : &quot;a&quot;가 1번만 반복되어 매치 X
  2. &quot;caat&quot; : &quot;a&quot;가 2번 반복되어 매치 O
  3. &quot;caaaaat&quot; : &quot;a&quot;가 5번 반복되어 매치 O</code></pre></li>
</ul>
<h4 id="3-">3. <code>&#39;?&#39;</code></h4>
<ul>
<li><code>?</code> : 반복은 아니지만 비슷한 개념으로 {0,1}을 의미<pre><code>  ab?c
  1. &quot;abc&quot; : &quot;b&quot;가 1번 사용되어 매치 O
  2. &quot;ac&quot; : &quot;b&quot;가 0번 사용되어 매치 O</code></pre></li>
</ul>
<h3 id="6-">6. <code>&#39;^&#39;,&#39;$&#39;</code></h3>
<ul>
<li><code>^</code> : 문자열의 시작으로부터 정규식을 만족해야 함을 의미<pre><code>  ^https:[a-z]+[.][a-z]+
  1. &quot;http:google.com&quot; : &quot;http:&quot;에서 &quot;s&quot;가 없기 때문에 매치 X
  2. &quot;https:google.com&quot; : &quot;https:&quot;가 맞고 뒤의 정규식을 만족하므로 매치 O</code></pre></li>
<li><code>$</code> : 문자열의 끝을 의미<pre><code>  [a-z]+ done[.]$
  1. &quot;python is fun done&quot; : &quot;done&quot;의 &quot;.&quot;가 없기 때문에 매치 X
  2. &quot;python is fun done.&quot; : 앞의 정규식을 만족하며 &quot;done.&quot;을 만족하기 때문에 매치 O</code></pre></li>
</ul>
<h3 id="7-">7. <code>&#39;|&#39;</code></h3>
<ul>
<li><code>|</code> : <code>or</code>와 동일한 의미로 사용된다. <code>A|B</code>는 <code>A</code> 또는 <code>B</code>라는 의미<pre><code class="language-python">p = re.compile(&#39;Crow|Servo&#39;)
m = p.amatch(&#39;CrowHello&#39;)
print(m)
&gt;&gt; &lt;re.Match object; span=(0, 4), match=&#39;Crow&#39;&gt;</code></pre>
</li>
</ul>
<h3 id="8-az">8. <code>&#39;\A&#39;,&#39;\Z&#39;</code></h3>
<ul>
<li><code>\A</code> : <code>^</code>와 동일하게 문자열의 처음과 매치됨을 의미한다.
(re.MULITLINE 옵션을 사용할 경우에도 각 줄과 매치되는 것이 아닌 전체 문자열의 처음과 매치된다.)<pre><code class="language-python">p = re.compile(&quot;\Apython\s\w+&quot;, re.MULTILINE)
</code></pre>
</li>
</ul>
<p>data = &quot;&quot;&quot;python one
life is too short
python two
you need python
python three&quot;&quot;&quot;</p>
<p>print(p.findall(data))</p>
<p>// 이후 등장하는 MULTILINE(각 줄별로 매치함)를 사용해도 전체 문자열의 처음만 매치됨 //</p>
<blockquote>
<blockquote>
<p>[&#39;python one&#39;]</p>
</blockquote>
</blockquote>
<pre><code>
* `\Z` : `$`와 동일하게 문자열의 마지막과 매치된다.
(`\A`와 마찬가지로 MULTILINE 옵션 사용 시에도 전체 문자열로부터 조사한다.)
```python
p = re.compile(&quot;\w+\spython\Z&quot;, re.MULTILINE)

data = &quot;&quot;&quot;first python
life is too short
second python
you need python
third python&quot;&quot;&quot;

print(p.findall(data))
&gt;&gt; [&#39;third python&#39;]</code></pre><h3 id="9-b-b">9. <code>&#39;\b&#39;, &#39;\B&#39;</code></h3>
<ul>
<li><code>\b</code> : 단어 구분자(Word boundary)이다. 단어는 whitespace에 의해 구분된다.
(<code>\b</code>는 파이썬 리터럴 규칙에 의하면 백스페이스(BackSpace)를 의미하므로 단어 구분자임을 알려주기 위해 <code>r&#39;\bclass\b&#39;</code>처럼 Raw string으로 작성해야 한다.)<pre><code class="language-python">p = re.compile(r&#39;\bclass\b&#39;)
</code></pre>
</li>
</ul>
<p>// 양 쪽이 whitespace(공백문자)이며 &quot;class&quot;가 있으므로 매치 O //
print(p.search(&#39;no class at all&#39;))</p>
<blockquote>
<blockquote>
<p>&lt;re.Match object; span=(3, 8), match=&#39;class&#39;&gt;</p>
</blockquote>
</blockquote>
<p>// &quot;class&quot;가 있지만 양 쪽이 whitespace가 아니므로 매치 X //
print(p.search(&#39;the declassified algorithm&#39;))</p>
<blockquote>
<blockquote>
<p>None</p>
</blockquote>
</blockquote>
<p>// &quot;class&quot;가 있지만 한 쪽이 whitespace가 아니므로 매치 X //
print(p.search(&#39;one subclass is&#39;))</p>
<blockquote>
<blockquote>
<p>None</p>
</blockquote>
</blockquote>
<pre><code>
* `\B` : `\b`와 반대의 경우이다. whitespace로 구분되지 않은 단어를 매치한다.
```python
p = re.compile(r&#39;\Bclass\B&#39;)

print(p.search(&#39;no class at all&#39;))  
&gt;&gt; None

print(p.search(&#39;the declassified algorithm&#39;))
&gt;&gt; &lt;re.Match object; span=(6, 11), match=&#39;class&#39;&gt;

print(p.search(&#39;one subclass is&#39;))
&gt;&gt; None</code></pre><h3 id="10-grouping---하위식---p--">10. grouping : <code>( )(하위식)</code>, <code>(?...)</code> : <code>(?P...)</code> <code>(?=...)</code> <code>(?!...)</code></h3>
<h4 id="1--하위식">1. <code>( )</code>(하위식)</h4>
<ul>
<li><code>( )</code> : <code>( )</code>안의 문자열이 반복되는지 조사<pre><code class="language-python">p = re.compile(&#39;(ABC)+&#39;)
m = p.search(&#39;ABCABCABC OK?&#39;)
</code></pre>
</li>
</ul>
<p>print(m)</p>
<blockquote>
<blockquote>
<p>&lt;re.Match object; span=(0, 9), match=&#39;ABCABCABC&#39;&gt;</p>
</blockquote>
</blockquote>
<p>print(m.group())</p>
<blockquote>
<blockquote>
<p>ABCABCABC</p>
</blockquote>
</blockquote>
<pre><code>
#### 2. group()

#### 2-1. 기본적인 group의 사용
* group() : `()`를 사용하는 이유는 반복되는 문자 이외에도 매치된 문자열에서 특정 부분의 문자열만 뽑아내기 위해서이다.
```python
// &#39;( )&#39;을 사용하지 않은 경우 //
p = re.compile(r&quot;\w+\s+\d+[-]\d+[-]\d+&quot;)
m = p.search(&quot;park 010-1234-1234&quot;)

// 기본적으로 매치된 문자열을 돌려준다. //
print(m.group())
&gt;&gt; park 010-1234-1234
// 그룹화된 문자열이 없기 때문에 인덱스에러가 발생한다. //
print(m.group(1))
&gt;&gt; IndexError: no such group

// &#39;( )&#39;를 사용하여 grouping한 경우 //
p = re.compile(r&quot;(\w+)\s+\d+[-]\d+[-]\d+&quot;)
m = p.search(&quot;park 010-1234-1234&quot;)

// 기본적으로 매치된 문자열을 돌려준다. //
print(m.group())
&gt;&gt; park 010-1234-1234
// &#39;\w+&#39;를 &#39;(\w+)&#39;로 grouping 해주었기 때문에 //
// group의 첫 번째 인덱스가 문자열인 &quot;park&quot;를 나타낸다. //
print(m.group(1))
&gt;&gt; park</code></pre><ul>
<li><p>group 메서드의 인덱스</p>
<table>
<thead>
<tr>
<th align="center">group(인덱스)</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">group(0)</td>
<td align="center">매치된 전체 문자열</td>
</tr>
<tr>
<td align="center">group(1)</td>
<td align="center">첫 번째 그룹에 해당되는 문자열</td>
</tr>
<tr>
<td align="center">group(2)</td>
<td align="center">두 번째 그룹에 해당되는 문자열</td>
</tr>
<tr>
<td align="center">group(n)</td>
<td align="center">n 번째 그룹에 해당되는 문자열</td>
</tr>
</tbody></table>
</li>
</ul>
<pre><code class="language-python">p = re.compile(r&quot;(\w+)\s+((\d+)[-]\d+[-]\d+)&quot;)
m = p.search(&quot;park 010-1234-1234&quot;)

// 전화번호 부분을 grouping하여 group으로 뽑아내는 경우 //
print(m.group(2))
&gt;&gt; 010-1234-1234
// 그룹을 중첩 사용하는 것도 가능하다. //
// 중첩 시는 바깥쪽부터 시작하여 인덱스가 증가한다. //
print(m.group(3))
&gt;&gt; 010</code></pre>
<h4 id="2-2-grouping-문자열-재참조">2-2. grouping 문자열 재참조</h4>
<ul>
<li><code>( )\1</code> : <code>( )</code>로 그룹화된 문자열은 <code>\n(1번 부터 시작하는 인덱스)</code>메타 문자로 정규식 내에서 불러 사용할 수 있다.<pre><code class="language-python">// &#39;(\b\w+)&#39;를 `\1`로 재참조하여 사용하므로써 //
// &quot;(group) + &#39; &#39; + group과 매치된 단어&quot;와 매치 //
p = re.compile(r&#39;(\b\w+)\s+\1&#39;)
str = p.search(&#39;Paris in the the spring&#39;).group()
</code></pre>
</li>
</ul>
<p>// &#39;(\b\w+)&#39; == &#39;the&#39;, &#39;\1&#39; == &#39;the&#39; //
print(str)</p>
<blockquote>
<blockquote>
<p>the the</p>
</blockquote>
</blockquote>
<p>// 여러 문자를 그룹화(grouping)했다면 <code>\n</code>을 통해 n 번째의 그룹을 참조할 수 있다. //</p>
<pre><code>
#### 2-3. 정규식 확장문 `(?...)`
* `(?...)` : 정규표현식의 확장 구문으로, 강력한 기능들을 사용할 수 있다.

|구문|설명|
|:--:|:--:|
|(?P&lt;그룹명&gt;...)|&#39;...&#39;에 매치되는 문자열이 &#39;그룹명&#39;을 가짐|
|(?P=그룹명)|&#39;그룹명&#39;의 값을 참조(정규식 내에서 재참조 시 사용)|
|(?=...)|&#39;...&#39;을 포함하여 매치되는 문자열을 검색하지만 검색 결과에는 포함시키지 않음|
|(?!...)|&#39;...&#39;을 포함하는 문자열의 경우 결과에서 제외|

#### 2-3-1. grouping 문자열에 이름 붙이기 `(?P&lt;name&gt;...)`
* `(?P&lt;그룹명&gt;...)` : `( )`내에서 `?P&lt;그룹명&gt;`구문을 사용하면 이후 정규식에 매치되는 문자열을 해당 이름(변수명)으로 그룹화(grouping)할 수 있다.
(`그룹명`은 정규식 안에서 재참조가 가능하다.)
```python
// &#39;(?P&lt;name&gt;\w+)&#39; =&gt; &#39;(\w+)&#39;에 &quot;name&quot;의 그룹명을 붙임 //
p = re.compile(r&quot;(?P&lt;name&gt;\w+)\s+((\d+)[-]\d+[-]\d+)&quot;)
m = p.search(&quot;park 010-1234-1234&quot;)

// &quot;name&quot;의 그룹명을 가진 &quot;park&quot;를 결과로 돌려준다. //
print(m.group(&quot;name&quot;))
&gt;&gt; park

// &quot;word&quot;를 정규식 내에서 재참조 //
p = re.compile(r&#39;(?P&lt;word&gt;\b\w+)\s+(?P=word)&#39;)
str = p.search(&#39;Paris in the the spring&#39;).group()

// (?P&lt;word&gt;\b\w+) =&gt; word = &#39;the&#39;, (?P=word) =&gt; &#39;the&#39; // 
print(str)
&gt;&gt; the the</code></pre><h4 id="2-3-2-긍정형-전방-탐색-">2-3-2. 긍정형 전방 탐색 <code>(?=...)</code></h4>
<ul>
<li><code>(?=...)</code> : <code>...</code>를 포함하여 매치하지만 결과에서 <code>...</code>를 제외<pre><code class="language-python">// (?=:) =&gt; &#39;:&#39;을 포함하여 검색하지만 결과에서 제외 //
p = re.compile(&quot;.+(?=:)&quot;)
m = p.search(&quot;http://google.com&quot;)
</code></pre>
</li>
</ul>
<p>// &#39;.+(?=:)&#39; =&gt; http + &#39;:&#39; = &quot;http&quot; 제외 //
print(m.group())</p>
<blockquote>
<blockquote>
<p>http</p>
</blockquote>
</blockquote>
<pre><code>
#### 2-3-3. 부정형 전방 탐색 `(?!...)`
* `(?!...)` : `...`의 매치 결과를 포함하는 결과를 제외
(긍정형 전방 탐색(`(?=...)`)에서 작성이 어려운 정규식을 쉽게 사용할 수 있다.)
```python
// (?!bat$|exe$) =&gt; &quot;bat&quot;이나 &quot;exe&quot;끝나는 것들은 제외 //
p = re.compile(r&quot;.*[.](?!bat$|exe$).*$&quot;, re.MULTILINE)

s = &quot;&quot;&quot;data.db
python.exe
title.txt
seq.bat
server.js
&quot;&quot;&quot;

m = p.findall(s)

// &quot;python.exe&quot;와 &quot;seq.bat&quot;가 제외된 결과 //
print(m)
&gt;&gt; [&#39;data.db&#39;, &#39;title.txt&#39;, &#39;server.js&#39;]</code></pre><h1 id="3-re--python-정규식-라이브러리">3. re : python 정규식 라이브러리</h1>
<h2 id="1-re-모듈">1. re 모듈</h2>
<ul>
<li>re(regular expression) : python에서 정규표현식을 지원하기 위해 제공하는 모듈
(파이썬 설치 시 자동으로 설치되는 기본(표준) 라이브러리이다.)<pre><code class="language-python">import re
p = re.compile(&#39;ab*&#39;) // &#39;ab*&#39;를 컴파일한다</code></pre>
re.compile을 사용하여 정규표현식을 컴파일하고 돌려주는 객체(p)를 사용하여 이후 작업을 수행하게 된다.</li>
<li>정규식을 컴파일할 때 특정 옵션을 주는 것도 가능하다.(이후에 다루기로 한다.)</li>
<li>패턴(p)란 정규식을 컴파일한 결과</li>
</ul>
<h2 id="2-정규식을-이용한-문자열-검색">2. 정규식을 이용한 문자열 검색</h2>
<ul>
<li>컴파일된 패턴 객체는 다음의 4가지 메서드를 가진다.<table>
<thead>
<tr>
<th align="center">Method</th>
<th align="center">목적</th>
</tr>
</thead>
<tbody><tr>
<td align="center">match()</td>
<td align="center">문자열의 처음부터 정규식과 매치되는지 조사</td>
</tr>
<tr>
<td align="center">search()</td>
<td align="center">문자열 전체를 검색하여 정규식과 매치되는지 조사</td>
</tr>
<tr>
<td align="center">findall()</td>
<td align="center">정규식과 매치되는 모든 문자열(substring)을 리스트로 돌려준다</td>
</tr>
<tr>
<td align="center">finditer()</td>
<td align="center">정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 돌려준다</td>
</tr>
</tbody></table>
</li>
<li>match, search는 정규식과 매치될 때 match 객체를 돌려주고, 아닐 경우 None을 돌려준다.<ul>
<li>match 객체 : 정규식의 검색 결과로 돌려주는 객체<pre><code class="language-python">// 메서드 사용을 위한 패턴 //
import re
p = re.compile(&#39;[a-z]+&#39;)</code></pre>
<h3 id="1-match">1. match</h3>
</li>
</ul>
</li>
<li>match : 문자열의 처음부터 정규식과 매치되는지 조사한다.<pre><code class="language-python">m = p.match(&quot;python&quot;)
print(m)
</code></pre>
</li>
</ul>
<blockquote>
<blockquote>
<p>&lt;re.Match object; span=(0, 6), match=&#39;python&#39;&gt;</p>
</blockquote>
</blockquote>
<pre><code>* &quot;python&quot;문자열이 `[a-z]+`에 부합하므로 `match` 객체를 돌려준다.
```python
m = p.match(&quot;3 python&quot;)
print(m)

&gt;&gt; None</code></pre><ul>
<li>&quot;3 python&quot; 문자열의 3이 <code>[a-z]+</code>에 부합하지 않으므로 <code>None</code>을 돌려준다.</li>
<li>일반적인 정규식 프로그램의 흐름<pre><code class="language-python">p = re.compile(정규식)
m = p.match(&#39;string goes here&#39;)
</code></pre>
</li>
</ul>
<p>// match의 결과값이 있을 경우만 작업을 수행 //
if m:
    print(&#39;Match found: &#39;, m.group())
else:
    print(&#39;No match&#39;)</p>
<pre><code>
### 2. search
* search : 문자열 전체에서 매치되는 경우를 조사한다.
```python
m = p.search(&quot;python&quot;)
print(m)

&gt;&gt; &lt;re.Match object; span=(0, 6), match=&#39;python&#39;&gt;</code></pre><pre><code class="language-python">m = p.search(&quot;3 python&quot;)
print(m)

&gt;&gt; &lt;re.Match object; span=(2, 8), match=&#39;python&#39;&gt;</code></pre>
<ul>
<li>match를 성공했을 때와 같은 객체를 돌려준다.</li>
</ul>
<h3 id="3-findall">3. findall</h3>
<ul>
<li>findall : 정규식과 매치된 문자열들을 리스트 형식으로 돌려준다.<pre><code class="language-python">result = p.findall(&quot;life is too short&quot;)
print(result)
</code></pre>
</li>
</ul>
<blockquote>
<blockquote>
<p>[&#39;life&#39;, &#39;is&#39;, &#39;too&#39;, &#39;short&#39;]</p>
</blockquote>
</blockquote>
<pre><code>
### 4. finditer
* finditer : findall과 동일하지만 결과로 반복 가능한 객체(iterator object)를 돌려준다.
(반복 가능한 객체가 포함하는 각각의 요소는 match 객체이다.)
```python
result = p.finditer(&quot;life is too short&quot;)
print(result)

&gt;&gt; &lt;callable_iterator object at 0x000002AF97B74E50&gt;

for r in result:
    print(r)

&gt;&gt; &lt;re.Match object; span=(0, 4), match=&#39;life&#39;&gt;
&gt;&gt; &lt;re.Match object; span=(5, 7), match=&#39;is&#39;&gt;
&gt;&gt; &lt;re.Match object; span=(8, 11), match=&#39;too&#39;&gt;
&gt;&gt; &lt;re.Match object; span=(12, 17), match=&#39;short&#39;&gt;</code></pre><h2 id="3-match-객체의-메서드">3. match 객체의 메서드</h2>
<table>
<thead>
<tr>
<th align="center">method</th>
<th align="center">목적</th>
</tr>
</thead>
<tbody><tr>
<td align="center">group()</td>
<td align="center">매치된 문자열을 돌려준다</td>
</tr>
<tr>
<td align="center">start()</td>
<td align="center">매치된 문자열의 시작 위치를 돌려준다</td>
</tr>
<tr>
<td align="center">end()</td>
<td align="center">매치된 문자열의 끝 위치를 돌려준다</td>
</tr>
<tr>
<td align="center">span()</td>
<td align="center">매치된 문자열의 (시작, 끝)에 해당하는 튜플을 돌려준다.</td>
</tr>
</tbody></table>
<ul>
<li><p>match로 받은 객체일 경우</p>
<pre><code class="language-python">import re
p = re.compile(&#39;[a-z]+&#39;)
m = p.match(&quot;python&quot;)
m.group()
&gt;&gt; &#39;python&#39;
m.start() // match 메서드는 시작부터 조사하기 때문에 start는 항상 0이다.
&gt;&gt; 0
m.end()
&gt;&gt; 6
m.span()
&gt;&gt; (0, 6)</code></pre>
</li>
<li><p>search로 받은 객체일 경우</p>
<pre><code class="language-python">m = p.match(&quot;3 python&quot;)
m.group()
&gt;&gt; &#39;python&#39;
m.start()
&gt;&gt; 2
m.end()
&gt;&gt; 8
m.span()
&gt;&gt; (2, 8)</code></pre>
</li>
</ul>
<blockquote>
<p>[모듈 단위로 수행하기]</p>
<p>지금까지 <code>re.compile</code>을 사용하여 컴파일된 패턴 객체를 사용했다면
re 모듈은 보다 축약한 형태로 사용할 수 있는 방법을 제공한다.</p>
<pre><code class="language-python">// 기본적인 컴파일된 패턴과 매치된 객체 //
p = re.compile(&#39;[a-z]+&#39;)
m = p.match(&quot;python&quot;)

// 모듈 내에서 축약시켜 사용하는 예 //
m = re.match(&#39;[a-z]+&#39;, &quot;python&quot;)</code></pre>
<p>컴파일과 메서드를 한 번에 수행할 수 있지만, 한 번 만든 패턴 객체를
여러번 사용해야 할 때는 <code>re.compile</code>을 사용하는 것이 편하다.</p>
</blockquote>
<h2 id="4-컴파일-옵션">4. 컴파일 옵션</h2>
<ul>
<li>정규식을 컴파일할 때 다음 옵션을 사용할 수 있다.
(<code>re.DOTALL</code>처럼 전체 옵션을 사용하거나 <code>re.S</code>처럼 약어를 사용할 수 있다.)</li>
</ul>
<table>
<thead>
<tr>
<th align="center">option(약어)</th>
<th align="center">기능</th>
</tr>
</thead>
<tbody><tr>
<td align="center">DOTALL(S)</td>
<td align="center"><code>&#39;.&#39;</code>이 줄바꿈 문자를 포함하여 모든 문자와 매치할 수 있도록 한다</td>
</tr>
<tr>
<td align="center">IGNORECASE(I)</td>
<td align="center">대소문자에 관계없이 매치할 수 있도록 한다</td>
</tr>
<tr>
<td align="center">MULTILINE(M)</td>
<td align="center">여러줄과 매치할 수 있도록 한다(<code>&#39;^&#39;</code>,<code>&#39;$&#39;</code>메타문자의 사용과 관계가 있는 옵션이다)</td>
</tr>
<tr>
<td align="center">VERBOSE(X)</td>
<td align="center">verbose 모드를 사용할 수 있도록 한다(정규식을 보기 편하게 만들 수 있고 주석 등을 사용할 수 있게된다)</td>
</tr>
</tbody></table>
<h3 id="1-dotall-s">1. DOTALL, S</h3>
<ul>
<li>DOTALL(S) : <code>.</code> 사용 시 줄바꿈 문자(<code>\n</code>)도 포함하여 매치한다.<pre><code class="language-python">import re
</code></pre>
</li>
</ul>
<p>// 기본 컴파일 시 //
p = re.compile(&#39;a.b&#39;)
m = p.match(&#39;a\nb&#39;)
print(m)</p>
<blockquote>
<blockquote>
<p>None</p>
</blockquote>
</blockquote>
<p>// DOTALL 옵션 사용 시 //
p = re.compile(&#39;a.b&#39;, re.DOTALL)
m = p.match(&#39;a\nb&#39;)
print(m)</p>
<blockquote>
<blockquote>
<p>&lt;re.Match object; span=(0, 3), match=&#39;a\nb&#39;&gt;</p>
</blockquote>
</blockquote>
<pre><code>
### 2. IGNORCASE, I
* IGNORECASE(I) : 대소문자 구별 없이 매치를 수행하는 옵션
```python
p = re.compile(&#39;[a-z]+&#39;, re.I)
p.match(&#39;python&#39;)
&gt;&gt; &lt;re.Match object; span=(0, 6), match=&#39;python&#39;&gt;
p.match(&#39;Python&#39;)
&gt;&gt; &lt;re.Match object; span=(0, 6), match=&#39;Python&#39;&gt;
p.match(&#39;PYTHON&#39;)
&gt;&gt; &lt;re.Match object; span=(0, 6), match=&#39;PYTHON&#39;&gt;</code></pre><h3 id="3-multiline-m">3. MULTILINE, M</h3>
<ul>
<li>MULTILINE(M) : <code>^</code>, <code>$</code>와 연관된 옵션으로, <code>^</code> 또는 <code>$</code> 옵션을 각 라인별로 적용시키고 싶을 경우 사용한다.
(각 줄마다 사용되므로 줄바꿈 문자(<code>\n</code>)가 있는 경우에 사용한다.)<pre><code class="language-python">import re
</code></pre>
</li>
</ul>
<p>// 기본적인 &#39;^&#39;를 사용한 정규식 매치 //
p = re.compile(&quot;^python\s\w+&quot;)</p>
<p>data = &quot;&quot;&quot;python one
life is too short
python two
you need python
python three&quot;&quot;&quot;</p>
<p>print(p.findall(data))</p>
<blockquote>
<blockquote>
<p>[&#39;python one&#39;]</p>
</blockquote>
</blockquote>
<p>// MULTILINE 옵션을 이용한 정규식 매치 //
p = re.compile(&quot;^python\s\w+&quot;, re.MULTILINE)</p>
<p>data = &quot;&quot;&quot;python one
life is too short
python two
you need python
python three&quot;&quot;&quot;</p>
<p>print(p.findall(data))</p>
<blockquote>
<blockquote>
<p>[&#39;python one&#39;, &#39;python two&#39;, &#39;python three&#39;]</p>
</blockquote>
</blockquote>
<pre><code>
### 4. VERBOSE, X
* VERBOSE(X) : 정규식을 주석 또는 줄 단위로 구분하여 사용 가능(가독성 증가)
* 문자열에 사용된 whitespace는 컴파일할 때 제거된다. 그리고 줄 단위로 #기호를 사용하여 주석문을 작성할 수 있다.
(단 `[]` 안에 사용한 whitespace는 제외된다.)
```python
// VERBOSE 적용 전 정규식 //
charref = re.compile(r&#39;&amp;[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);&#39;)

// VERBOSE 적용 후 사용 가능한 정규식 //
charref = re.compile(r&quot;&quot;&quot;
 &amp;[#]                # Start of a numeric entity reference
 (
     0[0-7]+         # Octal form
   | [0-9]+          # Decimal form
   | x[0-9a-fA-F]+   # Hexadecimal form
 )
 ;                   # Trailing semicolon
&quot;&quot;&quot;, re.VERBOSE)</code></pre><h2 id="5-백슬래시-문제">5. 백슬래시 문제</h2>
<ul>
<li>정규 표현식을 파이썬에서 사용하는 경우 <code>\</code>는 혼란을 준다.<pre><code class="language-python">// &quot;\section&quot;문자열을 찾기 위한 정규식 //
  \section
==&gt; &#39;\s&#39;문자가 whitespace로 해석되어 의도한 매치 불가
  \section : [ \t\n\r\f\v]ection 과 동일
</code></pre>
</li>
</ul>
<p>// &#39;&#39;를 문자로 인식하게 하기 위해 &#39;\&#39;(두 개를 사용) 이스케이프 처리를 한다. //
    \section
==&gt; 파이썬 정규식 엔진에선 문자열 리터럴 규칙에 따라 &#39;\&#39;이 &#39;&#39;로 변경된다.
    \section : \section으로 변경됨(파이썬 문자열 리터럴 규칙에 따라)
    (이 문제는 파이썬에서만 발생한다.)</p>
<p>// &#39;\&#39;를 문자로 전달하기 위해선 &#39;\\&#39;를 사용해야 한다. ==&gt; 비효율 //
// 파이썬 정규식의 &#39;Raw String&#39;규칙을 이용하여 처리할 수 있다. //
    &#39;\\section&#39; == r&#39;\section&#39;
==&gt; ex) p = re.compile(r&#39;\section&#39;)</p>
<p>// 백슬래시를 사용하지 않는 정규식이라면 &#39;r&#39;의 유무에 상관없이 동일한 정규식이 된다. //</p>
<pre><code>
## 6. 문자열 바꾸기

### 1. re.sub()
* `re.sub(바꿀 문자열, 대상 문자열, count=n(바꿀 횟수))` : `대상 문자열`에서 컴파일된 패턴에 해당하는 문자를 `바꿀 문자열`로 바꾼다. `count`가 있다면 그 횟수만큼만 바꾼다.
```python
p = re.compile(&#39;(blue|white|red)&#39;)
s = p.sub(&#39;colour&#39;, &#39;blue socks and red shoes&#39;)

// &quot;blue&quot;, &quot;red&quot; =&gt; &quot;colour&quot; //
print(s)
&gt;&gt; &#39;colour socks and colour shoes&#39;

// &#39;count&#39;를 사용한 경우 //
s = p.sub(&#39;colour&#39;, &#39;blue socks and red shoes&#39;, count=1)

// 첫 번째인 &quot;blue&quot;만 &quot;colour&quot;로 바뀜 //
print(s)
&gt;&gt; &#39;colour socks and red shoes&#39;</code></pre><h3 id="2-sub와-참조구문-사용">2. sub()와 참조구문 사용</h3>
<ul>
<li><code>sub()</code>를 사용할 때 참조구문을 사용할 수 있다.<pre><code class="language-python">// &#39;그룹명&#39;을 통한 참조와 sub() 활용 //
p = re.compile(r&quot;(?P&lt;name&gt;\w+)\s+(?P&lt;phone&gt;(\d+)[-]\d+[-]\d+)&quot;)
</code></pre>
</li>
</ul>
<p>// &#39;\g&lt;그룹명&gt;&#39;을 통해 sub()에서 사용 가능하다. //
print(p.sub(&quot;\g<phone> \g<name>&quot;, &quot;park 010-1234-1234&quot;))</p>
<blockquote>
<blockquote>
<p>010-1234-1234 park</p>
</blockquote>
</blockquote>
<p>// 그룹 &#39;인덱스&#39;를 통한 참조와 sub() 활용 //
p = re.compile(r&quot;(?P<name>\w+)\s+(?P<phone>(\d+)[-]\d+[-]\d+)&quot;)
print(p.sub(&quot;\g&lt;2&gt; \g&lt;1&gt;&quot;, &quot;park 010-1234-1234&quot;))</p>
<blockquote>
<blockquote>
<p>010-1234-1234 park</p>
</blockquote>
</blockquote>
<pre><code>
### 3. sub()에 매개변수로 함수 넣기
* `sub()`의 첫 번째 매개변수로 함수를 넣을 수 있다.
```python
// 10진수를 16진수로 바꾸는 함수 //
def hexrepl(match):
    value = int(match.group())
    return hex(value)

// sub()의 매개변수로 함수를 넘겨 10진수를 16진수로 변환 //ㅁ
p = re.compile(r&#39;\d+&#39;)
s = p.sub(hexrepl, &#39;Call 65490 for printing, 49152 for user code.&#39;)
print(s)
&gt;&gt; &#39;Call 0xffd2 for printing, 0xc000 for user code.&#39;</code></pre><h2 id="7-greedy-vs-non-greedy">7. Greedy vs Non-Greedy</h2>
<ul>
<li><p>Greedy : 같은 형식의 문자열일 경우 해당되는 모든 것이 매치된다.</p>
<pre><code class="language-python">// &quot;&lt;html&gt;&quot;만을 매치하기 어렵다 //
s = &#39;&lt;html&gt;&lt;head&gt;&lt;title&gt;Title&lt;/title&gt;&#39;
print(len(s))
&gt;&gt; 32
print(re.match(&#39;&lt;.*&gt;&#39;, s).span())
&gt;&gt; (0, 32)
print(re.match(&#39;&lt;.*&gt;&#39;, s).group())
&gt;&gt; &lt;html&gt;&lt;head&gt;&lt;title&gt;Title&lt;/title&gt;</code></pre>
</li>
<li><p><code>?</code>(Non-Greedy) : <code>?</code> non-greedy 문자로 가능한 한 최소한의 반복을 수행하도록 도움</p>
<pre><code class="language-python">s = &#39;&lt;html&gt;&lt;head&gt;&lt;title&gt;Title&lt;/title&gt;&#39;
print(re.match(&#39;&lt;.*?&gt;&#39;, s).group())
&gt;&gt; &lt;html&gt;
</code></pre>
</li>
</ul>
<p>print(re.findall(&#39;&lt;.*?&gt;&#39;, s))</p>
<blockquote>
<blockquote>
<p>[&#39;<html>&#39;, &#39;<head>&#39;, &#39;<title>&#39;, &#39;</title>&#39;]
```</p>
</blockquote>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 2021 Dev-Matching: 웹 백엔드 개발자(상반기)__로또의 최고 순위와 최저 순위]]></title>
            <link>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-2021-Dev-Matching-%EC%9B%B9-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%83%81%EB%B0%98%EA%B8%B0%EB%A1%9C%EB%98%90%EC%9D%98-%EC%B5%9C%EA%B3%A0-%EC%88%9C%EC%9C%84%EC%99%80-%EC%B5%9C%EC%A0%80-%EC%88%9C%EC%9C%84</link>
            <guid>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-2021-Dev-Matching-%EC%9B%B9-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%83%81%EB%B0%98%EA%B8%B0%EB%A1%9C%EB%98%90%EC%9D%98-%EC%B5%9C%EA%B3%A0-%EC%88%9C%EC%9C%84%EC%99%80-%EC%B5%9C%EC%A0%80-%EC%88%9C%EC%9C%84</guid>
            <pubDate>Wed, 29 Sep 2021 13:29:40 GMT</pubDate>
            <description><![CDATA[<p>[[프로그래머스] &gt; 코딩테스트 연습 &gt; 2021 Dev-Matching: 웹 백엔드 개발자(상반기) &gt; 로또의 최고 순위와 최저 순위]
(<a href="https://programmers.co.kr/learn/courses/30/lessons/77484">https://programmers.co.kr/learn/courses/30/lessons/77484</a>)</p>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<p><code>로또 6/45</code>(이하 &#39;로또&#39;로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. 1</p>
<table>
<thead>
<tr>
<th align="center">순위</th>
<th align="center">당첨 내용</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td align="center">6개 번호가 모두 일치</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center">5개 번호가 일치</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">4개 번호가 일치</td>
</tr>
<tr>
<td align="center">4</td>
<td align="center">3개 번호가 일치</td>
</tr>
<tr>
<td align="center">5</td>
<td align="center">2개 번호가 일치</td>
</tr>
<tr>
<td align="center">6(낙첨)</td>
<td align="center">그 외</td>
</tr>
</tbody></table>
<p>로또를 구매한 민우는 당첨 번호 발표일을 학수고대하고 있었습니다. 하지만, 민우의 동생이 로또에 낙서를 하여, 일부 번호를 알아볼 수 없게 되었습니다. 당첨 번호 발표 후, 민우는 자신이 구매했던 로또로 당첨이 가능했던 최고 순위와 최저 순위를 알아보고 싶어 졌습니다.
알아볼 수 없는 번호를 <code>0</code>으로 표기하기로 하고, 민우가 구매한 로또 번호 6개가 <code>44, 1, 0, 0, 31, 25</code>라고 가정해보겠습니다. 당첨 번호 6개가 <code>31, 10, 45, 1, 6, 19</code>라면, 당첨 가능한 최고 순위와 최저 순위의 한 예는 아래와 같습니다.</p>
<table>
<thead>
<tr>
<th align="center">당첨 번호</th>
<th align="center">31</th>
<th align="center">10</th>
<th align="center">45</th>
<th align="center">1</th>
<th align="center">6</th>
<th align="center">19</th>
<th align="center">결과</th>
</tr>
</thead>
<tbody><tr>
<td align="center">최고 순위 번호</td>
<td align="center">31</td>
<td align="center">0→10</td>
<td align="center">44</td>
<td align="center">1</td>
<td align="center">0→6</td>
<td align="center">25</td>
<td align="center">4개 번호 일치, 3등</td>
</tr>
<tr>
<td align="center">최저 순위 번호</td>
<td align="center">31</td>
<td align="center">0→11</td>
<td align="center">44</td>
<td align="center">1</td>
<td align="center">0→7</td>
<td align="center">25</td>
<td align="center">2개 번호 일치, 5등</td>
</tr>
<tr>
<td align="center">* 순서와 상관없이, 구매한 로또에 당첨 번호와 일치하는 번호가 있으면 맞힌 걸로 인정됩니다.</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">* 알아볼 수 없는 두 개의 번호를 각각 10, 6이라고 가정하면 3등에 당첨될 수 있습니다.</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">- 3등을 만드는 다른 방법들도 존재합니다. 하지만, 2등 이상으로 만드는 것은 불가능합니다.</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">* 알아볼 수 없는 두 개의 번호를 각각 11, 7이라고 가정하면 5등에 당첨될 수 있습니다.</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">- 5등을 만드는 다른 방법들도 존재합니다. 하지만, 6등(낙첨)으로 만드는 것은 불가능합니다.</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<p>민우가 구매한 로또 번호를 담은 배열 lottos, 당첨 번호를 담은 배열 win_nums가 매개변수로 주어집니다. 이때, 당첨 가능한 최고 순위와 최저 순위를 차례대로 배열에 담아서 return 하도록 solution 함수를 완성해주세요.</p>
<h3 id="1-제한사항">1. 제한사항</h3>
<ul>
<li><p>lottos는 길이 6인 정수 배열입니다.</p>
</li>
<li><p>lottos의 모든 원소는 0 이상 45 이하인 정수입니다.</p>
<ul>
<li>0은 알아볼 수 없는 숫자를 의미합니다.</li>
<li>0을 제외한 다른 숫자들은 lottos에 2개 이상 담겨있지 않습니다.</li>
<li>lottos의 원소들은 정렬되어 있지 않을 수도 있습니다.</li>
</ul>
</li>
<li><p>win_nums은 길이 6인 정수 배열입니다.</p>
</li>
<li><p>win_nums의 모든 원소는 1 이상 45 이하인 정수입니다.</p>
<ul>
<li><p>win_nums에는 같은 숫자가 2개 이상 담겨있지 않습니다.</p>
</li>
<li><p>win_nums의 원소들은 정렬되어 있지 않을 수도 있습니다.</p>
<h3 id="2-입출력-예">2. 입출력 예</h3>
<table>
<thead>
<tr>
<th align="center">lottos</th>
<th align="center">win_nums</th>
<th align="center">result</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[44,1,0,0,31,25]</td>
<td align="center">[31,10,45,1,6,19]</td>
<td align="center">[3,5]</td>
</tr>
<tr>
<td align="center">[0,0,0,0,0,0]</td>
<td align="center">[38,19,20,40,15,25]</td>
<td align="center">[1,6]</td>
</tr>
<tr>
<td align="center">[45,4,35,20,3,9]</td>
<td align="center">[20,9,3,45,4,35]</td>
<td align="center">[1,1]</td>
</tr>
<tr>
<td align="center">## 2. 풀이</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">def solution(lottos, win_nums):</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">answer = []</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">// 매치된 숫자와 해당하는 당첨순위</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">win_dic = {</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">6 : 1,</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">5 : 2,</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">4 : 3,</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">3 : 4,</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">2 : 5,</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">1 : 6,</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">0 : 6</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">}</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">pair = 0 // 매치된 숫자 개수</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">zero = 0 // 숫자 0의 개수</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">for num in lottos:</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">if num in win_nums:</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">pair += 1</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">if num == 0:</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">zero += 1</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<p>answer.append(win_dic[pair + zero])
answer.append(win_dic[pair])
return answer
```</p>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Heap__디스크 컨트롤러]]></title>
            <link>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-heap%EB%94%94%EC%8A%A4%ED%81%AC-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC</link>
            <guid>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-heap%EB%94%94%EC%8A%A4%ED%81%AC-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC</guid>
            <pubDate>Wed, 29 Sep 2021 12:29:31 GMT</pubDate>
            <description><![CDATA[<p>[[프로그래머스] &gt; 코딩테스트 연습 &gt; 힙(Heap) &gt; 디스크 컨트롤러]
(<a href="https://programmers.co.kr/learn/courses/30/lessons/42627">https://programmers.co.kr/learn/courses/30/lessons/42627</a>)</p>
<p><a href="https://velog.io/@younge/Python-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%94%94%EC%8A%A4%ED%81%AC-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC-%ED%9E%99">풀이 참고 - 디스크 컨트롤러 - younge님의 velog</a></p>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<p>하드디스크는 한 번에 하나의 작업만 수행할 수 있습니다. 디스크 컨트롤러를 구현하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법은 요청이 들어온 순서대로 처리하는 것입니다.</p>
<p>예를들어</p>
<pre><code>    - 0ms 시점에 3ms가 소요되는 A작업 요청
    - 1ms 시점에 9ms가 소요되는 B작업 요청
    - 2ms 시점에 6ms가 소요되는 C작업 요청</code></pre><p>와 같은 요청이 들어왔습니다. 이를 그림으로 표현하면 아래와 같습니다.
<img src="https://grepp-programmers.s3.amazonaws.com/files/production/b68eb5cec6/38dc6a53-2d21-4c72-90ac-f059729c51d5.png" alt="이미지 1">
한 번에 하나의 요청만을 수행할 수 있기 때문에 각각의 작업을 요청받은 순서대로 처리하면 다음과 같이 처리 됩니다.
<img src="https://grepp-programmers.s3.amazonaws.com/files/production/5e677b4646/90b91fde-cac4-42c1-98b8-8f8431c52dcf.png" alt="이미지 2"></p>
<pre><code>    - A: 3ms 시점에 작업 완료 (요청에서 종료까지 : 3ms)
    - B: 1ms부터 대기하다가, 3ms 시점에 작업을 시작해서 12ms 시점에 작업 완료(요청에서 종료까지 : 11ms)
    - C: 2ms부터 대기하다가, 12ms 시점에 작업을 시작해서 18ms 시점에 작업 완료(요청에서 종료까지 : 16ms)</code></pre><p>이 때 각 작업의 요청부터 종료까지 걸린 시간의 평균은 10ms(= (3 + 11 + 16) / 3)가 됩니다.</p>
<p>하지만 A → C → B 순서대로 처리하면
<img src="https://grepp-programmers.s3.amazonaws.com/files/production/9eb7c5a6f1/a6cff04d-86bb-4b5b-98bf-6359158940ac.png" alt="이미지 3"></p>
<pre><code>    - A: 3ms 시점에 작업 완료(요청에서 종료까지 : 3ms)
    - C: 2ms부터 대기하다가, 3ms 시점에 작업을 시작해서 9ms 시점에 작업 완료(요청에서 종료까지 : 7ms)
    - B: 1ms부터 대기하다가, 9ms 시점에 작업을 시작해서 18ms 시점에 작업 완료(요청에서 종료까지 : 17ms)</code></pre><p>이렇게 A → C → B의 순서로 처리하면 각 작업의 요청부터 종료까지 걸린 시간의 평균은 9ms(= (3 + 7 + 17) / 3)가 됩니다.</p>
<p>각 작업에 대해 [작업이 요청되는 시점, 작업의 소요시간]을 담은 2차원 배열 jobs가 매개변수로 주어질 때, 작업의 요청부터 종료까지 걸린 시간의 평균을 가장 줄이는 방법으로 처리하면 평균이 얼마가 되는지 return 하도록 solution 함수를 작성해주세요. (단, 소수점 이하의 수는 버립니다)</p>
<h3 id="1-제한사항">1. 제한사항</h3>
<ul>
<li>jobs의 길이는 1 이상 500 이하입니다.</li>
<li>jobs의 각 행은 하나의 작업에 대한 [작업이 요청되는 시점, 작업의 소요시간] 입니다.</li>
<li>각 작업에 대해 작업이 요청되는 시간은 0 이상 1,000 이하입니다.</li>
<li>각 작업에 대해 작업의 소요시간은 1 이상 1,000 이하입니다.</li>
<li>하드디스크가 작업을 수행하고 있지 않을 때에는 먼저 요청이 들어온 작업부터 처리합니다.<h3 id="2-입출력-예">2. 입출력 예</h3>
<table>
<thead>
<tr>
<th align="center">jobs</th>
<th align="center">return</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[[0,3],[1,9],[2,6]]</td>
<td align="center">9</td>
</tr>
<tr>
<td align="center">## 2. 풀이</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">import heapq</td>
<td align="center"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>def solution(jobs):
    answer = 0
    start = -1 // 최근 작업 시작 시간
    cur = 0 // 현재 시간
    done = 0 // 끝낸 작업 수
    job_size = len(jobs) // 총 작업량
    heap = [] // 정리를 위한 힙 리스트
    h_size = 0 // 힙 사이즈</p>
<pre><code>while (done &lt; job_size):
    for job in jobs:
        // 작업요청시간이 최근작업시간보다 크고 현재시간보다 작은 경우
        // 힙에 [작업시간, 작업요청시간] 형식으로 푸시한다.
        if (start &lt; job[0] and job[0] &lt;= cur):
            heapq.heappush(heap, [job[1], job[0]])
            h_size += 1
    // 힙에 작업물이 있을 경우 작업량 순서로 꺼내 적용한다.
    if (0 &lt; h_size):
        job = heapq.heappop(heap)
        start = cur // 작업시작시간을 현재시간으로 변경
        cur += job[0] // 현재시간 + 작업시간 = 작업 후 현재시간
        answer += cur - job[1] // 현재시간 - 요청시간 = 요청부터 작업이 끝나기까지 시간
        h_size -= 1
        done += 1
    else:
        cur += 1
answer = int(answer / job_size) // 평균을 내주고 소수점 아래는 버린다.
return answer</code></pre><p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Heap__더 맵게]]></title>
            <link>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-heap%EB%8D%94-%EB%A7%B5%EA%B2%8C</link>
            <guid>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-heap%EB%8D%94-%EB%A7%B5%EA%B2%8C</guid>
            <pubDate>Wed, 29 Sep 2021 03:04:25 GMT</pubDate>
            <description><![CDATA[<p>[[프로그래머스] &gt; 코딩테스트 연습 &gt; 힙(Heap) &gt; 더 맵게]
(<a href="https://programmers.co.kr/learn/courses/30/lessons/42626">https://programmers.co.kr/learn/courses/30/lessons/42626</a>)</p>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/42626">python 힙(Heap)</a></p>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<p>매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다.</p>
<pre><code>섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2)</code></pre><p>Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다.
Leo가 가진 음식의 스코빌 지수를 담은 배열 scoville과 원하는 스코빌 지수 K가 주어질 때, 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성해주세요.</p>
<h3 id="1-제한사항">1. 제한사항</h3>
<ul>
<li>scoville의 길이는 2 이상 1,000,000 이하입니다.</li>
<li>K는 0 이상 1,000,000,000 이하입니다.</li>
<li>scoville의 원소는 각각 0 이상 1,000,000 이하입니다.</li>
<li>모든 음식의 스코빌 지수를 K 이상으로 만들 수 없는 경우에는 -1을 return 합니다.<h3 id="2-입출력-예">2. 입출력 예</h3>
<table>
<thead>
<tr>
<th align="center">scoville</th>
<th align="center">K</th>
<th align="center">return</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[1,2,3,9,10,12]</td>
<td align="center">7</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">## 2. 풀이</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">import heapq //heapq 라이브러리 불러오기</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>def solution(scoville, K):
    answer = 0
    s_lst = scoville
    heapq.heapify(s_lst) // 리스트를 힙(기본값 최소힙)으로 변환하기(정렬)
    node_size = len(s_lst) // 힙 크기(예제에서 6)</p>
<pre><code>while (node_size &gt; 1 and s_lst[0] &lt; K):
    min_n = heapq.heappop(s_lst) // 최소힙이므로 제일 작은 값 꺼내기
    min_m = heapq.heappop(s_lst) // 그 다음 작은 값 꺼내기
    heapq.heappush(s_lst, min_n + (min_m * 2)) // 섞은 음식 힙으로 추가(최소힙조건 만족)
    answer += 1 // 섞은 횟수
    node_size -= 1 // 힙 크기(섞이므로 줄어듦)

if (s_lst[0] &lt; K): // 모든 음식을 섞었음에도 조건을 만족하지 못했을 경우
    return -1

return answer</code></pre><p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Greedy__체육복]]></title>
            <link>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Greedy%EC%B2%B4%EC%9C%A1%EB%B3%B5</link>
            <guid>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Greedy%EC%B2%B4%EC%9C%A1%EB%B3%B5</guid>
            <pubDate>Tue, 13 Jul 2021 04:10:48 GMT</pubDate>
            <description><![CDATA[<p>[[프로그래머스] &gt; 코딩테스트 연습 &gt; 탐욕법 &gt; 체육복]
(<a href="https://programmers.co.kr/learn/courses/30/lessons/42862">https://programmers.co.kr/learn/courses/30/lessons/42862</a>)</p>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<p>점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.</p>
<p>전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.</p>
<h3 id="1-제한사항">1. 제한사항</h3>
<p>전체 학생의 수는 2명 이상 30명 이하입니다.
체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.</p>
<h3 id="2-입출력-예">2. 입출력 예</h3>
<table>
<thead>
<tr>
<th align="center">n</th>
<th align="center">lost</th>
<th align="center">reserve</th>
<th align="center">return</th>
</tr>
</thead>
<tbody><tr>
<td align="center">5</td>
<td align="center">[2, 4]</td>
<td align="center">[1, 3, 5]</td>
<td align="center">5</td>
</tr>
<tr>
<td align="center">5</td>
<td align="center">[2, 4]</td>
<td align="center">[3]</td>
<td align="center">4</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">[3]</td>
<td align="center">[1]</td>
<td align="center">2</td>
</tr>
</tbody></table>
<h2 id="2-풀이">2. 풀이</h2>
<pre><code class="language-python">def solution(n, lost, reserve):
    answer = 0
    # 학생 순서로 정렬(이 때는 모든 학생이 체육복을 가지고 있음)
    lst = [1 for __ in range(0, n)]

    # 체육복을 잃었거나 빌려줄 수 있는 경우의 셈(0 = 없음, 2 = 2벌)
    for los in lost:
        lst[los - 1] -= 1
    for res in reserve:
        lst[res - 1] += 1

    # 체육복 빌려주기 시작
    for i in range(0, n):
        # 0번 학생일 경우) 체육복이 2개라면 1번 학생이 0개일 경우 빌려줌
        if i == 0:
            if lst[i] == 2 and lst[i + 1] == 0:
                lst[i] -= 1
                lst[i + 1] += 1
        # 첫 번째와 마지막 학생이 아니라면 자신의 체육복이 2개일 때
        # 자신의 앞 학생부터 0개일 경우 빌려줌(아니라면 다음 학생)
        if i != 0 and i != n-1:
            if lst[i - 1] == 0 and lst[i] == 2:
                lst[i] -= 1
                lst[i - 1] += 1
            if lst[i] == 2 and lst[i + 1] == 0:
                lst[i] -= 1
                lst[i + 1] += 1
        if i == n - 1:
            if lst[i] == 2 and lst[i - 1] == 0:
                lst[i] -= 1
                lst[i - 1] += 1

    # 체육복을 입은(1) 모든 학생 수를 셈
    for i in lst:
        if i &gt;= 1:
            answer += 1
    return answer</code></pre>
<h2 id="3-고찰">3. 고찰</h2>
<p>나의 경우는 순서의 이점을 교묘하게 사용하여 문제를 해석하였는데, 보다 더 재미있는 코드를 짤 수 있을 것 같기도 하였다. 이번 문제는 그리디 문제 중 쉬운 만큼 접근만 정확하게 할 수 있다면, 코드 자체는 어렵지 않은 편이었다. 무엇보다 최선의 이득을 구하는 문제인 만큼 기초로써 손색없다 느꼈다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Windows 10 환경에서 Linux 사용하기 ]]></title>
            <link>https://velog.io/@kim-mg/Windows-10-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-Linux-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kim-mg/Windows-10-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-Linux-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 02 Mar 2021 07:57:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1-들어가며">1. 들어가며</h2>
<p>본래 나는 Windows 환경에서 ICT에 대해 배워왔고 작업해왔다. 그러던 내게 iMAC을 사용하게 될 일이 생겼는데, 달라진 환경에 적응하기도 전에 난관에 봉착했다. iMAC 환경 외 작업은 내 노트북으로 진행 되었는데, 노트북은 Windows 환경이었기 때문에 서로 다른 환경에서 같은 작업의 연속이 가능할까 하는 것이었다. 실제로도 개발도 환경에 따라 다르다고 하니 노트북에 MacOS의 Linux 환경을 만들어 주기로 했다.</p>
<p>P.S Linux는 환경이라기 보단 Kernel의 의미이다. 그래서 Linux 환경을 구축한다는 것은 Ubuntu 터미널을 사용한다는 것과 같다.</p>
<h2 id="2-설치하기">2. 설치하기</h2>
<p>Microsoft는 Linux환경을 사용할 수 있도록 WSL(Windows Subsystem for Linux)기능을 제공한다. 하여 MS사의 홈페이지에 있는 WSL 수동 설치 가이드를 따라가기로 했다.</p>
<h4 id="wsl-설치-가이드">WSL 설치 가이드</h4>
<p>👉 <a href="https://docs.microsoft.com/ko-kr/windows/wsl/install-win10">https://docs.microsoft.com/ko-kr/windows/wsl/install-win10</a></p>
<h3 id="1-linux용-windows-하위-시스템-사용">1. Linux용 Windows 하위 시스템 사용</h3>
<p>이 설정을 한 후에는 재부팅을 해야 적용되며 4번 단계를 진행할 수 있다.
2번 확인 및 업데이트 후, 1번과 3번을 진행하고 재부팅해 불필요한 수고를 줄일 수 있다.</p>
<ul>
<li><p><strong>설정창에서 직접 설정하기</strong>
[제어판] &gt; 프로그램 &gt; 프로그램 및 기능 &gt; Windows 기능 켜기/끄기 &gt; Linux용 Windows 하위 시스템 체크</p>
<p align="center">
<img src="https://images.velog.io/images/kim-mg/post/b73cd149-6f64-4cfb-bbc9-0bfb1c94e7a5/subsystem_for_linux_checkbox.PNG" alt="Linux용 Windows 하위 시스템 사용에 체크" style="margin:30px 0px 10px 0px">
</p>
<p style="text-align:center">Linux용 Windows 하위 시스템에 체크해 준다.</p>
</li>
<li><p><strong>PowerShell에서 CLI로 설정하기</strong>
Windows PowerShell 을 우클릭하여 관리자 권한으로 실행하고 다음 명령을 입력한다.
<code>dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart</code></p>
<p align="center">
<img src="https://images.velog.io/images/kim-mg/post/7a01dd3e-4203-4114-b2d5-c6af0ba20667/powershell_1.PNG" alt="CLI로 설정" style="margin:30px 0px 10px 0px">
작업 이후에 재부팅해야 적용된다.
</p>

</li>
</ul>
<h3 id="2-wsl-2-실행을-위한-요구-사항-확인">2. WSL 2 실행을 위한 요구 사항 확인</h3>
<p><code>Windows 로고 + R</code>로 실행창을 띄우고 <code>winver</code>를 입력해 현재 widows 버전을 확인한다.
(작성일 <strong>2021-03-02</strong> 기준)</p>
<ul>
<li>x64 시스템의 경우: <strong>버전 1903</strong> 이상, <strong>빌드 18362</strong> 이상</li>
<li>ARM64 시스템의 경우: <strong>버전 2004</strong> 이상, <strong>빌드 19041</strong> 이상</li>
<li>18362보다 낮은 빌드는 <code>WSL 2</code>를 지원하지 않으므로 Windows Update를 이용해 최신 버전으로 유지하도록 한다.<p align="center">
<img src="https://images.velog.io/images/kim-mg/post/a084e330-21b9-44d5-9681-5bcb5428fe2a/winver.PNG">
</p>

</li>
</ul>
<h3 id="3-virtual-machine-기능-사용">3. Virtual Machine 기능 사용</h3>
<p>1번과 같이 재부팅을 해야 4단계를 실행할 수 있다.</p>
<ul>
<li><p><strong>설정창에서 직접 설정하기</strong>
[제어판] &gt; 프로그램 &gt; 프로그램 및 기능 &gt; Windows 기능 켜기/끄기 &gt; Linux용 Windows 하위 시스템 체크</p>
<p align="center">
<img src="https://images.velog.io/images/kim-mg/post/64d2a152-3886-4003-9e23-eaa0e5658689/virtual_machine.png" alt="Linux용 Windows 하위 시스템 사용에 체크" style="margin:30px 0px 10px 0px">
가상 머신 플랫폼에 체크해 준다.
</p>
</li>
<li><p><strong>PowerShell에서 CLI로 설정하기</strong>
Windows PowerShell 을 우클릭하여 관리자 권한으로 실행하고 다음 명령을 입력한다.
<code>dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart</code></p>
<p align="center">
<img src="https://images.velog.io/images/kim-mg/post/54d89e54-016f-45fa-85c4-0bb763116ecf/powershell_2.PNG" alt="CLI로 설정" style="margin:30px 0px 10px 0px">
필자는 1번과 3번을 실행시킨 이후에 재부팅을 하여 이 설정 변경이 재부팅 이후에 적용되는 것인지 확인하지 못했다. 만약 1번을 진행시킨 이후라면 우선 4번을 진행해 보고 안될 시 재부팅을 통해 4번을 다시 진행하도록 하자.
</p>

</li>
</ul>
<h3 id="4-linux-커널-업데이트-패키지-다운로드">4. Linux 커널 업데이트 패키지 다운로드</h3>
<p>최신 패키지를 다운받고 실행하도록 하자. 실행할 때에는 관리자 권한을 요구한다면 <strong>&quot;예&quot;</strong>를 눌러 허용해 주도록 한다.</p>
<ul>
<li><a href="https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi">x64 머신용 최신 WSL2 Linux 커널 패키지 다운로드</a></li>
<li><a href="https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_arm64.msi">ARM64 머신용 다운로드</a></li>
</ul>
<p align="center">
  <img src="https://images.velog.io/images/kim-mg/post/5788c675-7ea2-492b-9c3a-529ed36854ed/linux_kernel.PNG" alt="Linux용 Windows 하위 시스템 사용에 체크" style="margin:30px 0px 10px 0px">
  파일이 열리지 않을 경우 1번 혹은 3번 이후 재부팅이 안된 것일 수 있으니 재부팅하고 다시 시도한다.
</p>

<h3 id="5-wsl-2를-기본-버전으로-설정">5. WSL 2를 기본 버전으로 설정</h3>
<p>PowerShell을 열고 이 명령을 실행하여 새 Linux 배포를 설치할 때 WSL 2를 기본 버전으로 설정한다.
<code>wsl --set-default-version 2</code>
<img src="https://images.velog.io/images/kim-mg/post/87f5891d-eaaa-4118-ad91-cd1ca4ae0d5c/powershell_3.PNG" alt="WSL 2를 기본 버전으로 설정"></p>
<h3 id="6-선택한-linux-배포-설치">6. 선택한 Linux 배포 설치</h3>
<ol>
<li><a href="https://aka.ms/wslstore">Microsoft Store</a>를 열고 사용할 Linux 배포를 설치한다.
여러 배포에 대한 링크는 가이드 페이지에서 확인할 수 있다.
SUSE, Kail, Debian, Fedora, Pengwin, Alpine 등 이미 테마가 적용된 배포 버전들이 있지만, 나는 기본이 되는 Ubuntu를 설치하기로 했다.
<img src="https://images.velog.io/images/kim-mg/post/302395e2-87a4-4f69-bb57-12c70a6ada15/ms_store_1.PNG" alt="MS_Store_Ubuntu"></li>
<li>배포 페이지에서 <code>받기</code>를 통해 설치한다.<p align="center">
<img src="https://images.velog.io/images/kim-mg/post/4b77ada5-15b0-497f-b3b6-f962f2a50767/ms_store_2.PNG" alt="MS_Store_Ubuntu_get" style="margin:30px 0px 10px 0px">
이후 설치된 Linux 배포를 처음 시작하면 콘솔 창이 열리고 파일이 압축 해제되고 PC에 저장될 때까지 1~2분 정도 걸린다.
</p></li>
<li>실행된 Ubuntu 창에서 <code>사용자</code>를 추가하고 <code>암호</code>를 설정해준다.
<img src="https://images.velog.io/images/kim-mg/post/9d42f330-7ff4-4662-9795-dbb34b54e40e/ubuntu_user_add.PNG" alt="Ubuntu 초기 사용자 등록"></li>
</ol>
<hr>
<h2 id="3-느낀점">3. 느낀점</h2>
<p>프로젝트마다 제작 환경은 천차만별이다. 여러 프로그램을 사용함에 있어서 호환 및 동작 여부를 판단해야 한다. 어느 프로그램은 윈도우 환경이 아닌 다른 환경에서 실행 가능할 수도 있다. 그를 대비해 개발자는 여러 환경을 로컬에 구축할 수 있는 능력이 필요하다. 하지만 사실을 말하자면 내가 하는 작업은 그저 c 언어 공부이며 사용하는 범위가 좁기 때문에 윈도우에서와 어떤 차이가 있는지는 체감할 수 없었다. 다만 후에 리눅스 개발환경이 필요해질 때면 당황하지 않고 해낼 수 있을 것 같다.</p>
<p><code>Ubuntu</code>를 통해 <code>Linux</code>환경을 구축해 봤다. 보이는 것은 터미널일 뿐이었는데 이 터미널을 마음대로 커스터마이징 할 수 있다는 것을 알게 되었다. 내 맘대로 꾸미는 터미널은 못 참는다. 바로 진행시키러 가야겠다.</p>
<p>P.S 이미지 밑에 캡션을 넣었는데 미리보기에선 적용되어 보이지만 실제 글에선 적용되지 않았음을 확인했다. Velog 측에서 적용되도록 해주었으면 한다. 😥</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Brute-Force Search__모의고사]]></title>
            <link>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</link>
            <guid>https://velog.io/@kim-mg/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</guid>
            <pubDate>Sun, 31 Jan 2021 05:51:06 GMT</pubDate>
            <description><![CDATA[<p><a href="https://programmers.co.kr/learn/courses/30/lessons/42840">[프로그래머스] &gt; 코딩테스트 연습 &gt; 완전탐색 &gt; 모의고사</a></p>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<p>수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.</p>
<pre><code>1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...</code></pre><p>1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.</p>
<h3 id="1-제한-조건">1. 제한 조건</h3>
<ul>
<li>시험은 최대 10,000 문제로 구성되어있습니다.</li>
<li>문제의 정답은 1, 2, 3, 4, 5중 하나입니다.</li>
<li>가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.</li>
</ul>
<h3 id="2-입출력-예">2. 입출력 예</h3>
<table>
<thead>
<tr>
<th align="center">answers</th>
<th align="center">return</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>[1,2,3,4,5]</strong></td>
<td align="center"><strong>[1]</strong></td>
</tr>
<tr>
<td align="center"><strong>[1,3,2,4,2]</strong></td>
<td align="center"><strong>[1,2,3]</strong></td>
</tr>
</tbody></table>
<h2 id="2-풀이">2. 풀이</h2>
<p>세 사람의 채점이 동시에 이뤄질 수 있도록 알고리즘을 구현하는 데에 중점을 두었습니다.
매 인덱스마다 채점을 진행하며 각 사람의 정답 체크 리스트의 크기에 맞출 수 있는 조건을 주었고, 주어진 문제가 모두 채점되면 while 문을 종료하고 제일 많이 맞춘 정답 수를 찾아 조건에 맞는 사람을 찾아냅니다.</p>
<pre><code class="language-python">def solution(answers):
    answer = []
    # 각 사람의 정답 찍기 리스트
    first = [1,2,3,4,5]
    second = [2,1,2,3,2,4,2,5]
    third = [3,3,1,1,2,2,4,4,5,5]

    # 주어진 정답을 비교할 수 있게 사용할 인덱스를 정의
    ans_idx = 0
    first_idx = 0
    second_idx = 0
    third_idx = 0

    # 각 수포자 순서대로 맞춘 정답 수 입력 리스트
    score = [0, 0, 0]

    # 정답 채점!!
    while True:
        # 각 사람의 정답 찍기 리스트 크기를 넘어가면 자동으로 처음 원소(0)로 변환
        if first_idx == len(first):
            first_idx = 0
        if second_idx == len(second):
            second_idx = 0
        if third_idx == len(third):
            third_idx = 0

        # 문제의 정답과 각 사람의 답
        ans = answers[ans_idx] 
        fir = first[first_idx]
        sec = second[second_idx]
        thi = third[third_idx]

        # 정답 비교!!
        if fir == ans:
            score[0] += 1
        if sec == ans:
            score[1] += 1
        if thi == ans:
            score[2] += 1

        # 다음 문제의 인덱스(순번)
        ans_idx += 1
        first_idx += 1
        second_idx += 1
        third_idx += 1

        # 문제가 끝났다면 while 문 탈출
        if ans_idx == len(answers):
            break

    # 최고 점수 정의
    high_score = max(score)

    # 자신의 점수가 최고 점수와 같다면 answer 리스트에 추가
    for idx, sco in enumerate(score):
        if sco == high_score:
            answer.append(idx + 1)

    return answer</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Velog [Markdown] 사용법]]></title>
            <link>https://velog.io/@kim-mg/velog-%EA%B8%80%EC%93%B0%EA%B8%B0-markdown-%EC%9E%91%EC%84%B1%EB%B2%95</link>
            <guid>https://velog.io/@kim-mg/velog-%EA%B8%80%EC%93%B0%EA%B8%B0-markdown-%EC%9E%91%EC%84%B1%EB%B2%95</guid>
            <pubDate>Thu, 28 Jan 2021 05:42:05 GMT</pubDate>
            <description><![CDATA[<p>나도 나만의 블로그를 가져야겠다 싶어 Velog를 시작했다.
글을 작성하려는데 웬 생소한 페이지에 너무나도 간결한 도구들에 당황했다.
지금껏 한글이나 엑셀 또는 파워포인트만 접해온 내게 Velog의 글쓰기는 그렇게 생소하게 다가왔다.
분명 다른 사람들은 이쁘게 잘 사용하고 있었지만, 내게 주어진 조건은 단촐하기 그지없었다.
찾아보니 이러한 글쓰기 방식은 Markdown에 기인하고 있었다.
정보의 바다에는 내가 유용하게 Markdown을 사용하게 할 많은 정보들이 있었지만, 필요할 때마다 중구난방으로 정보를 수집하기 귀찮았던 나는 Markdown을 쓰는 방법을 모아 내가 보기 쉽도록 정리하여 보관하기로 했다.</p>
<h1 id="1-markdown-이란">1. Markdown 이란?</h1>
<p>일반 텍스트(Plaintext) 기반의 경량 마크업(Markup) 언어이다. 그림의 표현같은 오브젝트가 아닌 읽을 수 있는 문자열인 일반 텍스트, 태그 등을 이용하여 문서나 데이터의 구조를 명기하는 마크업 언어인 것이다.</p>
<p>존 그루버(Jhon Gruber)가 2004년에 만들었고 지금은 세계에서 가장 대중적인 언어라고 한다.
내게 큰 해당사항은 없다.(알고 난 후에는 간결하고 편리한 방식에 매료되었다.)</p>
<p>마크다운(Markdown)은 워드 프로세서에서 단추를 눌러 서식을 즉시 변경시키는 위지위그(WYSIWYG) 방식의 편집기와 다르게, 마크다운(Markdown) 구문을 이용하여 어떤 단어나 구문의 서식을 나타낸다.</p>
<p>Velog의 글쓰기 방식은 마크다운(Markdown)에서 여러 기능을 추가한 방식으로 생각된다.</p>
<h1 id="2-markdown-을-쓰는-이유">2. Markdown 을 쓰는 이유?</h1>
<p>편리한 단추와 도구들을 보유한 워드 프로세서들이 있는데 굳이 마크다운(Markdown)을 쓰는 이유는 </p>
<h3 id="1-범용성이-뛰어나다">1. 범용성이 뛰어나다.</h3>
<p>마크다운(Markdown)은 <strong>모든 것</strong>에 사용할 수 있다. 웹 사이트, 문서, 메모, 책, 프레젠테이션, 전자 메일 등 여러 형식 또는 결과물을 만드는데 사용할 수 있다는 것이다.</p>
<h3 id="2-이식-가능하다">2. 이식 가능하다.</h3>
<p>마크다운(Markdown) 형식의 텍스트가 포함된 파일은 거의 <strong>모든 응용 프로그램</strong>을 사용하여 열 수 있다. 이는 사용한 응용 프로그램을 통해서만 열 수 있는 워드 프로세싱 응용 프로그램과 비교되는 이점을 가진다.</p>
<h3 id="3-독립적으로-사용할-수-있다">3. 독립적으로 사용할 수 있다.</h3>
<p><strong>운영 체제를 실행하는 모든 장치</strong>에서 마크다운(Markdown) 형식의 텍스트를 만들 수 있다.</p>
<h3 id="4-점유율이-높다">4. 점유율이 높다.</h3>
<p>주요 커뮤니티 사이트(Reddit, GitHub) 등의 웹사이트와 데스크탑, 웹 기반 어플리케이션 등 많은 곳에서 마크다운(Markdown)을 지원한다.(점유율이란 단어를 사용하는 것이 맞는지는 모르겠다.)</p>
<h1 id="3-velog-시작하기">3. Velog 시작하기</h1>
<p>지금까지 Velog 글쓰기 방식의 기반이 된 마크다운(Markdown)의 관련 내용을 살펴봤다. 이제 Velog 글쓰기에 필요한 기능을 설명하기로 하고, 해당 기능을 통해 개성있는 나만의 Velog를 만들고자 한다.</p>
<h2 id="1-제목headings">1. 제목(Headings)</h2>
<p>제목은 <code>#</code>으로 나타낼 수 있고 HTML에서의 <code>h1</code>부터 <code>h6</code>까지 표현할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code># h1
## h2
### h3
#### h4
##### h5
###### h6</code></pre><p>💻 결과</p>
<h1 id="h1">h1</h1>
<h2 id="h2">h2</h2>
<h3 id="h3">h3</h3>
<h4 id="h4">h4</h4>
<h5 id="h5">h5</h5>
<h6 id="h6">h6</h6>
<p>💡 <code>h1</code>과 <code>h2</code>는 <code>#</code>말고도 <code>=</code>와 <code>-</code>로 대체가 가능하다.</p>
<p>✍ 작성 시</p>
<pre><code>Heading level 1(h1)
===================
Heading level 2(h2)
-------------------</code></pre><p>💻 결과
Heading level 1(h1)
===================
Heading level 2(h2)</p>
<hr>
<p>제목을 쓸 경우에는 <code>#</code>구문 입력 후 &#39; &#39;한 칸 띄어쓴 다음에 사용해야 한다.</p>
<h2 id="2-문단-단락paragraphs">2. 문단, 단락(Paragraphs)</h2>
<p>마크다운(Markdown)에선 문단을 나눌 때 문단 사이에 한 줄을 비워두는 것으로 구분한다.</p>
<p>✍ 작성 시</p>
<pre><code>문단을 나눌 경우, 문단 사이에 한 줄의 빈 공간이 있는 것으로 구분짓는다.

문단의 첫 문장에 들여쓰기를 하는 것과 다르므로 유의하여야 하지만 글 작성에 크게 주의하여야 할 점은 아닌 것 같다.</code></pre><p>💻 결과</p>
<p>문단을 나눌 경우, 문단 사이에 한 줄의 빈 공간이 있는 것으로 구분짓는다.</p>
<p>문단의 첫 문장에 들여쓰기를 하는 것과 다르므로 유의하여야 하지만 글 작성에 크게 주의하여야 할 점은 아닌 것 같다.</p>
<h2 id="3-줄-바꿈line-breaks">3. 줄 바꿈(Line Breaks)</h2>
<p>줄 바꿈은 <code>&lt;br&gt;</code>를 이용하여 할 수 있다. 여러 번 사용 시 사용한 수 만큼 줄 바꿈을 시행한다.</p>
<p>✍ 작성 시</p>
<pre><code>문단을 나눌 경우 enter 키를 이용하여 문단 사이의 하나의 빈 줄을 넣는다.&lt;br&gt;또한 문단은 `&lt;br&gt;`을 두 번 사용하여 구분지을 수도 있다.</code></pre><p>💻 결과</p>
<p>문단을 나눌 경우 enter 키를 이용하여 문단 사이의 하나의 빈 줄을 넣는다.<br>또한 문단은 <code>&lt;br&gt;</code>을 두 번 사용하여 구분지을 수도 있다</p>
<h2 id="4-강조-취소선emphasis-strikethrough">4. 강조, 취소선(Emphasis, Strikethrough)</h2>
<p>글을 강조하거나 취소하는 표시를 할 경우엔 <code>*</code>또는 <code>_</code>, 그리고 <code>~</code>를 이용하여 나타낼 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>**굵게** (Bold)
__굵게__
*기울임* (Italic)
_기울임_
***강조와 기울임***
___강조와 기울임___
~~취소선~~ (취소선은 &#39;~&#39;를 꼭 두 개 사용하도록 하자)</code></pre><p>💻 결과</p>
<p><strong>강조</strong>
<strong>강조</strong>
<em>기울임</em>
<em>기울임</em>
<strong><em>강조와 기울임</em></strong>
<strong><em>강조와 기울임</em></strong>
<del>취소선</del></p>
<p>💡 여담이지만 마크다운(Markdown) 어플리케이션은 단어 중간의 <code>_</code> 처리하는 방법을 지원하지 않으니 <code>*</code>를 사용할 것을 권장한다고 한다.</p>
<h2 id="5-인용구blockquotes">5. 인용구(Blockquotes)</h2>
<p>인용구를 사용할 경우 문단 앞에 <code>&gt;</code>를 추가한다.</p>
<p>✍ 작성 시</p>
<pre><code>&gt; 인용구를 사용하여 글을 쓸 경우 문단 앞에 &#39;&gt;&#39;를 추가한다.
&gt;
&gt; 단락을 나눌 경우 빈 공간에 &#39;&gt;&#39;를 입력하면 된다.
&gt;
&gt;&gt; ### 인용구 내에서 인용구의 재사용, *강조* 또는 &#39;제목&#39;
&gt;&gt; 1. **리스트** 또한 사용 가능하다.
&gt;&gt; - 자유롭게 사용할 수 있는 점 기억해 두었으면 한다.</code></pre><p>💻 결과</p>
<blockquote>
<p>인용구를 사용하여 글을 쓸 경우 문단 앞에 &#39;&gt;&#39;를 추가한다.</p>
<p>단락을 나눌 경우 빈 공간에 &#39;&gt;&#39;를 입력하면 된다.</p>
<blockquote>
<h3 id="인용구-내에서-인용구의-재사용-강조-또는-제목">인용구 내에서 인용구의 재사용, <em>&#39;강조&#39;</em> 또는 &#39;제목&#39;</h3>
<ol>
<li><strong>리스트</strong> 또한 사용 가능하다.</li>
</ol>
<ul>
<li>자유롭게 사용할 수 있는 점 기억해 두었으면 한다.</li>
</ul>
</blockquote>
</blockquote>
<h2 id="6-목록lists">6. 목록(Lists)</h2>
<p>목록은 <code>순서가 있는 목록</code>과 <code>순서가 없는 목록</code>으로 나뉜다.</p>
<h3 id="1-순서가-있는-목록">1. 순서가 있는 목록</h3>
<p>숫자 <code>1</code>과 <code>.</code>(온점)을 합한 것으로 시작하며 같은 형식의 순차적인 번호 표기로 나타낸다.
<code>1.</code>이후에 오는 숫자는 꼭 연속적일 필요는 없지만 처음은 <code>1.</code>로 시작하여야 한다.</p>
<p>✍ 작성 시</p>
<pre><code>1. 첫 번째 목록
2. 두 번째 목록
3. 세 번째 목록
3. 네 번째 목록
2. 다섯 번째 목록</code></pre><p>💻 결과</p>
<ol>
<li>첫 번째 목록</li>
<li>두 번째 목록</li>
<li>세 번째 목록</li>
<li>네 번째 목록</li>
<li>다섯 번째 목록</li>
</ol>
<h3 id="2-순서가-없는-목록">2. 순서가 없는 목록</h3>
<p>기호 <code>-</code>, <code>+</code> 그리고 <code>*</code>로 나타낸다.
<code>&#39; &#39;</code>공백 또는 <code>Tab</code>키를 통해 들여쓰기하여 목록에 요소를 추가할 수 있다.
(Velog에서는 첫 요소를 넣을 경우 <code>Tab</code>이 아닌 <code>&#39; &#39;</code>공백을 사용해야 한다.) </p>
<p>✍ 작성 시</p>
<pre><code>- 순서 없는 목록
    - 띄어쓰기(공백) 4번으로 들여쓰기 후 목록 내 요소 생성
        - 요소 내에서 &#39;Tab&#39;을 이용한 들여쓰기 후 생성
- 순서 없는 목록
    &gt; 첫 인용구를 요소로 넣을 경우 공백을 통한 들여쓰기가 필요
* 순서 없는 목록
    * &#39;목록 내에서 한 줄 코드&#39;표기가 가능하다.
+ 순서 없는 목록
        &#39; &#39;공백 여덟 번 또는 &#39;Tab&#39;을 두 번 사용하여 목록 내에서 코드블럭을 만들 수 있다.
        하지만 Velog에서는 코드블럭과 목록 사이에 &#39;1.한 칸의 빈 줄&#39;을 넣어 구분해줘야 하고, 
        &#39;2.공백을 사용한 들여쓰기&#39; 조건에만 반응한다.</code></pre><p>💻 결과</p>
<ul>
<li><p>순서 없는 목록 1</p>
<ul>
<li>띄어쓰기(공백) 4번으로 들여쓰기 후 목록 내 요소 생성<ul>
<li>요소 내에서 &#39;Tab&#39;을 이용한 들여쓰기 후 생성</li>
</ul>
</li>
</ul>
</li>
<li><p>순서 없는 목록 2</p>
<blockquote>
<p>Velog에서 첫 인용구를 요소로 넣을 경우 공백을 통한 들여쓰기가 필요 </p>
</blockquote>
</li>
<li><p>순서 없는 목록 3</p>
<ul>
<li><code>목록 내에서 한 줄 코드</code>표기가 가능하다.</li>
</ul>
</li>
<li><p>순서 없는 목록 4</p>
<pre><code>  &#39; &#39;공백 여덟 번 또는 &#39;Tab&#39;을 두 번 사용하여 목록 내에서 코드블럭을 만들 수 있다.
  하지만 Velog에서는 코드블럭과 목록 사이에 &#39;1.한 칸의 빈 줄&#39;을 넣어 구분해줘야 하고, 
  &#39;2.공백을 사용한 들여쓰기&#39; 조건에만 반응한다.</code></pre></li>
</ul>
<h2 id="7-코드code">7. 코드(Code)</h2>
<p><code>`</code>백틱(Backticks) 키를 이용하여 코드 글을 작성할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>`백틱(Backtick)키는 &#39;ESC&#39;키 바로 밑에 그리고 숫자 &#39;1&#39;키 왼편에 붙어있다.`</code></pre><p>💻 결과</p>
<p><code>백틱(Backtick)키는 &#39;ESC&#39;키 바로 밑에 그리고 숫자 &#39;1&#39;키 왼편에 붙어있다.</code>
<code>앞 뒤로 &#39;`&#39; 키를 두 번씩 사용하므로써 코드 안에 백틱 키를 표시할 수 있다.</code></p>
<h2 id="8-코드블럭code-blocks">8. 코드블럭(Code Blocks)</h2>
<p>본래 마크다운(Markdown)에서는 공백 4개 또는 &#39;Tab&#39; 1개를 통해 들여쓰기하여 코드블럭을 생성할 수 있지만 다른 방법으로도 사용 가능하다.
<code>`</code> 또는 <code>~</code>를 세 번 사용하여 문단의 시작과 끝에 표기하여 코드블럭을 사용할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>```
이러한 형식을 사용하여 코드블럭을 생성한다.
```</code></pre><p>💻 결과</p>
<pre><code>이러한 형식을 사용하여 코드블럭을 생성한다.</code></pre><h3 id="구문-강조syntax-highlighting">구문 강조(Syntax Highlighting)</h3>
<p>Velog에 매료된 이유가 여기 코드블럭에 있다.
코드블럭의 시작에 사용 컴퓨터 언어를 입력하면 해당 언어 형식으로 변환해 준다.</p>
<p>✍ 작성 시</p>
<pre><code>```python
import collections

l = [1,3,2,1,3,3,1]
count = 0
deq = collections.deque()

for i in l:
    deq.append(i)

while deq:
    num = deq.popleft()

    if num &gt;= 2:
        count += 1

print(count)
```</code></pre><p>💻 결과</p>
<pre><code class="language-python">import collections

l = [1,3,2,1,3,3,1]
count = 0
deq = collections.deque()

for i in l:
    deq.append(i)

while deq:
    num = deq.popleft()

    if num &gt;= 2:
        count += 1

print(count)</code></pre>
<h2 id="9-수평선horizontal-rules">9. 수평선(Horizontal Rules)</h2>
<p><code>***</code> 또는 <code>---</code>, <code>___</code>를 사용하여 수평선을 생성할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>페이지의 끝

***
글 쓰기를 종료하거나 페이지를 나누고 싶을 때

---
수평선 사용할 때는 한 줄 띄워주고 사용하자.

____________________________
</code></pre><p>💻 결과</p>
<p>페이지의 끝</p>
<hr>
<p>글 쓰기를 종료하거나 페이지를 나누고 싶을 때</p>
<hr>
<p>수평선 사용할 때는 한 줄 띄워주고 사용하자.</p>
<hr>
<h2 id="10-링크links">10. 링크(Links)</h2>
<p>괄호를 통해 링크를 생성할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>링크
[Velog](http://velog.io)

링크에 제목 추가하기
[Velog](http://velog.io &quot;쉽고 간편한 글쓰기 Velog&quot;)

URL
&lt;http://velog.io&gt;

참조링크
[참조 한 링크 사용함][참조링크]
[참조링크]: http://velog.io</code></pre><p>💻 결과</p>
<p>링크
<a href="http://velog.io">Velog</a></p>
<p>링크에 제목 추가하기(링크 위에 커서를 두면 내용이 보인다)
<a href="http://velog.io" title="쉽고 편한 글쓰기 Velog">Velog</a></p>
<p>URL
<a href="http://velog.io">http://velog.io</a></p>
<p>참조링크
[참조 한 링크 사용함][참조링크]
[참조링크]: <a href="http://velog.io">http://velog.io</a> &quot;쉽고 편한 글쓰기 Velog&quot;</p>
<h2 id="11-이미지-링크images">11. 이미지 링크(Images)</h2>
<p>앞에 <code>!</code>를 붙여주면 이미지를 불러 붙이거나 링크할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>이미지 넣기
![A Sunday Afternoon on the island of La Grande Jatte.-Seurat](이미지 주소)

이미지 링크
[![A Sunday Afternoon on the island of La Grande Jatte.-Seurat]](이미지 URL)</code></pre><p>💻 결과</p>
<p>이미지 넣기
<img src="https://images.velog.io/images/kim-mg/post/281505c0-c511-4da6-a4d0-d10d51fd842d/image.png" alt="A Sunday Afternoon on the island of La Grande Jatte.-Seurat"></p>
<p>이미지 링크
<a href="https://artsandculture.google.com/asset/a-sunday-on-la-grande-jatte/twGyqq52R-lYpA?hl=ko&amp;ms=%7B%22x%22%3A0.5%2C%22y%22%3A0.5%2C%22z%22%3A9.185405174372573%2C%22size%22%3A%7B%22width%22%3A1.2176046441470967%2C%22height%22%3A1.2374999999999996%7D%7D" title="그랑드 자트 섬의 일요일 오후 -쇠라"><img src="https://images.velog.io/images/kim-mg/post/281505c0-c511-4da6-a4d0-d10d51fd842d/image.png" alt="A Sunday Afternoon on the island of La Grande Jatte.-Seurat"></a></p>
<h2 id="12-탈출문자escaping-characters">12. 탈출문자(Escaping Characters)</h2>
<p>텍스트 서식에 사용되는 문자나 기호들을 표현하고자 할 때는 <code>\</code>백슬래시(Backslash) 키를 이용한다.</p>
<p>✍ 작성 시</p>
<pre><code>\* 백슬래시가 없으면 정렬되지 않은 목록의 글머리 기호가 된다.</code></pre><p>💻 결과</p>
<p>* 백슬래시가 없으면 정렬되지 않은 목록의 글머리 기호가 된다.</p>
<h2 id="13-html">13. HTML</h2>
<p>마크다운(Markdown)에선 HTML 태그 또한 이용할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>&lt;strong&gt;굵게&lt;/strong&gt;
&lt;h3&gt;제목&lt;/h3&gt;
&lt;a href=&quot;http://velog.io&quot;&gt;Velog&lt;/a&gt;&lt;br&gt;
&lt;font color=&quot;red&quot;&gt;red&lt;/font&gt;
&lt;br&gt;
&lt;span style=&quot;color:red&quot;&gt;something *red*&lt;/span&gt;</code></pre><p>💻 결과</p>
<p><strong>굵게</strong></p>
<h3>제목</h3>
<a href="http://velog.io">Velog</a><br>
<font color="red">red</font>
<br>
<span style="color:red">something *red*</span>

<h2 id="14-표tables">14. 표(Tables)</h2>
<p><code>|</code>파이프(Pipe)와 <code>-</code>를 사용하여 표를 만들 수 있다.
표 내에서 간단한 강조 등의 글자 서식을 정할 수 있다.</p>
<p>✍ 작성 시</p>
<pre><code>|구문|설명|비고|
|:---|:---:|---:| # 좌측, 가운데, 우측 정렬
|**Header**|_Title_|1|
|`Paragraph`|Text|2|</code></pre><p>💻 결과</p>
<table>
<thead>
<tr>
<th align="left">구문</th>
<th align="center">설명</th>
<th align="right">비고</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Header</strong></td>
<td align="center"><em>Title</em></td>
<td align="right">1</td>
</tr>
<tr>
<td align="left"><code>Paragraph</code></td>
<td align="center">Text</td>
<td align="right">2</td>
</tr>
</tbody></table>
<h2 id="15-작업-목록task-lists">15. 작업 목록(Task Lists)</h2>
<p><code>-</code> 뒤에 <code>[ ]</code> 빈 공간을 가진 대괄호를 사용하여 나타낸다.
박스에 체크하고 싶다면 <code>[x]</code> 빈 공간 대신 <code>x</code>키를 입력하면 된다.</p>
<p>✍ 작성 시</p>
<pre><code>- [x] 회의록 작성하기
- [x] 상품샘플 받아오기
- [ ] 보고서 작성하기</code></pre><p>💻 결과</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 회의록 작성하기</li>
<li><input checked="" disabled="" type="checkbox"> 상품샘플 받아오기</li>
<li><input disabled="" type="checkbox"> 보고서 작성하기</li>
</ul>
<h2 id="16-이모티콘emoji">16. 이모티콘(Emoji)</h2>
<p>이모티콘은 그림 이모티콘을 복사하여 붙여넣거나 단축 코드를 사용하여 나타낸다.
Velog 글쓰기에선 단축 코드를 지원하지 않는 것 같다. 하지만 단축키를 통해 이모티콘을 사용할 수 있다.</p>
<p>💡 이모티콘 사이트
<a href="https://emojipedia.org/">https://emojipedia.org/</a>
<a href="https://getemoji.com/">https://getemoji.com/</a></p>
<p>💡 단축키
Windows 10 : <code>Window</code> + <code>&#39;.&#39;(마침표)</code>
Mac : <code>Command</code> + <code>Control</code> + <code>Space Bar</code></p>
<hr>
<p>이렇게 Velog 글을 쓰기 위한 마크다운 작성법에 대해 알아봤다. 마크다운은 각 웹이나 어플리케이션마다 지원하는 기능에 간소한 차이가 있는데, Velog 또한 적용하기 어렵거나 지원하지 않는 기능들이 더러 있었다. 그리고 생각보다 기능이 많아 글쓰기 페이지의 첫인상과 괴리가 있었지만, 할 수 있는게 늘어나면서 상당한 재미를 느낄 수 있었다.</p>
]]></description>
        </item>
    </channel>
</rss>