<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hailey.log</title>
        <link>https://velog.io/</link>
        <description>중간노력자</description>
        <lastBuildDate>Wed, 23 Mar 2022 09:14:21 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hailey.log</title>
            <url>https://images.velog.io/images/hailey_dev/profile/cf646975-6e6c-4db3-92fc-032c0bb4a42e/IMG_9744.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hailey.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hailey_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[재귀 함수]]></title>
            <link>https://velog.io/@hailey_dev/%EC%9E%AC%EA%B7%80-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@hailey_dev/%EC%9E%AC%EA%B7%80-%ED%95%A8%EC%88%98</guid>
            <pubDate>Wed, 23 Mar 2022 09:14:21 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/2d8e4900-dee7-4a22-b744-379a1d0318bf/algorithm.001.jpeg" alt=""></p>
<h1 id="재귀함수란">재귀함수란?</h1>
<p>재귀함수는 내가 나를 참조하는 함수.
가장 대표적인 것은 <em><del>(오늘 내가 못 풀었던^^..)</del></em> <strong>팩토리얼</strong></p>
<h2 id="팩토리얼">팩토리얼</h2>
<p>팩토리얼은 중학교때? 배우는 수학적 개념으로 5!이면 5부터 1까지를 순서대로 곱하는 연산이다.
예를 들어, 5!는 1<em>2</em>3<em>4</em>5, 즉 120이다.</p>
<p>팩토리얼은 주로 경우의 수를 구하는데 사용된다.
n개의 색깔을 나열하는 경우의 수를 구하려면 n!을 하면 된다.</p>
<p>이걸 for문을 써서 먼저 코드로 구현하게 되면</p>
<pre><code class="language-java">public static int fact(int n) {
    int result = 1;

    for(int i = 1; i&lt;=n ; i++) {
        result *= i;
    }

    return result;
};
</code></pre>
<pre><code class="language-java"> public static int fact(int n) {
        if(n&lt;=1)
            return 1;
        else
            return fact(n-1)*n;
    }</code></pre>
<p>이런 식으로 구현될 수 있다.
이런 식으로 함수 안에서 나 자신을 다시 참조하는 것을 재귀함수라고 한다.</p>
<p>이렇게 간단한 건데 왜 못했을까?ㅠㅠ
흑흑..</p>
<p>예를 들어, <code>fact(5);</code>를 실행한다고 치면</p>
<h3 id="n5">n=5</h3>
<p>else문을 타고 fact(4) x 5이 return 된다.
그러면 그 안에서 fact(4)가 다시 실행되므로</p>
<h3 id="n4">n=4</h3>
<p>가 되고 else문을 타고 다시
fact(3)x4x5</p>
<p>...</p>
<p>이런 식으로 </p>
<h3 id="n2">n=2</h3>
<p>까지 진행되고, </p>
<h3 id="n1">n=1</h3>
<p>이 되면 n만 return이 되기 때문에,
결과적으로는
1x2x3x4x5 연산이 실행 되는 것이다.</p>
<h2 id="재귀의-기본-개념은">재귀의 기본 개념은</h2>
<blockquote>
<p>문제의 범위보다 약간 좁은 하위 문제를 해결하고, 이 답을 이용하여 원래 문제를 해결하는 것</p>
</blockquote>
<h2 id="직접-재귀와-간접-재귀">직접 재귀와 간접 재귀</h2>
<ul>
<li>직접 재귀: 자기 자신과 같은 메서드를 호출하는 것<pre><code class="language-java">a() {
  a();
}</code></pre>
</li>
<li>간접 재귀: 다른 메서드를 통해 자기 자신과 같은 메서드를 호출하는 것<pre><code class="language-java">b() {
  a();
}
</code></pre>
</li>
</ul>
<p>a() {
    b();
}</p>
<pre><code>
## 스택 프레임으로 재귀함수 이해하기

자바 메모리 구조에서 메서드는 Stack에 올라가게 된다.

재귀 함수의 예제 중에 N을 넣으면 1부터 N까지 숫자를 모두 출력하는 함수를 작성한다고 치면,

```java

public void DFS(int n) {
    if(n==0) return;
    else {
        DFS(n-1);
        System.out.print(n + &quot; &quot;);
    }
}</code></pre><p>으로 작성할 수 있다.</p>
<p>여기서 <code>System.out.print()</code>가 함수 위에 있는지,
아래 있는지에 따라 숫자의 출력 순서가 반대가 되는데 이를 이해하려면 Stack Frame의 구조를 이해해야 한다.</p>
<p>Stack은 모두 알다시피, <code>First In Last Out</code> 구조로 되어있다.</p>
<p>Main 메서드에서 <code>DFS (3)</code>을 호출했을 때,
Stack에는 else 문을 타고 </p>
<table>
<thead>
<tr>
<th align="center">Stack Frame</th>
</tr>
</thead>
<tbody><tr>
<td align="center">DFS(1)</td>
</tr>
<tr>
<td align="center">DFS(2)</td>
</tr>
<tr>
<td align="center">DFS(3)</td>
</tr>
</tbody></table>
<p>이런 식으로 쌓이게 된다.</p>
<p>들어갈 때는 <code>DFS(3)</code>부터 순서대로 쌓이고 <code>System.out.print()</code>는 보류가 된 상태이며, 모두 쌓이게 된 후에 <code>DFS(1)</code> 부터 차례대로 출력 함수가 실행되며 <code>Pop</code>　되는 것이다.</p>
<p>그러면 실제 출력은</p>
<p><code>1 2 3</code></p>
<p>이런 식으로 출력되게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Static과 Final]]></title>
            <link>https://velog.io/@hailey_dev/Static%EA%B3%BC-Final</link>
            <guid>https://velog.io/@hailey_dev/Static%EA%B3%BC-Final</guid>
            <pubDate>Sat, 19 Mar 2022 13:45:26 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/cd2ed700-40c5-4351-86db-f6fe66ac7e14/java.001.jpeg" alt=""></p>
<h2 id="static">Static</h2>
<pre><code class="language-java">public class MyClass {
    public static void foo1() {}
    public void foo2() {}
}</code></pre>
<p>위 2개의 메서드를 사용하고 싶을 때의 차이를 이해하면 된다.
다른 점은 <strong>static</strong>이 붙고 안붙고의 차이다.</p>
<p>첫번째 <code>foo1</code>은 <code>MyClass.foo1();</code>으로 사용할 수 있고,
두번째 <code>foo2</code>는 <code>MyClass myClass = new MyClass();</code>로 인스턴스를 생성해준 후, <code>myClass.foo2();</code>로 사용할 수 있다.</p>
<p><strong>static</strong>은 보통 모든 인스턴스에서 공통으로 사용하는 것에 붙는다.
static 변수, static 메소드는 인스턴스를 생성(new)하지 않아도 이미 클래스가 메모리에 올라갈 때 생성되기 때문에, 모든 인스턴스에서 공통적으로 사용할 수 있기 때문이다.</p>
<p>여기서 주의해야 할 점은 static 메서드의 경우 인스턴스 변수를 사용할 수 없다는 것이다.</p>
<p>예를 들어,</p>
<pre><code class="language-java">int a, b;

static int add () {
    return a+b;
}</code></pre>
<p>이런 식으로 사용이 불가하다는 것이다.</p>
<p>왜냐하면 <code>int a,b</code>는 인스턴스 변수이므로 인스턴스가 반드시 존재해야지만 사용할 수 있는데, static메서드는 인스턴스 생성 없이 호출이 되므로 메서드만 호출되고, 인스턴스는 생성이 되지 않아 <code>int a,b</code>는 없는 변수가 될 수 있기 때문이다.</p>
<p>이 때, JVM의 메모리 구조를 살펴보면서 좀 더 직관적으로 이해해보자.</p>
<h3 id="java-메모리-구조">Java 메모리 구조</h3>
<p><img src="https://images.velog.io/images/hailey_dev/post/3edb016a-711c-4f4b-bb51-960bb2e63ee5/java_jvm_runtime_data_area.png" alt=""></p>
<p>Java는 JVM(Java Virtual Machine)이라는 가상 시스템에서 실행된다. 우리가 <code>.java</code> 파일로 코딩을 하면 이 파일을 자바 컴파일러(javac)가 JVM이 이해할 수 있는 bytecode로 바꾸어서 <code>.class</code> 파일을 생성해준다.</p>
<p>그러니까 javac는 일종의 번역가인 셈이다.</p>
<p>이 <code>.class</code> 파일은 JVM만 설치되어 있으면 OS(Windows, Mac, Linux)에 관계없이 실행될 수 있다.</p>
<p>이렇게 번역된 <code>.class</code> 파일은 JVM 안에서 위의 그림처럼 나뉘어져서 관리된다.</p>
<p>한 눈에 봐도 알 수 있듯이, <strong>Method Area</strong>에 우리가 아까 본 Static 메서드와 변수가 저장된다. 아까 </p>
<blockquote>
<p>static 변수, static 메소드는 인스턴스를 생성(new)하지 않아도 이미 클래스가 메모리에 올라갈 때 생성되기 때문에</p>
</blockquote>
<p>라고 언급했는데, 이게 바로 그 말이다.</p>
<p>그렇기 때문에 생명주기(Lifecycle)도 클래스와 똑같다.</p>
<p>반대로 일반 메서드의 경우, 객체를 생성해야 하는데, <code>new</code>를 해주어 객체를 생성하면 <strong>Heap</strong> 영역에 객체가 만들어진다. 그 후에 객체를 통해서 접근하여 메서드를 호출할 수 있다.</p>
<h2 id="final">Final</h2>
<p>흔히, <strong>상수</strong>라고 하는 것들이다.
final이 붙으면 오버라이딩을 할 수 없게 되고, 자손클래스를 정의하지 못하게 된다.
일반적으로 선언과 초기화를 동시에 하고, 인스턴스 변수일 경우에는 <strong>생성자</strong>에서 초기화를 할 수 있다.</p>
<p>선언과 초기화를 동시에 하지 않고 생성자에서 하게 되면, 각 인스턴스마다 final 변수들이 각각 다른 값을 갖도록 할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[List<String> a = new ArrayList<>();]]></title>
            <link>https://velog.io/@hailey_dev/ListString-a-new-ArrayList</link>
            <guid>https://velog.io/@hailey_dev/ListString-a-new-ArrayList</guid>
            <pubDate>Sat, 19 Mar 2022 08:52:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/b905f416-1c16-44be-8e83-a20e707291b2/java.001.jpeg" alt=""></p>
<h3 id="정말-사소하지만-사소하지-않게-궁금했던-미스테리">정말 사소하지만 사소하지 않게 궁금했던 미스테리</h3>
<p>국비에서 어찌저찌 자료구조를 배우고, 실습 과제를 할 때 일이다.
국비학원에서는 디테일하게 코드를 봐주거나 하는 일이 별로 없었기 때문에, 조원들끼리 머리를 싸매고 유사 석기시대 마냥 코드를 짜고 있었더랬다.</p>
<p>그 때의 우리는, 막 ArrayList, HashMap 등을 배웠고, 그걸 활용해서 간단한 프로그램을 짜고 있었는데, 나는 너무 당연하게 아래와 같이 코드를 썼다.</p>
<pre><code class="language-java">ArrayList&lt;String&gt; list = new ArrayList&lt;&gt;();</code></pre>
<p>그러다가, 현업에서 일하는 친구를 둔 한 조원이 짠 코드를 보니 다음과 같이 선언되어 있었다.</p>
<pre><code class="language-java">List&lt;String&gt; list = new ArrayList&lt;&gt;();</code></pre>
<h3 id="어">어?</h3>
<p>그 때는 아무리 생각해도 양쪽을 다르게 쓰는(?) 이유를 모르겠어서 친구에게 물어보니, 현업에서는 대부분 저렇게 쓴다고, _이유는 잘 모르겠지만 여튼 저렇게 쓴대!_라는 답을 들었다.</p>
<p>물론 당시에는 코드를 짜서 실행 시키는 데 급급했기 때문에 넘어갔지만, 나와 같은 의문을 품는 사람들이 있을까봐 이렇게 기록을 남겨둔다.</p>
<p>저렇게 코드를 짜는 이유는</p>
<h2 id="유연성">유연성</h2>
<p>때문이다.</p>
<p>결국 </p>
<pre><code class="language-java">List&lt;String&gt; list = new ArrayList&lt;&gt;();
// List 인터페이스를 참조하여 ArrayList로 구현</code></pre>
<p>요 코드를 나중에 성능 개선이나 기능 추가 같은 일이 발생하여 구현을 다른 것으로 바꿀 일이 있을 때 (Vector나 LinkedList 등..) 유연하게 바꿀 수 있도록 하는 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터페이스는 왜 쓰나요?]]></title>
            <link>https://velog.io/@hailey_dev/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%8A%94-%EC%99%9C-%EC%93%B0%EB%82%98%EC%9A%94</link>
            <guid>https://velog.io/@hailey_dev/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%8A%94-%EC%99%9C-%EC%93%B0%EB%82%98%EC%9A%94</guid>
            <pubDate>Sat, 19 Mar 2022 08:39:29 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/8a28de0b-475c-4b48-9d83-50cf98e9b512/interface.001.jpeg" alt=""></p>
<h1 id="애초에-인터페이스란-무엇인가">애초에 인터페이스란 무엇인가</h1>
<p>인터페이스는 한마디로 말하자면 일종의 추상 클래스다. 추상 클래스처럼 추상메서드를 갖지만, 추상 클래스보다 추상화 정도가 높아서 추상 클래스와 달리 <strong>추상 메서드</strong>와 <strong>상수</strong>만을 멤버로 가질 수 있다.</p>
<p>추상 클래스를 부분적으로만 완성된 <strong>미완성 설계도</strong>라고 한다면 인터페이스는 밑그림만 그려져 있는 <strong>기본 설계도</strong>라고 할 수 있다.</p>
<pre><code class="language-java">inerface MyInterface {
    public static final int number = 0;
    public abstract method();
}</code></pre>
<p>이런 식으로 인터페이스의 모든 멤버변수는 <strong>public static final</strong>이고, 모든 메서드는 <strong>public abstract</strong>이다. </p>
<p>이렇게 전체적인 틀을 짜준 후, 실제 구현 클래스에서 메서드 내용 부분을 채워넣어 구현(implements)을 해주는 것이다.</p>
<h1 id="그렇다면-바로-구현하면-되지-왜-귀찮게-서비스-인터페이스-만들고-구현-클래스를-따로-만드는-걸까">그렇다면 바로 구현하면 되지 왜 귀찮게 서비스 인터페이스 만들고 구현 클래스를 따로 만드는 걸까?</h1>
<h2 id="✅-개발-기간을-단축-시킬-수-있다">✅ 개발 기간을 단축 시킬 수 있다</h2>
<p>일단 인터페이스와 구현 클래스를 나누어서 작업하면, 인터페이스만 먼저 작성해놓으면 이 <strong>틀</strong>을 사용해서 프로그램을 작성할 수 있다. 또한, 한 쪽에서 구현 클래스를 작성하면서 동시에 다른 개발을 진행할 수 있다.</p>
<h2 id="✅-표준화가-가능하다">✅ 표준화가 가능하다</h2>
<p>아까부터 <strong>틀</strong>이라는 단어를 계속 사용하고 있는데, 이렇게 인터페이스로 <strong>틀</strong>을 잡아 놓고 개발을 하게 되면 여러 명의 개발자가 작업을 할 때도 일관된 <strong>틀</strong>안 에서 그 안의 내용을 구현하면서 개발이 진행되므로 정형화된 작업이 가능하다.</p>
<h2 id="✅-서로-관계없는-클래스들에게-관계를-맺어-줄-수-있다">✅ 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다</h2>
<p>서로 상속(extends)관계도 아니고 조상 클래스도 갖고 있지 않은 아무런 관계도 없는 클래스들이 하나의 인터페이스를 공통적으로 구현하게 하면 관계를 맺어줄 수 있다.</p>
<h2 id="✅-독립적인-프로그래밍이-가능하다">✅ 독립적인 프로그래밍이 가능하다</h2>
<p>클래스의 선언(interface &gt; Service)과 구현(class &gt; ServiceImpl)을 분리시킴으로써 독립적인 프로그래밍이 가능하다. 만약 모든 클래스들을 직접 관계로 한다면, 한 클래스를 변경할 때마다 직접 관계로 맺어진 클래스를 모두 수정해야 할 것이다. 하지만 선언과 구현을 나누면서 간접적인 관계로 변경하면, 하나의 클래스를 변경하더라도 다른 클래스에 영향을 미치지 않게 된다.</p>
<h1 id="jdk18부터-달라진-점">JDK1.8부터 달라진 점</h1>
<h2 id="default-메서드-추가-가능">Default 메서드 추가 가능</h2>
<p>기존에 <strong>public abstract</strong> 추상 메서드만 가질 수 있었던 것에서 확장되어, <strong>디폴트 메서드(default)</strong>를 추가할 수 있게 되었다.</p>
<h3 id="디폴트-메서드는-왜-추가가-되었지">디폴트 메서드는 왜 추가가 되었지?</h3>
<p>항상 이 점이 의문이였는데, 자바의 정석을 다시 읽어보니 너무나 떡하니 이유가 나와있었다. 아까 인터페이스는 <strong>틀</strong>을 잡아주는 것이라고 했는데, 이상적으로는 이 <strong>틀</strong>이 처음부터 설계가 완벽하게 되어서 인터페이스를 수정하지 않고 구현 클래스만 수정하면서 프로그램을 작성하는 것이 좋겠지만, 현실적으로 언젠가 그 <strong>틀</strong>을 변경해야 할 일이 있는 경우가 많을 것이다.</p>
<p>이 경우에, 인터페이스에 추상 메서드를 추가하게 되면 아주 큰 일이 나게 된다. 이 인터페이스를 구현한 모든 클래스에서 추가된 메서드의 내용을 구현해줘야 하기 때문이다. </p>
<p>이럴 경우를 대비해서 추가된 것이 바로 <strong>디폴트 메서드</strong>이다.
(접근 제어자는 다른 것들과 마찬가지로 public)</p>
<p>디폴트 메서드는 추상 메서드가 아니기 때문에 추가되어도 인터페이스를 구현한 클래스를 변경하지 않아도 된다. 다만, 디폴트 메서드의 이름과 기존 메서드의 이름이 중복되는 경우에는 다음과 같은 규칙으로 해결할 수 있다.</p>
<ul>
<li>여러 인터페이스의 디폴트 메서드간 충돌: 구현 클래스에서 디폴트 메서드 override</li>
<li>디폴트 메서드와 조상 클래스 메서드 간의 충돌: 조상 클래스 메서드가 상속, <strong>디폴트 메서드는 무시</strong></li>
</ul>
<h2 id="static-메서드-추가-가능">Static 메서드 추가 가능</h2>
<p>사실 static 메서드는 인스턴스와 관련이 없는 독립적인 메서드이기 때문에 인터페이스에 추가하지 못할 이유가 없었다. (즉, static 메서드는 특정 객체에 속하는 것이 아니기 때문에)</p>
<p>인터페이스는 추상 메서드만 가져야 한다는 규칙 때문에 대표적으로 <strong>Collection</strong> 인터페이스의 관련된 static 메서드들이 Collections라는 클래스에 들어가게 되었다.</p>
<p>어쨋든, 1.8 이후부터는 <strong>public static</strong> 메서드를 선언할 수 있게 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CORS(Cross-Origin Resource Sharing)에 대한 고찰]]></title>
            <link>https://velog.io/@hailey_dev/CORSCross-Origin-Origin-Resource-Sharing%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0</link>
            <guid>https://velog.io/@hailey_dev/CORSCross-Origin-Origin-Resource-Sharing%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0</guid>
            <pubDate>Wed, 23 Feb 2022 15:52:13 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/61c3387f-ed42-45fc-98e4-223b0b122377/cors.001.jpeg" alt=""></p>
<h1 id="cors는-뭐길래-자꾸만-나를-괴롭히는가">CORS는 뭐길래 자꾸만 나를 괴롭히는가</h1>
<p>CORS는 한창 최종 프로젝트를 해 나갈 때, 마주치게 된 녀석이다.
화면을 캡쳐해 이미지로 다운로드 되는 기능을 넣기 위해 HTML을 CANVAS로 그려주는 라이브러리를 갖다 썼었는데, 다른 건 다 잘 캡쳐가 되면서
AWS S3 버킷을 사용한 이미지들만 CORS 정책을 위배했다면서 캡쳐가 되지 않고 공란으로 나오는 현상이 발생했다.</p>
<p>그게 CORS와 나의 첫 만남이었다.</p>
<p>결국, 그때 당시에는 구글을 탈탈 털어, S3 버킷에 CORS 정책에 프로젝트 URL을 추가해주고, S3 서버에서 이미지를 불러올 때 JS에서 자동으로 타임스탬프를 초단위로 찍어주게 하여 해결을 하였다.</p>
<h2 id="해결됐으니-다행이긴-한데-대관절-이-cors란-어떤-녀석인가">해결됐으니 다행이긴 한데, 대관절 이 CORS란 어떤 녀석인가</h2>
<p><strong>CORS</strong>를 알려면 먼저 <strong>SOP</strong>을 봐야한다.</p>
<p>_<strong>브라우저</strong>_는 실행 중인 웹 애플리케이션에서 가져오는 자원들의 출처를 항상 감시하고 있는데, 이 때 <strong>SOP</strong>, 즉, 자원들의 출처가 같은 웹 서버(도메인)일 경우에는 문제가 발생하지 않는다.</p>
<p>문제는 우리가 개발을 할 때 항상 하나의 서버에 모든 자원들을 담아두진 않는다는 것이다.</p>
<p>CORS와 나의 첫만남이었던 그 프로젝트에서도 처음으로 시도했던 해결방법은 이미지들을 임시적으로 로컬로 옮기는 것이었다. <del>(정말 단순무식했다)</del></p>
<p>로컬 서버에 있는 이미지들을 아무 정책도 위반하지 않고 잘만 출력이 됐었다. 하지만 AWS S3 버킷을 사용하여 이미지를 동적으로 불러오면, CORS 정책에 위배되어 이미지가 있어야할 칸은 휑한 공란으로 표시됐다.</p>
<p>다시 정확히 정리하자면</p>
<h4 id="출처가-다를-경우-브라우저는-보안상의-이유로-http-요청을-제한한다">출처가 다를 경우 브라우저는 보안상의 이유로 HTTP 요청을 제한한다</h4>
<p>는 것이다.</p>
<p>여기서 주목해야 할 것은 출처를 비교하는 로직은 서버가 아니라 <strong>브라우저</strong>에 구현되어 있다는 것인다.</p>
<p>서버는 CORS 정책을 위반했다고 할지라도 정상적으로 응답을 보내고, 브라우저 측에서 받은 응답을 가지고 출처를 판단한 후, CORS 정책을 위반했다고 판단하면 그 응답을 쓰지 않고 버려버린다.</p>
<h2 id="근데-귀찮게-왜-제한하는거지">근데 귀찮게 왜 제한하는거지?</h2>
<p>아까도 말했듯이 <strong>보안상의 이유</strong>이다.</p>
<p>브라우저는 보안에 취약하다.
개발자 도구를 사용하면 가져온 스크립트 내용을 다 볼 수 있듯이, 
악의를 가진 어떤 사람이 마음만 먹는다면 개인 정보와 같은 민감한 정보를
얼마든지 가져가고, 또 본인이 원하는 스크립트를 낑겨 넣을 수도 있다.</p>
<p>그렇기 때문에 브라우저는 <strong>인증되지 않은 출처의 리소스를</strong> 함부로 가져오지 않으려고 하는 것이다.</p>
<h2 id="해결하려면">해결하려면?</h2>
<p>내가 AWS S3 버킷에 URL을 추가해줬듯이, 서버 측에서 <strong>인증된 출처</strong>라고 안심할만한 정보를 넘겨주어야 한다.</p>
<p>Request의 헤더에 <strong>Origin</strong>이라는 것을 추가해서 보내줘야 한다.
Origin에는 요청하는 쪽의 Scheme, Domain, Port를 담아 보낸다.</p>
<blockquote>
<p>scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]</p>
<ul>
<li>Sheme: 자원에 접근할 방법을 정의해 둔 프로토콜의 이름(HTTP, FTP, TELNET 등)</li>
<li>Domain: IP 주소를 보다 알기 쉽게 하기 위해 정해준 네트워크 호스트 이름</li>
<li>Port: 네트워크 서비스나 특정 프로세스를 식별하는 논리 단위 (월드 와이드 웹, HTTP의 기본 포트는 80)</li>
</ul>
</blockquote>
<p>Response의 헤더에는 지정된 <strong>Access-Control-Allow-Origin</strong> 정보를 실어서 보내야 한다. </p>
<p>대부분은 이렇게 하면 해결이 되는데, S3 버킷의 이미지들을 Canvas로 재구성할 때 다시 Cross-Origin 정책을 위반한다고 나온다.</p>
<p>이에 대해서는 여러가지 해결책이 있지만, 내가 사용했던 방법은
이미지를 재사용하지 않고 새로 내려받게 하기 위해서 S3 버킷에 이미지 다운로드 요청을 보낼 때 GET 요청의 Parameter로 Timestamp와 같은 값을 추가하여 <strong>요청이 발생할 때마다 다른 URL을 사용</strong>하도록 해서 문제를 해결하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[배열(Array)]]></title>
            <link>https://velog.io/@hailey_dev/%EB%B0%B0%EC%97%B4Array</link>
            <guid>https://velog.io/@hailey_dev/%EB%B0%B0%EC%97%B4Array</guid>
            <pubDate>Fri, 11 Feb 2022 09:57:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/82ab5794-d172-4f4a-82e1-bd4adf39d98e/algorithm.002.jpeg.001.jpeg" alt=""></p>
<h1 id="array-배열">Array [배열]</h1>
<h2 id="reading">Reading</h2>
<p>원래 배열은 방 갯수를 미리 예약해야 한다! 마치 라잌 Java처럼
JavaScript, Python은 얘네들이 대신 해줌 (그래서 편함)
배열은 방 갯수를 예약하고, 0부터 방의 인덱스를 붙이기 때문에
인덱스 넘버를 안다면 호로록 가져올 수 있다</p>
<p><strong>많은 자료를 읽어와야 한다면 배열이 짱 (인덱스번호만 알면 되기 때문에!)</strong></p>
<hr>
<h2 id="search">Search</h2>
<p>Reading과 Search의 차이점은 Search는 <strong>내가 인덱스 번호를 모를수도</strong> 있다는 것이다
(가령, 그 안에 값은 아는데 어디에 있는지를 모름)
이러면 하나씩 값이 맞는지를 확인해줘야함 &gt; 시간이 겁나 걸림!</p>
<p>만약에 내가 찾는 값이 배열의 초반에 있으면 빨리 찾겠지만
만약에 맨 끝에 있거나 값이 아예 없을 때는 한~~참 걸림
이런 방식을 <strong>선형 검색(Linear Search)</strong> 이라고 한다</p>
<hr>
<h2 id="insert">Insert</h2>
<p>아까 말했다시피, 배열은 일단 방 갯수를 예약해야 하는데
여기서 값이 다 들어가있지 않은 경우
나중에 값을 추가(Insert) 해줄 수 있다</p>
<h3 id="값을-맨-뒤에-추가하고-싶을-때">값을 맨 뒤에 추가하고 싶을 때</h3>
<p>가장 쉬운 경우
그냥 맨 뒤에 넣어주면 된다</p>
<h3 id="값을-맨-앞에-추가하고-싶을-때">값을 맨 앞에 추가하고 싶을 때</h3>
<p>배열의 크기가 클수록 난감해짐
맨 앞에 추가하게 되면 그 안에 있던 <strong>기존 값들을 한 칸씩 다 뒤로 미뤄야 함</strong></p>
<h3 id="배열에-빈-공간이-없는데-추가하고-싶을-때">배열에 빈 공간이 없는데 추가하고 싶을 때</h3>
<p>배열은 아까도 말했다시피 방 갯수가 미리 정해져 있는 구조라,
마음대로 방 갯수를 늘리고 줄일 수 없음
이럴 때는 더 큰 배열을 새로 만든 후,
기존 배열에서 값들을 복사해와야 비로소 값을 추가할 수 있다</p>
<hr>
<h2 id="delete">Delete</h2>
<p>추가랑 비슷함</p>
<h3 id="맨-뒤에-있는-값을-삭제하고-싶을-때">맨 뒤에 있는 값을 삭제하고 싶을 때</h3>
<p>가장 쉬움
걍 지우면 된다</p>
<h3 id="보통은-중간에-있는-값을-지우고-싶어하지">보통은 중간에 있는 값을 지우고 싶어하지</h3>
<p>중간 값을 지워버리게 되면 공백이 생김
근데 배열에는 <strong>중간 공백이 있으면 안됨!!!</strong>
빈 공간을 뒤에 있는 값들로 하나씩 땡겨온다</p>
<h3 id="첫-번째-값을-지우고-싶으면">첫 번째 값을 지우고 싶으면?</h3>
<p>첫 번째 값을 지우고 그 뒤에 값들을 한칸씩 다 옮겨야 함</p>
<blockquote>
<p>해당 포스팅은 노마드 코더의 알고리즘, 데이터구조 with Nico의 내용을 정리한 것입니다!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조와 알고리즘]]></title>
            <link>https://velog.io/@hailey_dev/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@hailey_dev/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Fri, 11 Feb 2022 09:53:24 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/hailey_dev/post/b6e66a49-f3b7-4f64-a3b8-0b8271a65b3a/algorithm.001.jpeg" alt=""></p>
<h1 id="그래서-자료구조는-뭐고-알고리즘은-뭔데">그래서 자료구조는 뭐고 알고리즘은 뭔데?</h1>
<h2 id="알고리즘">알고리즘</h2>
<ul>
<li>여러 개의 지시사항, <strong>어떠한 액션을 수행하기 위해 컴퓨터가 해야하는 것들</strong></li>
<li>좋은 알고리즘을 찾으면 계속 써먹을 수 있음</li>
<li>예를 들어, 출근 루틴 (일어나서, 이 닦고, 세수하고, 옷 입고, 밥 먹고, 문을 열고, 나간다)</li>
<li>컴퓨터에서 예제를 찾는다면, 최단 거리 찾기, 이미지 압축 방법, 데이터 암호화</li>
</ul>
<h2 id="자료구조">자료구조</h2>
<ul>
<li>우리가 쓰는 <strong>데이터를 정리하는 것</strong></li>
<li>어떻게 정리하느냐에 따라서 속도에 영향을 주게 되기 때문에!</li>
<li>사이트가 느려지고, 빨라지는 것을 결정함</li>
<li>어떻게 정렬할지, 어떻게 검색할지, 어떻게 추가할지, 어떻게 편집할지</li>
<li><strong>어떻게 데이터를 정리해야 제일 빠르게 결과에 도달할 수 있을까?</strong></li>
</ul>
<h1 id="시간복잡도란">시간복잡도란?</h1>
<p>알고리즘이 실행되는 시간을 계산한 것
&#39;초&#39;단위가 아니라 <strong>몇 &#39;단계&#39;</strong> 로 실행되느냐를 러프하게 판단</p>
<h1 id="메모리">메모리</h1>
<ul>
<li>휘발성 메모리: 컴퓨터를 끄면 사라지는 것 &gt; RAM (Random Access Memory)</li>
<li>비휘발성 메모리: 컴퓨터를 꺼도 사라지지 않는 것 &gt; 하드 드라이브</li>
</ul>
<p>RAM은 이름 그대로 랜덤하게 데이터들에 접속할 수 있기 때문에 하드 드라이브보다 빠르다
(순차적으로 1번방, 2번방... 식으로 방문하는 것이 아님!)</p>
<blockquote>
<p>해당 포스팅은 노마드 코더의 알고리즘, 데이터구조 with Nico의 내용을 정리한 것입니다!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[노션 활용하기 - 커스텀 위젯]]></title>
            <link>https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%9C%84%EC%A0%AF</link>
            <guid>https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%9C%84%EC%A0%AF</guid>
            <pubDate>Sun, 01 Aug 2021 08:04:17 GMT</pubDate>
            <description><![CDATA[<h1 id="저-음악-플레이어-진짜-되는건가">저 음악 플레이어 진짜 되는건가?</h1>
<p><a href="https://vimeo.com/581705803"><img src="https://images.velog.io/images/hailey_dev/post/17cc0f01-99f0-4a42-8ca7-aae54a23f86b/notion03.002.jpeg" alt="notion player"></a></p>
<p>👆 위 썸네일을 클릭하면 대시보드를 동영상으로 볼 수 있다</p>
<p>내가 레딧에서 처음 음악플레이어가 들어있는 대시보드를 보고 한 생각이다.
결과부터 말하자면, 된다.</p>
<p>커스텀 위젯을 만드는 법부터 설명해보고자 한다.</p>
<h2 id="weatherwidgetio">weatherwidget.io</h2>
<p>날씨 위젯 또한 원래 사이트에서는 노션용의 위젯은 지원하지 않는다.
임베드 html 태그만 지원을 하는데, 그건 바로 노션에서 쓸 수 없다.
이렇게 <strong>html 태그로 된 위젯</strong>을 노션에서 사용하고 싶다면,
한번 노션용 위젯을 만들어주는 사이트를 거쳐서 <strong>url</strong>로 바꿔줘야 한다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/117eb3da-1508-4eda-ac45-f405e0273b6f/image.png" alt=""></p>
<p>일단 내가 요 날씨 위젯을 만든 사이트는 <a href="https://weatherwidget.io">여기</a>다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/75bbd881-8dbe-4fe4-bf00-2fc6bda2b316/image.png" alt=""></p>
<p>다른 날씨 위젯이 많은데 여기를 선택했던 이유는, 커스텀이 가능하기 때문이다.</p>
<blockquote>
<ul>
<li>settings : 위치, 왼쪽 문구, 표시할 언어, 섭씨/화씨</li>
<li>options : 폰트, 아이콘 모양, 현재날씨 표시 유무, 며칠까지 표시할건지</li>
<li>themes : 테마 선택</li>
<li>customize : 테마에서 설정된 각종 배경, 폰트 색깔 변경</li>
</ul>
</blockquote>
<p>이렇게 모든 것을 내 마음대로 할 수 있다.</p>
<p>내가 사용한 설정은,</p>
<blockquote>
<ul>
<li>settings : Seoul, 프랑스어 표기, 섭씨</li>
<li>options : courier new, Climacons Animated, both, 5days</li>
<li>themes : flat - pure</li>
<li>customize : text - #459fb4</li>
</ul>
</blockquote>
<p>로 바꿔서 사용했다.</p>
<p>모두 바꾼 후에는 미리보기에서 크기를 조정해 준 후에, <code>get code</code>를 눌러서 코드를 복사하면 된다.</p>
<h2 id="커스텀-위젯---apptionco">커스텀 위젯 - apption.co</h2>
<p><a href="https://apption.co">https://apption.co</a></p>
<p>이렇게 만든 위젯을 어떻게 노션에서 사용 가능한 embed 링크로 만들기 위해서는,
위 사이트에 들어가서 커스텀 위젯을 만들어줘야 한다.</p>
<p>사용법은 간단하다.
<img src="https://images.velog.io/images/hailey_dev/post/fd971ff0-942e-48fc-a69d-1e1afd50edc1/image.png" alt=""></p>
<p>사이트에 로그인 후, 요걸 클릭해서 들어간다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/7fa7d205-f912-4699-9dfc-d883f5b7446b/image.png" alt=""></p>
<p>여기다가 원하는 이름과 코드를 넣고 배경을 선택한 후,
(default는 저 홈페이지 바탕색이 나와서 비추,
라이트 모드 사용하는 경우에는 light,
다크 모드 사용하는 경우에는 dark로 배경색을 맞춰주는게 예쁨)</p>
<p>url를 생성해주면 된다.</p>
<p>무료 사용자는 <em><strong>3개</strong></em> 까지만 만들 수 있다.</p>
<h2 id="음악-플레이어를-담아보자">음악 플레이어를 담아보자</h2>
<p>일단, 대시보드에 음악 플레이어를 달 생각은 꿈에도 없었다.
대시보드에 사용할 위젯을 검색하면서 수많은 레딧 글을
해석하던 나는, <a href="https://www.reddit.com/r/Notion/comments/n3shzf/music_player_widget/">이 글</a>을 보게 된다.</p>
<h4 id="너-무-예-쁘-잖-아-">너 무 예 쁘 잖 아 ?</h4>
<p>그래서 몇 시간에 걸쳐 만들었다.</p>
<blockquote>
<p>this music player ui (codes and all) aren&#39;t mine. here&#39;s the codepen for it made by <strong>himalaya singh</strong>. i just made an html file with the css and js embedded and then put it in notion.</p>
</blockquote>
<blockquote>
<p>to do it, here&#39;s some things first:</p>
</blockquote>
<ul>
<li>this is not a spotify/apple music playlist. although i do also use notion for spotify and apple music (plays full on firefox which i use and apparently chrome too but i haven&#39;t tried that yet, doesn&#39;t work on other browsers or the notion desktop/mobile app)</li>
<li>the js, css, songs, and images used are hosted online (i use github)</li>
<li>you can either
use potions.dev to create the embed and then copy+paste the whole code (which i don&#39;t like bc of the edit widget/lock widget buttons below that are ugly but that&#39;s just a me thing, it&#39;s completely fine to use)
OR use a burner website (like i do) that you just embed in notion. i have my own that i host on a server and it contains pages of all widgets i use, but tumblr&#39;s fine too. just remove the controls by putting this is in the css.</li>
<li><em>body &gt; iframe:first-child { display: none !important; }*</em>
and then u can create an embed block and put the tumblr blog link</li>
</ul>
<blockquote>
<p>what you need:</p>
</blockquote>
<ul>
<li>urls of images and songs that must end with the file extensions (i.e. .jpg, .png, .mp3)you can host these on websites like dropbox and github, or you can even just copy the address of something you find online although it&#39;s safer to download and then upload them in your own folder in case the original gets deleted</li>
<li>html code to put in the embedhere&#39;s the code itself + the tutorial on how you can edit it</li>
</ul>
<p>일단, 레딧 작성자가 말해준 만드는 방법을 토대로 만들어 나가기 시작했다.</p>
<p>뮤직 플레이어 자체는 작성자가 직접 만든 것이 아니고, <strong>himalaya singh</strong>가 만든 codepen 소스를 따 온 것이라고 했다.</p>
<h3 id="1-소스코드">1. 소스코드</h3>
<p>!codepen[himalayasingh/embed/QZKqOX?default-tab=html%2Cresult]</p>
<p>여기서 오리지널 위젯의 html, css, js 코드를 받을 수 있다.</p>
<h3 id="2-인텔리제이에서-코드-수정">2. 인텔리제이에서 코드 수정</h3>
<p>레딧 작성자는 친절하게 html 알못도 코드를 수정해서 쓸 수 있도록 설명해주는 문서를 추가해 주었다.</p>
<p><a href="https://www.dropbox.com/scl/fi/h772vg2j3sbf00i4yzmiq/putting-together-himalayasinghs-music-player-ui-code.paper?dl=0&amp;rlkey=tsd5qgtmv5n5igmqg1402tvzi">여기</a>서 볼 수 있다.</p>
<pre><code>&lt;html&gt;
&lt;head&gt;
&lt;link rel=&#39;stylesheet&#39; href=&#39;https://use.fontawesome.com/releases/v5.3.1/css/all.css&#39;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;style&gt;
// insert the css from the codepen here
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
// insert the html code from the codepen here
&lt;script type=&quot;text/javascript&quot; src=&quot;https://code.jquery.com/jquery-2.1.4.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
// insert the js code from the codepen here
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><p>그 분이 작성해 준, html 틀을 인텔리제이에 복붙해서 넣고,
소스코드의 html, css, js 코드를 각각 복사해서 </p>
<blockquote>
<p>// insert the *** from the codepen here</p>
</blockquote>
<p>이라고 쓰여져 있는 곳에 잘 붙여넣는다.</p>
<p>잘 붙여넣었으면 이제, 원하는 대로 코드를 수정해야 한다.
(이 내용들은 <del><em>html을 기초만 배운자</em></del>를 기준으로 작성되었씁니다...)</p>
<hr>
<ol start="0">
<li>일단 코드를 수정하기 전에 원하는 곡의 mp3 파일과 앨범아트 이미지 파일을 준비한다.
그리고 인터넷에 업로드해서 url을 따 올수 있게 만든다.</li>
</ol>
<p>나는 <strong>github</strong>를 이용했는데, github의 저장소를 만들어 파일들을 업로드 한 후, 아래 주소에서 경로를 수정해주면 url을 만들 수 있다.</p>
<blockquote>
<p><a href="https://raw.githubusercontent.com/*%EC%A0%80%EC%9E%A5%EC%86%8C%EC%9D%B4%EB%A6%84*/files/*%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%9D%B4%EB%A6%84*/*%ED%8C%8C%EC%9D%BC%EB%AA%85.%ED%99%95%EC%9E%A5%EC%9E%90">https://raw.githubusercontent.com/*저장소이름*/files/*브랜치이름*/*파일명.확장자</a>*</p>
</blockquote>
<ol>
<li><strong>⭐️ 원하는 앨범아트로 바꾸기</strong></li>
</ol>
<p><code>&lt;div id=&quot;album-art&quot;&gt;</code> 코드를 찾아서 <code>img src</code> 코드를 찾아 앨범아트 이미지 url를 넣어준다.</p>
<ol start="2">
<li><strong>⭐️ 앨범, 곡명, 음악파일 바꾸기</strong></li>
</ol>
<p><code>var playerTrack</code>를 찾아 옆으로 쭈욱 넘기면,
<code>albums</code>, <code>trackNames</code>, <code>trackUrl</code>이 나온다.
얘네를 각각 수정해주면 되는데, 나는 <strong>앨범명</strong>을 <strong>곡명</strong>으로, <strong>트랙이름</strong>을 <strong>가수명</strong>으로 바꿔서 사용했다.
URL은 앨범아트와 마찬가지로 github 주소를 차례로 넣어주면 된다.</p>
<ol start="3">
<li><strong>⭐️ 플레이어 배경, 색 수정하기</strong></li>
</ol>
<p>여기서 멈춰도 되지만, 디폴트 배경이 앨범아트를 블러처리한 것을 되어있어서 노션에 위젯으로 넣으면 배경이 안맞는 것과 폰트를 맞춰주고, 초기 설정으로 되어있는 핑크톤보다는 내 대시보드에 맞게 노란색으로 수정을 해주고 싶었다.
그러기 위해서는 다음의 css 코드를 수정해줘야 했다.</p>
<ul>
<li>폰트, 기본 배경 바꾸기</li>
</ul>
<pre><code class="language-html">body
{
    font-family: Helvetica, Arial;
    margin: 0;
    background-color: #ffeff5;
}</code></pre>
<p>이 부분을 다음과 같이 바꾼다</p>
<pre><code>Helvetica 👉🏻 Courier New
#ffeff5 👉 #fff</code></pre><p>그 후에는 아래 <code>#bg-artwork</code>을 찾아서, <code>background-image</code>로 되어 있는 부분을 삭제해 준 후,
<code>background-color: #fff;</code>로 바꿔준다.</p>
<pre><code>#bg-artwork
{
    position: fixed;
    top: -30px;
    right: -30px;
    bottom: -30px;
    left: -30px;
    background-image: url(&quot;https://raw.githubusercontent.com/himalayasingh/music-player-1/master/img/_1.jpg&quot;);
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50%;
    filter: blur(40px);
    -webkit-filter: blur(40px);
    z-index: 1;
}</code></pre><ul>
<li>플레이어 몸통 부분 수정</li>
</ul>
<p><img src="https://images.velog.io/images/hailey_dev/post/52a541ac-82fd-4eec-a69f-42285479d5d5/image.png" alt=""></p>
<p>각 부분의 명칭을 정리해 놓았다.
저 이름들을 css 코드에서 찾아서 색상 코드를 바꿔주면 된다.</p>
<p>내가 쓴 색깔 코드는 </p>
<ul>
<li>배경색 : #fbf3da (연한 노랑)</li>
<li>재생바, 글씨색 : #FFB40F (개나리색)</li>
<li>그림자 : #E6E6E6 (연한 회색)</li>
</ul>
<p>이다.</p>
<ol start="4">
<li><strong>⭐️ 플레이어 위치, 그림자 수정</strong></li>
</ol>
<p>이대로 코드를 복사해서 붙여넣으면 플레이어 본체에 들어간
그림자가 너무 크고, 위치가 너무 아래여서 노션에 넣었을 때
예쁘게 보이지 않는다.</p>
<p>따라서 css 코드에서 다음 부분을 수정해 주어야 한다.</p>
<pre><code>#player-content
{
  position: relative;
  height: 100%;
  background-color: #fff;
  box-shadow: 0 30px 30px #E6E6E6;
  border-radius: 10px;
  z-index: 2;
}</code></pre><p><code>box-shadow</code> 부분의 픽셀과 색상코드, <code>border-radius</code>를 줄여주었다.</p>
<pre><code>    #app-cover
    {
      position: fixed;
      top: 35%;
      right: 0;
      left: 0;
      width: 430px;
      height: 100px;
      margin: -4px auto;
    }</code></pre><p> <code>position</code>을 <code>fixed</code>로 바꿔주고, <code>top</code>의 퍼센테이지를 수정해준다.</p>
<p> 이렇게 한 다음, 모든 코드를 복사해서 <code>apption</code>에서 embed widget을 만들어 주면 된다.</p>
<p> <a href="https://vimeo.com/581724343"><img src="https://images.velog.io/images/hailey_dev/post/81d05fb0-f556-494c-a526-977deef142de/image.png" alt="notion player"></a>
👆🏼 위 이미지를 클릭하면 동영상으로 연결</p>
<hr>
<h3 id="느낀점">느낀점</h3>
<p>사실 저 플레이어는 디폴트가 한곡이 끝나면 재생이 멈추는데,
한곡이 끝나면 자동으로 다음곡이 나오게 하고 싶었으나
html과 css 기초만 공부한 나는 아무리 봐도 자바스크립트를어떻게 수정하는지 모르겠다...</p>
<p>나중에 자바스크립트를 배우게되면 도전해 봐야겠다!</p>
<p>다음에는 구글 캘린더와 노션 캘린더를 연결해서 사용하는 방법을 알아보겠다!</p>
<p><a href="https://haileynotes.notion.site/sample-click-duplicate-1d5b61facbc649cc97fb1481b693ea63">template 공유</a></p>
<p>끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[노션 활용하기 - 위젯과 기본 블럭 활용]]></title>
            <link>https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%9C%84%EC%A0%AF%EA%B3%BC-%EA%B8%B0%EB%B3%B8-%EB%B8%94%EB%9F%AD-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%9C%84%EC%A0%AF%EA%B3%BC-%EA%B8%B0%EB%B3%B8-%EB%B8%94%EB%9F%AD-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Sun, 01 Aug 2021 05:29:40 GMT</pubDate>
            <description><![CDATA[<h1 id="기본-블럭은-예쁘다">기본 블럭은 예쁘다</h1>
<p><img src="https://images.velog.io/images/hailey_dev/post/0368f46c-3645-4125-ad97-ea0df3a304e4/notion_widget.001.jpeg" alt=""></p>
<p>내 대시보드의 반은 위젯이고, 반은 기본 블럭이다.</p>
<p>커스텀 위젯은 사용방법이 조금 복잡하니까, 제쳐두고 일단 기본 블럭으로 어떻게 꾸민건지, 웹페이지에서 바로 만들어서 간단한게 사용할 수 있는 위젯을 소개하겠다</p>
<h2 id="기본-블럭---call-out">기본 블럭 - call out</h2>
<p><img src="https://images.velog.io/images/hailey_dev/post/aeb38fb5-05ce-4c07-a59c-3009ace239cb/image.png" alt=""></p>
<p>콜아웃은 보통 강조하고 싶은 내용을 회색 블럭 안에 넣을 때 사용한다. 
나는 여기서 구역을 나누는데에 사용했다.
이모지를 적당한 걸 골라주고, 적당하게 내용을 넣으면 
구분선보다 더 두껍고 예쁘게 구역을 나눠줄 수 있다.</p>
<h2 id="기본-블럭---인용">기본 블럭 - 인용</h2>
<p><img src="https://images.velog.io/images/hailey_dev/post/c6d08be4-5f8b-4595-b0ac-0a34c6f4c2d6/image.png" alt=""></p>
<blockquote>
<p>이렇게 어디서 가져온 말을 인용할 때 많이 쓰는 블럭이다.</p>
</blockquote>
<p>옆에 선이 붙는 게 예뻐서 색을 추가해서 제목으로 활용했다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/0c3b734a-afc2-425e-a8ff-04332ffa4300/image.png" alt=""></p>
<p>색은 이렇게 블럭에서 우클릭을 하면 바꿔줄 수 있다!</p>
<h2 id="구분선은-사랑입니다">구분선은 사랑입니다.</h2>
<p>구분선은 블럭과 별개로 텍스트 밑이나 인라인 블럭을 불러올 때, 쓰기 편하다.</p>
<p>다른 마크다운들과 똑같이 <code>---</code>를 입력해주면 바로 기다란 회색선이 생긴다.</p>
<hr>
<h2 id="갬성-이미지-찾기-1">갬성 이미지 찾기 1.</h2>
<p>노션에 적당한 이미지를 넣어야 하는데 구글링은 귀찮고
그래도 이미지를 포기할 수 없어..!
하는 분들에게 이미지 탭에 <strong>unsplash</strong>를 추천한다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/605692a6-4690-4010-9632-583615d4b422/image.png" alt=""></p>
<p>위와 같이 원하는 키워드를 넣으면 적당한 이미지를 추천해준다.
내 대시보드의 여자아이 사진도 unsplash에서 빈티지를 쳤더니 나온 사진이다🤓</p>
<h2 id="갬성-이미지-찾기-2">갬성 이미지 찾기 2.</h2>
<p><a href="https://www.pinterest.co.kr">https://www.pinterest.co.kr</a></p>
<p>이건 뭐, 다들 알만한 <strong>pinterest</strong>를 이용하는 것이 가장 편하다.</p>
<p>나는 대시보드에 넣을만한 빈티지스러운 애니메이션 gif를 찾으려고 사용했다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/b9fa2cff-cd78-4929-be3a-acb39d083be4/image.png" alt=""></p>
<p><strong>지브리 gif</strong>나 <strong>빈티지 gif</strong>를 검색해서 적당한 걸 받아다 사용하면 된다!</p>
<h1 id="위젯을-가져와보자">위젯을 가져와보자</h1>
<h2 id="indify">indify</h2>
<p><a href="https://indify.co">https://indify.co</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/6aaaaf5c-1fe4-43a2-86c6-5caac9169e49/image.png" alt=""></p>
<p>학원 종강일 디데이 표시랑 벨로그, 네이버, 위버스 바로가기 버튼은 노션 전용 위젯 사이트인 indify에서 만들어 넣은 것이다.</p>
<p>위 링크를 타고 들어가서 로그인을 하면 내가 만든 것 말고도 총 9가지의 위젯을 만들어 쓸 수 있다.</p>
<p>그 중 내가 쓴 것은 <strong>countdown</strong>과 <strong>button</strong>이다.</p>
<p>만드는 방법은 정말 쉽고 간단하다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/3cd4f081-5615-4f0f-908d-c846dbf693d3/image.png" alt=""></p>
<p>사이트에서 만들고 싶은 위젯을 만든 후, 맨 하단의 링크를 복사한다.</p>
<p>그 후, 노션에 가서 원하는 위치에 <strong>embed</strong> 블럭으로 해당 링크를 임베드 해주면 된다!</p>
<h2 id="widgetbox">widgetbox</h2>
<p><a href="https://widgetbox.app/">https://widgetbox.app/</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/1e0a9ec2-5a20-4725-8506-292aa0ca7c07/image.png" alt=""></p>
<p>indify에도 시계와 달력 위젯이 있긴 하지만, 모양이 마음에 들지 않았다.</p>
<p>그러다가 찾게 된 것이 <strong>widgetbox</strong>이다. </p>
<p>여기도 노션용 위젯을 제공하는 사이트로, 보통 컴팩트한 사이즈의 위젯들을 제공한다.</p>
<p>그 중에서 내가 쓴 것은 <strong>Digital Retro Clock</strong>과 <strong>Simple Calendar</strong>이다.</p>
<p>단, indify의 구글 캘린더 위젯이 구글 캘린더를 연동하여 보여주는 것과 달리, widgetbox의 캘린더는 말그대로 그냥 오늘 날짜를 보여주는 달력 모양의 위젯일 뿐, 아무 기능이 없다.</p>
<h1 id="아이콘들은-어디서">아이콘들은 어디서?</h1>
<h2 id="icon8">icon8</h2>
<p><a href="https://icons8.com/icon/set/popular/">https://icons8.com/icon/set/popular/</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/86f7629c-1e61-4c18-8298-89f72f19ae2c/image.png" alt=""></p>
<p>여기에 쓰인 아이콘들은 모두 <strong>icon8</strong>에서 가져왔다.</p>
<p>노션 페이지마다 아이콘을 지정할 수 있는 건 다 알 것이다. 기본 이모지들 말고도 옆에 보면 커스텀으로 본인이 쓰고 싶은 아이콘 이미지를 사용할 수 있는데, 보통 유료이다.</p>
<p><em><strong>popular</strong></em> 탭은 무료로 사용이 가능하다.</p>
<p>나는 저 <strong>popular</strong>에서 <strong>pastel</strong> 테마의 아이콘들을 저장해서 썼다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/4295f18e-4ce5-440a-be86-d4540185611a/image.png" alt=""></p>
<p>다운 받을 때는 반드시 <strong>png</strong>로, <strong>250px</strong> 이상인 놈으로 다운    받아야, 본 페이지에 들어가서 큰 아이콘이 보였을 때도 이미지가 깨지거나 흐릿하지 않다.</p>
<hr>
<p>기본 블럭과 위젯에 대해 소개해 보았다.
다음에는 커스텀 위젯을 만드는 방법에 대해 써보겠다👒</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[노션 활용하기 - 대시보드]]></title>
            <link>https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-1</link>
            <guid>https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-1</guid>
            <pubDate>Sat, 31 Jul 2021 17:18:16 GMT</pubDate>
            <description><![CDATA[<h2 id="노션은-정말-획기적인-툴이다">노션은 정말 획기적인 툴이다</h2>
<p>오늘은 하루종일 이걸 만들었다.
다이어그램을 그렸어야 했는데...
그래도 이거 하느라고 html, css, javascript를
처음으로 인텔리제이에서 작성해봤으니
나름 반정도는 공부였다고 치자😋</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/35c4eddb-52db-4127-b69a-cb2c05e430c4/0F8D2B33-D9E7-4C66-934F-E3EDB2E39BE6_1_105_c.jpeg" alt=""></p>
<p>노션을 맨 처음 사용하기 시작하면 제일 먼저 만드는 것이 <code>대시보드</code>라고 한다.</p>
<p>나는 비록 사용한지 1년이 넘어서야, 제대로 된 대시보드를 만들었다.</p>
<p>구성요소는 다음과 같다.</p>
<hr>
<p><a href="https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%9C%84%EC%A0%AF%EA%B3%BC-%EA%B8%B0%EB%B3%B8-%EB%B8%94%EB%9F%AD-%ED%99%9C%EC%9A%A9">노션 활용하기 - 위젯과 기본 블럭 활용</a></p>
<blockquote>
<p>커스텀 아이콘 추가
콜아웃을 이용한 블럭 구분
간단한 캘린더 위젯
현재 시각 위젯
바로가기 버튼 위젯
인용을 이용한 제목 작성</p>
</blockquote>
<p><a href="https://velog.io/@hailey_dev/%EB%85%B8%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%9C%84%EC%A0%AF">노션 활용하기 - 커스텀 위젯</a></p>
<blockquote>
<p>날씨 위젯
뮤직 플레이어</p>
</blockquote>
<p><strong>작성 예정</strong>
구글 캘린더 연동 노션 캘린더</p>
<hr>
<p>오늘 하루종일 한 만큼, 할말이 많아서
자세한 내용은 내일 쓰기로 하고...
오늘은 일단 만든거 자랑만 하려고 올린다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥북 세팅하기 #1]]></title>
            <link>https://velog.io/@hailey_dev/%EB%A7%A5%EB%B6%81-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hailey_dev/%EB%A7%A5%EB%B6%81-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 31 Jul 2021 08:19:48 GMT</pubDate>
            <description><![CDATA[<h1 id="일단-그렇게-맥북을-샀다">일단 그렇게 맥북을 샀다</h1>
<p>초기설정, 셋팅에 목숨 거는 만큼 일주일 내내 세팅만 한 것 같다.
낑낑대면서 했던 나의 세팅들을 요 한 글에 모아보려고 한다.
(일주일동안 틈만 나면 구글링을 하면서 어플 500개 깔아보고 400개 지우고를 반복한.. 피땀눈물이 담긴 리스트이다😇)</p>
<h2 id="1-사파리-익스텐션">1. 사파리 익스텐션</h2>
<p>사파리에는 크롬 못지 않게 다양한 확장 프로그램들이 있다.
웹서핑을 하면서 쓰면 좋을만한 익스텐션을 소개한다!
(사파리 익스텐션은 App Store에서 받을 수 있다)</p>
<h3 id="🗂-유튜브-화질-강제로-고정하기-auto-hd-fps-for-youtubes-extension">🗂 유튜브 화질 강제로 고정하기 (Auto HD+ FPS for Youtube&#39;s extension)</h3>
<p><a href="https://apps.apple.com/kr/app/auto-hd-fps-for-youtube/id1546729687?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/38958520-cc9a-4506-bc29-0603d2cb5fa8/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/d4927d37-cfd4-4c6a-a55b-b5008afa0c51/image.png" alt=""></p>
<p>유튜브 화질이 무조건 해당 프레임 레이트로 실행되게 해주는 익스텐션이다. 최소 144p부터 4320p까지 설정할 수 있다. 
추가로 플레이어 사이즈를 항상 크게 영화관 모드로 나오게 초기 설정할 수 있다.</p>
<h3 id="🗂-영어-문법-체크하기-grammarly">🗂 영어 문법 체크하기 (Grammarly)</h3>
<p><a href="https://apps.apple.com/kr/app/grammarly-for-safari/id1462114288?l=en&amp;mt=12">바로가기</a>
<img src="https://images.velog.io/images/hailey_dev/post/d3129abf-2214-41b3-94b0-a01d491b63fa/image.png" alt=""></p>
<p>영작하거나 영어로 업무를 보는 분들이 쓰면 정말 좋은 익스텐션.
자동으로 문법을 체크해서 수정 제안을 해준다.
크롬에도 동일한 익스텐션을 쓰고 있었어서 바로 설치했다.</p>
<h3 id="🗂-동영상-pip-화면으로-띄우기-pipifier">🗂 동영상 PIP 화면으로 띄우기 (Pipifier)</h3>
<p><a href="https://apps.apple.com/kr/app/pipifier-pip-for-nearly-every-video/id1160374471?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/44515e33-7ebd-41b2-9537-59903bedcc8d/image.png" alt=""></p>
<p>유튜브나 동영상이 플레이되는 사이트에서 동영상만 팝업처럼 띄울 수 있도록 해주는 익스텐션이다.
단순히 PIP로만 되는 것이기 때문에 배속설정이나 이런 부분은 불가하다. (이게 다 되도록 하려면 익스텐션으로는 안되고, 별개 어플이 있는데 추후 소개하도록 하겠다!)</p>
<p>사용법은 간단하다.
동영상이 들어간 페이지에서 익스텐션 아이콘을 누르면,
PIP화면으로 동영상이 띄워진다.
앞, 뒤 이동이나 재생/일시정지하는 키보드 단축키도 먹힌다!</p>
<h2 id="2-앱스토어에-있는-툴들">2. 앱스토어에 있는 툴들</h2>
<h3 id="⌛️-디스크-정리-툴은-하나쯤은-clear-one">⌛️ 디스크 정리 툴은 하나쯤은...? (Clear One)</h3>
<p><a href="https://apps.apple.com/kr/app/cleaner-one-disk-clean/id1133028347?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/111d9ff7-d990-4460-a997-32ec6360767a/image.png" alt=""></p>
<p>디스크를 주기적으로 청소하고, 불필요한 파일들을 삭제하는 어플이다. </p>
<p>메뉴가 많은데, 그냥 맨 위에 Smart Scan만 돌리면 아래 있는 메뉴들의 기능이 한꺼번에 실행된다. 
<img src="https://images.velog.io/images/hailey_dev/post/22543834-eeaa-49d5-a671-547a736dce80/image.png" alt="">
이런식으로 정크 파일, 크기가 큰 파일, 중복 파일, 비슷한 사진들, 업데이트 가능 여부, 자주 사용하지 않는 어플들까지 보여준다. (일부는 유료기능이다.)
<img src="https://images.velog.io/images/hailey_dev/post/57472a59-993b-40b2-9efd-8ce9009b9f21/image.png" alt="">
자세히 보기를 클릭해서 들어가서 원하는 부분을 선택해서 정리해주면 된다!</p>
<p>연 2만원이면 프리미엄 기능도 쓸 수 있다고 하는데 나는 무료버전도 충분한 거 같아서 잘 쓰고 있다.</p>
<h3 id="⌛️-메뉴-바에서라도-집사-되어보기-run-cat">⌛️ 메뉴 바에서라도 집사 되어보기 (Run Cat)</h3>
<p><a href="https://apps.apple.com/kr/app/runcat/id1429033973?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/dfdc1314-73cf-46de-9092-c5b8e2be7589/image.png" alt="">
간단한 어플이다. 메뉴바에 고양이가 뛰어다닌다. (<em><del>나만 고양이 없어..</del></em>)</p>
<p>고양이를 클릭하면 현재 메모리 사용량 등을 알 수 있다. 의외로 자주 보게 된다. 고양이가 뛰어다니는데 이런 기능까지 있다니 금상첨화다.</p>
<p>고양이는 러버덕🐣이나, 사람, 그냥 점 모양 등으로 바꿀 수 있다.</p>
<h3 id="⌛️-미국은-대체-왜-아직도-인치를-쓰는가-g-converter">⌛️ 미국은 대체 왜 아직도 인치를 쓰는가 (g Converter)</h3>
<p><a href="https://apps.apple.com/kr/app/g-converter/id1545532142?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/e7ff9e62-2ef8-48d2-85ee-a2e2016fe1a4/image.png" alt="">
이것도 간단한 어플이다. 단위 변환을 해준다.
실행시키면 메뉴바에 아이콘에 추가되고 거기서 길이부터 온도까지 다양한 단위들을 변환할 수 있다.</p>
<p>창은 메뉴바에 고정시킬수도 있고, 따로 떼서 원하는 위치에 두고 쓸수도 있다.</p>
<p>물론 앱스토어에 검색하면 단위 변환 어플이 오조오억개지만, 그중에서 가장 디자인이 심플하고, 가벼워보이고, 그놈의 분수 (<del>1과 3/8인치 죽여...</del>)도 변환이 되는 어플을 선택했다.</p>
<p>일반인들이 많이 사용할 일이 있을까? 싶긴 하지만, 어쨋든 번역을 하는 입장에서 단위 변환할 일이 정말 많아서 바로 설치했다.</p>
<h3 id="⌛️-안읽은-메일-5천개-spark">⌛️ 안읽은 메일 5천개... (Spark)</h3>
<p><a href="https://apps.apple.com/kr/app/spark-email-app-by-readdle/id1176895641?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/7faa005f-9551-4b56-b3ae-4bc92d831aca/image.png" alt="">
이메일 어플이다. 이메일을 관리하는 어플은 맥에도 기본 내장되어 있고, 아웃룩도 있고 다양하지만, 나는 이 어플에 정착했다.</p>
<p>그 이유는 일단 안읽은 메일을 한꺼번에 읽음 처리 할 수 있는 기능이 있다. 여러 계정을 등록해두면, 안읽은 메일이 &#39;뉴스레터&#39;와 &#39;일반&#39; 메일로 자동으로 분류되어서 보여지고, 우측 상단에 &#39;한꺼번에 읽음 처리&#39; 버튼이 있다.</p>
<p>온갖 쇼핑몰, 웹사이트에서 날아오는 쓸데없는 메일들을 한꺼번에 (한 100개까진 한번에 되는거 같다) 처리하기 정말 좋다.</p>
<h3 id="⌛️-아니-맥은-왜-잘라내기가-안됩니까-pasta">⌛️ 아니 맥은 왜 잘라내기가 안됩니까? (Pasta)</h3>
<p><a href="https://apps.apple.com/kr/app/pasta/id1438389787?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/666935a8-b9b5-4333-bf65-02a1fefdcc92/image.png" alt="">
클립보드 관리 어플이다. 원래는 구글링 하니까 다른 어플이 나와서 깔았는데, 구독형으로 바뀌면서 가격이 너무 올라 욕을 바가지로 먹고 있다는 걸 깨달았다..</p>
<p>그 대체용으로 찾은 것이 이 어플이다.</p>
<p>일단 그림을 포함해서 복사한 것들이 저장되고 단축키를 통해 어플을 열어서 원하는 걸 복사해다 쓸 수 있다. 자주 쓰는 건 즐겨찾기 설정도 가능하다.</p>
<p>서식이 지정된 글인 경우에는 서식까지 한번에 복사가 되고, 그 안에서 서식을 지운 텍스트만 복사하는 것도 가능하다.</p>
<p>무엇보다 내가 이 어플을 못 지우는 이유는 바로 <strong>잘라내기</strong> 때문이다.</p>
<p>아니 잘라내기가 얼마나 쓸 일이 많은데 맥북은 잘라내기가 안된다. 되긴 하지만 단축키가 복잡하고 귀찮다. </p>
<p>이 어플을 깔아두면 똑같이 <code>⌘x</code> 로 잘라내기를 할 수 있다. 복붙을 하는데 복사가 된건지 안된건지 확인할 수 있게 소리가 나게 설정할 수도 있다!</p>
<p>이거 하나만으로 이 어플은 효용을 다했다고 본다.
잘라내기 최고.</p>
<h3 id="⌛️-좀더-진화된-딴짓을-하고-싶다면-friendly-streaming">⌛️ 좀더 진화된 딴짓을 하고 싶다면... (Friendly Streaming)</h3>
<p><a href="https://apps.apple.com/kr/app/friendly-streaming-browser/id553245401?l=en&amp;mt=12">바로가기</a></p>
<p>아까 사파리 익스텐션을 소개하면서, 배속까지 가능한 PIP 화면을 보는 방법이 있다고 했는데, 그게 바로 이 어플이다.</p>
<p><img src="https://images.velog.io/images/hailey_dev/post/e46358de-433d-4d45-94b6-ede9345a29c6/image.png" alt=""></p>
<p>나는 이렇게 주로, 생활코딩 같은 인터넷 강의를 들을 때 활용하고 있다.
강의를 들으면서 코드를 따라치기에 아주 좋다!
앞서 나온 <strong>PiPifier</strong>이랑 비교해서 다른 점은 아래와 같다.</p>
<table>
<thead>
<tr>
<th align="center">이름</th>
<th align="center">PiPifier</th>
<th align="center">Friendly Streaming</th>
</tr>
</thead>
<tbody><tr>
<td align="center">실행방법</td>
<td align="center">사파리에서 버튼을 누름</td>
<td align="center">원하는 URL을 복붙</td>
</tr>
<tr>
<td align="center">배속기능</td>
<td align="center">미리 배속 설정하고 띄우면 사용 가능</td>
<td align="center">유튜브 기준 동일하게 3배속까지 가능</td>
</tr>
<tr>
<td align="center">투명도조절</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">창크기 조절</td>
<td align="center">가능 (비율 고정)</td>
<td align="center">가능 (비율 자유)</td>
</tr>
<tr>
<td align="center">재생바 이동</td>
<td align="center">불가능</td>
<td align="center">가능</td>
</tr>
</tbody></table>
<p>일반 동영상을 볼때는 귀찮으니까 그냥 Pipifier를 이용해서 보고,
배속을 해서 강의를 들어야 할때는 Friendly Streaming을 켠다.</p>
<p>유일한 단점이, 사파리로 서핑을 하다가 어플을 켜서 URL을 복붙해야 제대로 된다는 건데 이건 추후 소개할 <strong>알프레드</strong>를 이용해서 어느정도 보완이 가능하다.</p>
<h3 id="⌛️-내가-복사한-내용을-안드로이드에서-볼-수-있을까-magic-copy">⌛️ 내가 복사한 내용을 안드로이드에서 볼 수 있을까? (Magic Copy)</h3>
<p><a href="https://apps.apple.com/kr/app/magic-copy/id1434526691?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/f2072edb-7108-4acd-b684-e1c17edfdead/image.png" alt="">
클립보드 공유 앱이다.</p>
<p>나는 맥북을 처음 사는 입장으로, 맥북을 제외한 나머지 모든 기기가 윈도우 PC나 안드로이드 태블릿, 안드로이드 폰이었기 때문에 동시에 기기를 사용할 때 이래저래 애를 먹었다.</p>
<p>특히, URL 같은걸 복사해서 붙여넣거나 강의 내용을 복붙할 때 귀찮음을 많이 겪었는데, 그걸 어느정도 해소해준 것이 이 어플이다.</p>
<p>매직카피는 맥, 아이폰, 안드로이드, 윈도우를 모두 지원한다.</p>
<p><a href="https://magiccopy.xyz">https://magiccopy.xyz</a></p>
<p>해당 사이트로 들어가서 각 지원체제에 맞는 것을 다운 받고, 같은 계정으로 로그인 해두면 클립보드가 공유된다.
단, 이미지나 서식은 복사가 안되고 <strong>텍스트만</strong> 된다.</p>
<p>물론 빠릿빠릿하게 잘 되지는 않고 가끔 동기화가 안될 때도 있고 버벅일 때도 있지만 그래도 이런 어플이 있다는 게 어딘가 싶다😇</p>
<h3 id="⌛️-gif를-간단하게-만드는-방법-giphy-capture">⌛️ GIF를 간단하게 만드는 방법 (GIPHY Capture)</h3>
<p><a href="https://apps.apple.com/kr/app/giphy-capture-the-gif-maker/id668208984?l=en&amp;mt=12">바로가기</a></p>
<p><img src="https://images.velog.io/images/hailey_dev/post/372f1dfb-e127-4248-82f2-de4162bb21d0/Jul-31-2021%2017-08-16.gif" alt="">
간단하게 gif를 만들 수 있는 어플이다.</p>
<p>giphy에서 개발한 어플이라, gilhy 계정을 로그인해서 바로 업로드를 할수도 있고, 그냥 바로 파일로 저장을 할수도 있다.</p>
<p>간단하지만 나름 캡션도 넣을 수 있고 프레임수 조절이나 찍은 후 간단하게 편집도 가능하다.</p>
<hr>
<p>글이 너무 길어져서 2편으로 나누어야 겠다.
다음 편에서는 앱스토어에 없는 맥용 툴들을 정리해야겠다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ArrayList 활용 예제]]></title>
            <link>https://velog.io/@hailey_dev/ArrayList-%ED%99%9C%EC%9A%A9-%EC%98%88%EC%A0%9C</link>
            <guid>https://velog.io/@hailey_dev/ArrayList-%ED%99%9C%EC%9A%A9-%EC%98%88%EC%A0%9C</guid>
            <pubDate>Thu, 29 Jul 2021 15:46:27 GMT</pubDate>
            <description><![CDATA[<h4 id="🎈-5명의-사람-이름을-입력-받아서-arraylist에-저장한-후에-이들-중-김씨-성을-가진-사람을-모두-출력하시오">🎈 5명의 사람 이름을 입력 받아서 ArrayList에 저장한 후에 이들 중 &#39;김&#39;씨 성을 가진 사람을 모두 출력하시오</h4>
<hr>
<pre><code class="language-java">// 5명의 사람 이름을 입력 받아서 ArrayList에 저장한 후에 이들 중 &#39;김&#39;씨 성을 가진 사람을 모두 출력하시오.
// + 김씨 성을 가진 사람이 몇 명인지 출력하시오.

import java.util.ArrayList;
import java.util.Scanner;

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

        Scanner sc = new Scanner(System.in); // 스캐너 불러오기
        ArrayList&lt;String&gt; names = new ArrayList(); // ArrayList 생성
        int index = 0; // 몇 명인지 숫자 세기

        for(int i = 0 ; i &lt;= 4 ; i++) { // 스캐너로 이름 5개 입력 받기
            System.out.println(&quot;이름을 입력해 주세요&quot;);
            names.add(sc.nextLine());
        }

        System.out.println(&quot;성이 &#39;김&#39;인 분의 이름을 모두 출력합니다.&quot;);

        for(int i = 0 ; i &lt;= 4 ; i++) {
            String name = names.get(i); // 배열의 값(이름)을 변수에 저장
            if (name.startsWith(&quot;김&quot;)) { // 만약 &quot;김&quot;으로 시작한다면, 
                index++; // 인덱스는 +1
                System.out.printf(&quot;[%s]\t&quot;,names.get(i)); // 이름이 출력됨
            }
        }
        System.out.println();
        System.out.println(&quot;김씨 성을 가진 분은 모두 &quot; + index + &quot; 명 입니다.&quot;);
          // 몇 명인지도 인덱스를 통해 출력됨
    }
}</code></pre>
<h4 id="🎈-5명의-별명을-입력-받아-arraylist에-저장하고-이들-중-별명의-길이가-제일-긴-별명을-출력하시오">🎈 5명의 별명을 입력 받아 ArrayList에 저장하고 이들 중 별명의 길이가 제일 긴 별명을 출력하시오.</h4>
<ul>
<li>단, 각 별명의 길이는 모두 다르게 입력한다.</li>
<li>별명의 길이가 같은 것을 입력할 수 있는 경우를 처리하시오.</li>
</ul>
<hr>
<pre><code class="language-java">import java.util.ArrayList;
import java.util.Scanner;

// 5명의 별명을 입력 받아 ArrayList에 저장하고 이들 중 별명의 길이가 제일 긴 별명을 출력하시오.
// (단, 각 별명의 길이는 모두 다르게 입력한다.)
// 위 문제에서 별명의 길이가 같은 것을 입력할 수 있는 경우를 처리하시오.

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

        Scanner sc = new Scanner(System.in); // 스캐너
        ArrayList&lt;String &gt; nicknames = new ArrayList(); // ArrayList 생성
        int[] lengthArr = new int[5]; // 별명 문자열 길이를 저장할 배열
        int max = lengthArr[0]; // 최대값을 저장할 인스턴스

        for (int i = 0 ; i &lt;= 4 ; i++) { // 5개의 별명을 입력 받는다
            System.out.println(&quot;별명을 입력 해 주세요!&quot;);
            nicknames.add(sc.nextLine());
        }


        for (int i = 0 ; i &lt;= 4 ; i++) {
          // ArrayList에 저장된 각 별명들의 길이를 lengthArr에 저장한다
            lengthArr[i] = nicknames.get(i).length();
            if (max &lt; lengthArr[i]) { // 최대값을 찾아 max에 저장한다
                max = lengthArr[i];
            }
        }

        for (int i = 0 ; i &lt;= 4 ; i++) { // i번째 배열의 길이가 max와 같다면 출력한다
            if (max == nicknames.get(i).length()) {
                System.out.println(&quot;가장 길이가 긴 별명은 &gt; &quot; + nicknames.get(i));
            }
        }
    }
}</code></pre>
<hr>
<p><a href="https://velog.io/@amuse_on_01/HIGH-JAVA-ArrayList-%EC%97%B0%EC%8A%B5%EB%AC%B8%EC%A0%9C">예제 출처</a></p>
<hr>
<h2 id="느낀점">느낀점</h2>
<p>뭔가 더 for문을 적게 쓰고도 할 수 있는 방법이 있을 것 같은데 잘 모르겠다. ArrayList를 배워서 어딘가 써먹었다는 데에 의의를 둔다.
두 번째 문제에서 중복값을 처리할 수 있는 방안을 만들라고 했는데, 어차피 중복값이 나와도 가장 길이가 긴 별명이 복수일 경우, 모두 출력 되기 때문에 저 코드로 괜찮지 않나 싶었다. (<em><del>아닌가?</del></em>)
아, 여전히 for문으로 최대값, 최소값 구하기와 String 함수 종류가 헷갈리기 때문에 내일 다시 정리해 두어야 겠다고 생각했다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[추상 클래스와 인터페이스]]></title>
            <link>https://velog.io/@hailey_dev/%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@hailey_dev/%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Wed, 28 Jul 2021 16:13:52 GMT</pubDate>
            <description><![CDATA[<h2 id="✨-추상-클래스-abstract-class">✨ 추상 클래스 (Abstract Class)</h2>
<p>➡️ 문법 : <code>stract class 클래스이름</code> </p>
<ul>
<li>추상 메서드를 포함한 클래스</li>
<li>인스턴스 생성 불가</li>
<li>생성자, 멤버변수, 메서드는 포함</li>
<li>반드시 상속을 해서 자손 클래스에서 완성 시켜 줘야 함</li>
</ul>
<p><strong>추상클래스의 역할</strong></p>
<ul>
<li>새로운 클래스를 작성하는데 있어서 바탕이 되는 조상클래스</li>
<li>클래스들의 공통부분을 그린 미완성 설계도를 그려놓고 나중에 각 설계도를 완성하는 방식</li>
</ul>
<hr>
<h2 id="✨-추상-메서드-abstract-method">✨ 추상 메서드 (Abstract Method)</h2>
<p><img src="https://user-images.githubusercontent.com/87118337/127353813-f808c5a2-16aa-4367-9dff-587fc88e8d58.png" alt="image"></p>
<p>추상 메서드는 위 이미지의 메서드의 구성 요소 중 <code>선언부</code> 만 작성한다 (마칠때 세미콜론(;) 포함)
주석으로는 어떤 기능을 수행할 목적으로 작성하였는지 설명한다</p>
<p><code>구현부</code> 인 메서드 내용은 추상클래스를 상속 받는 자손클래스에서 overriding을 통해 재정의를 해서 사용한다.</p>
<p>즉, 해당 추상 클래스를 상속받은 자손 클래스는 <strong>반드시 클래스 내에 있는 추상 메서드를 전부 재정의(overriding) 해줘야만</strong> 사용이 가능하다</p>
<hr>
<h2 id="✨-인터페이스-interface">✨ 인터페이스 (Interface)</h2>
<p>➡️ 문법 : <code>interface 인터페이스 이름 {  인터페이스 내용  }</code>  </p>
<p>인터페이스는 일종의 추상 클래스이다. 추상클래스 보다 추상화 정도가 높은 추상 메서드를 가지고 있는 클래스의 일종이라고 생각하면 된다.</p>
<p>인스턴스만 생성 불가이고, 생성자, 멤버변수, 메서드는 얼마든지 넣어도 되는 추상 클래스와 달리 인터페이스가 가질 수 있는 것은 단 2개이다.</p>
<ul>
<li>상수</li>
<li>추상 메서드</li>
</ul>
<p>어차피 인터페이스 안에는 위 2가지만 쓸 수 있기 때문에 상수랑 추상 메서드 앞에 길게 붙는 수식어들(아래 괄호 안)을 생략할 수 있다.</p>
<pre><code class="language-java">(public static final) [타입] [상수이름] = [값];
(public abstract) [메서드이름] ([매개변수]);</code></pre>
<p>인터페이스가 특이한 점은, 다중상속이 가능하다는 것이다. </p>
<pre><code class="language-java">interface Movable {
            void move (int x, int y);
}

interface Attackable {
            void attck (Unit u);
}

interface Fightable extends Movable, Attackable { 
            // 위의 인터페이스 2개를 상속 받았으므로, 이 안에서는
            // move(), attack() 메소드를 쓸 수 있다 (멤버로 가진다)
 }</code></pre>
<p>인터페이스는 추상 클래스와 마찬가지로 인스턴스를 생성할 수 없고, 다른 클래스에서 인터페이스를 받아서 메소드를 완성해 줘야 한다.</p>
<p><img src="https://user-images.githubusercontent.com/87118337/127353914-85b636fe-a945-42de-b1a8-01b26d39f1e1.png" alt="image"></p>
<p>이렇게 다른 클래스에서 인터페이스를 받아 쓸 때는, 상속과 마찬가지로 클래스 이름 뒤에 <code>implements</code> 를 붙이고 인터페이스 이름을 넣어주면 된다. 이 때 이런 것을 <code>[인터페이스 이름]이 [클래스 이름]을 구현한다</code>고 말한다. </p>
<p>위 이미지 같이 상속과 구현을 동시에 하는 것도 가능하다.</p>
<blockquote>
<p>인터페이스 이름은 어떠한 기능 또는 행위를 하는데 필요한 메소드를 제공한다는 의미를 강조하기 위해서<code>Fightable</code> 과 같이 <strong><em>~할 수 있는</em></strong> 이라는 뜻을 가진 <strong><em>able</em></strong>을 붙이는 것이 일반적이다.</p>
</blockquote>
<pre><code class="language-java">class Unit { int currentHP, x, y; }

interface Movable {
            void move (int x, int y);
}

interface Attackable {
            void attack (Unit u);
}

interface Fightable extends Movable, Attackable { 
            // 위의 인터페이스 2개를 상속 받았으므로, 이 안에서는
            // move(), attack() 메소드를 쓸 수 있다 (멤버로 가진다)
 }

class Fighter extends Unit implements Fightable {
            public void move (int x , int y) { 함수 내용  }
            public void attack (Unit u) { 함수 내용 }
}</code></pre>
<p>위의 코드를 도식화 하면 아래 그림과 같다.</p>
<p><img src="https://user-images.githubusercontent.com/87118337/127353993-dd4a84df-aea2-4ffb-a3de-6983a0fcf834.png" alt="image"></p>
<p><code>Fightable</code> 인터페이스는 <code>Movable</code> 과 <code>Attackable</code>  인터페이스를 다중상속 받았기 때문에 <code>Fighter</code>  클래스는 <code>Fightable</code> 인터페이스만 구현했지만, <code>move();</code>과  <code>attack();</code> 메소드를 모두 가져와서 완성시킬 수 있었다.</p>
<p>이 때, 주목해야할 점은 <code>Fighter</code> 클래스에서 두 메소드를 완성시킬 때 <code>public</code> 이 사용되었다는 것이다. 이 이유는, 인터페이스에 들어가는 모든 메소드에는 앞서 말했다시피, <code>public abstract</code>이 생략 되었기 때문이다.</p>
<p>이와 같이 인터페이스는 다중 상속이 가능하지만 실제로 인터페이스를 통해 다중 상속을 구현하는 경우는 거의 없다. 굳이 다중 상속을 해야할 경우에는 보통 두 조상 클래스 중에서 비중이 높은 쪽을 선택하여 구현하고 다른 한 쪽은 클래스 내부에 멤버로 포함 시키거나 필요한 부분만 뽑아서 포함 시키는 것이 바람직하다.</p>
<hr>
<h2 id="✨-다형성의-활용-interface의-형변환-instanceof-연산자-활용">✨ 다형성의 활용 (Interface의 형변환, instanceof 연산자 활용)</h2>
<p>인터페이스 타입으로 형변환 하는 것을 알아보기 전에, 며칠 전에 배웠던 다형성과 참조변수의 형번환을 다시 복습해보자. </p>
<p>객체지향개념에서 다형성 이란?
<code>조상</code>클래스 타입의 <code>참조변수</code>로 <code>자손</code>클래스의 <code>인스턴스</code>를 참조할 수 있는 것</p>
<pre><code class="language-java">class Tv {
        boolean power;
        int channel;

        void power() { power = !power; }
        void channelUp() { ++channel; }
        void channelDown() { --channel; }
}

class CaptionTv extends Tv {
        String text;
        void caption() { /*내용생략*/ }
}

public class Exercise {
    public static void main(String[] args) {
            Tv       t     =   new CaptionTv();
    //조상class    참조변수     인스턴스   자손타입
    // -&gt; 조상 타입의 참조변수로 자손 인스턴스를 참조

    CaptionTv c = new CaptionTv();
    Tv t = (Tv) c;
    // 위 두 줄을 합치면 Tv t = new CaptionTv();가 된다    
    }
}</code></pre>
<p>위와 같이 <code>CaptionTv</code>가 <code>Tv</code>를 상속할 때, <code>Tv</code> 타입의 참조변수로 <code>CaptionTv</code> 타입의 인스턴스를 참조할 수 있는 것이다. 이 때, 참조변수 <code>t</code> 는 <code>CaptionTv</code> 에 있는 인스턴스 중, <code>Tv</code> 에서 정의된 멤버들만 사용할 수 있다. (<code>String text</code> 와 <code>caption()</code> 은 사용하지 못함)</p>
<p>참조변수들은 상속 관계가 있을 때, 형변환으로 부모 타입이나 자식 타입으로 변신할 수 있다. 이때, 자손타입에서 부모타입은 <code>(부모타입)</code> 이라는 캐스팅 연산자를 생략 가능하지만, 부모타입에서 자손타입은 생략이 불가하다.</p>
<p><img src="https://user-images.githubusercontent.com/87118337/127354098-3da31707-698b-4809-b29b-cc59a79448ca.png" alt="image"></p>
<pre><code>👶🏻 ➡️ 👵🏻  : 형변환 생략가능 
👵🏻 ➡️ 👶🏻 : 형변환 생략불가 
🤷‍♀️ WHY? →  
자손타입이 더 포함하고 있는 내용이 많기 때문에 (내꺼도 내꺼, 니꺼도 내꺼) </code></pre><blockquote>
<p><strong><em>애초에 형변환은 왜 하는 걸까?</em></strong>
형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에 참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다.
단지 참조변수의 형변환을 통해서 참조하고 있는 <strong>인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절</strong>하는 것 뿐이다.</p>
</blockquote>
<p>서로 상속관계에 있는 타입 간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다. 그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.</p>
<p>이때 쓰는 것이 연산자 <code>instanceof</code> 이다. <code>instanceof</code>는 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아볼 수 있다. 주로 조건문(if)에서 쓰이며, 결과값은 true/false로 반환된다.</p>
<pre><code class="language-java">if ( 참조변수 instanceof 타입명 ) {
                    타입명 변수명 = (타입명) 참조변수;
                    // 형변환이 가능할 때(true), 형변환을 하는 구문
    } </code></pre>
<p><code>instanceof</code> 는 구체적으로 다음과 같은 상황일 때 쓰일 수 있다.</p>
<pre><code class="language-java">void doWork(Car c) {
            if (c instanceof FireEngine) {
                    FireEngine fe = (Fireengine) c;
                    fe.water();
            } else if (c instanceof Ambulance) {
                    Ambulance a = (Ambulance) c;
                    a.siren();
            }
}

/* ... */

public class Exercise {
    public static void main(String[] args) {
                doWork(c);
                // 여기서 매개변수를 입력 했을 때, c의 클래스가 
              // Car클래스일지, Car클래스의 자손클래스일지 모름
        }
}</code></pre>
<p>예제에서 보면, <code>doWork</code> 함수에서 매개변수로 <code>Car</code> 타입의 참조변수 <code>c</code> 를 받고 있다. 이 함수가 실제로 메인 함수에서 쓰였을 때, 매개변수로 입력될 수 있는 것은 <code>Car 클래스 및 Car 클래스의 자손 클래스를 타입으로 가지는 인스턴스</code> 이다. 그러므로, 매개변수로 입력되는 것(인스턴스)이 <code>FireEngine</code> 타입으로 형변환이 가능할지 모르는 것이다.</p>
<p>이럴 때는 무작정 형변환을 시도하는 것이 아닌, <code>instanceof</code>로 형변환이 가능한지 체크를 해주고 형변환을 진행해야 한다.</p>
<pre><code class="language-java">class Unit { int currentHP, x, y; }

interface Movable {
            void move (int x, int y);
}

interface Attackable {
            void attck (Unit u);
}

interface Fightable extends Movable, Attackable { 
            // 위의 인터페이스 2개를 상속 받았으므로, 이 안에서는
            // move(), attack() 메소드를 쓸 수 있다 (멤버로 가진다)
 }

class Fighter extends Unit implements Fightable {
            public void move (int x , int y) { /*함수 내용*/  }
            public void attack (Unit u) { /*함수 내용*/ }
}

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

            Fightable f = (Fightable) new Fighter();
                                /*또는*/
            Fightable f = new Fighter();
    }
}</code></pre>
<p>다시 인터페이스 얘기로 돌아와서, 인터페이스를 구현한 클래스는 인터페이스를 부모 클래스로 둔 자손 클래스라고도 볼 수 있다. 따라서 위 코드에서 보면 <code>Fightable</code>타입의 참조변수로 <code>Fighter</code> 인스턴스를 호출한 것을 알 수 있다. (단, 참조변수로는 인터페이스 <code>Fightable</code>에 정의된 멤버만 가능하다.)</p>
<p>인스턴스를 참조할 수 있으니까, 매개변수로도 쓸 수 있다.</p>
<pre><code class="language-java">void attack (Fightable f) { /*함수내용*/ }
            /*또는 함수 호출 시에 아래와 같이도 사용 가능*/
attack(new Fighter());</code></pre>
<p>이렇게. 아래와 같이 리턴타입으로 지정하는 것도 가능하다.</p>
<pre><code class="language-java">Fightable method() {
            /* 함수 내용 */
        Fighter f = new Fighter();
        return f;
        // 위 두 문장을 한 문장으로 합치면
        return new Fighter();
}</code></pre>
<p>이런 식으로. </p>
<p>이는 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
→ 풀어쓰면, <code>Fightable</code> 이 리턴 타입이다 = <code>Fighter</code> 클래스의 인스턴스를 리턴하는 거나 마찬가지라는 얘기.</p>
<p>이렇게 인터페이스의 다형성은 아래 예제처럼도 활용될 수 있다.</p>
<pre><code class="language-java">interface Parseable {
    // 구문 분석 작업을 수행한다.
    public abstract void parse (String fileName);
}

class ParserManager {
    // 리턴 타입이 Parseable 인터페이스
    public static Parseable getParser(String type) {
        if (type.equals(&quot;XML&quot;)) {
            return new XMLParser();
        } else {
            Parseable p = new HTMLParser();
            return p;
            // return new HTMLParser();
        }
    }
}

class XMLParser implements Parseable {

    @Override
    public void parse(String fileName) {
        /* 구문 분석 작업을 수행하는 코드를 적는다 */
        System.out.println(fileName + &quot;- XML parsing completed&quot;);
    }
}

class HTMLParser implements Parseable {

    @Override
    public void parse(String fileName) {
        /* 구문 분석 작업을 수행하는 코드를 적는다 */
        System.out.println(fileName + &quot;- HTML parsing completed&quot;);
    }
}

public class Interface_ParserTest {
    public static void main(String[] args) {
        Parseable parser = ParserManager.getParser(&quot;XML&quot;);
                // parser는 XMLParser의 주소값을 갖게 된다
        parser.parse(&quot;document.xml&quot;);
        parser = ParserManager.getParser(&quot;HTML&quot;);
                // parser는 HTMLParser의 주소값을 갖게 된다
        parser.parse(&quot;document2.html&quot;);
    }
}</code></pre>
<p>다음과 같다. <del>복잡하다.</del></p>
<p>일단, 해당 예제는 파일 확장자가 xml인지, html인지 구분하는 프로그램을 구현한 것이다. </p>
<ul>
<li><code>Parseable</code> 은 인터페이스로, 파일 이름을 매개변수로 받아서 분석을 하는 함수를 포함하고 있다.</li>
<li><code>ParserManager</code>은 클래스로, 확장자(type)을 매개변수로 받아서 파일 확장자가 XML이면 <code>XMLParser</code> 클래스를 리턴하고, HTML이면 <code>HTMLParser</code> 클래스를 리턴하는 함수(<code>getParser</code>)가 들어있다.</li>
<li>밑의 내용만 다른 두 개의 <code>XMLParser</code> , <code>HTMLParser</code> 는 인터페이스 <code>Parseable</code> 를 구현하는 클래스로, 인터페이스 안에 있는 <code>parse</code> 함수를 재정의 하여, 파일 이름 밑 구문 분석이 끝났다는 문구를 출력하는 내용을 넣어주었다 (=구현하였다).</li>
<li><code>main</code> 함수 영역에서는 인터페이스 타입의 <code>parser</code> 객체를 만들고, <code>getParser</code> 함수를 호출하여 &quot;XML&quot;이라는 타입명을 매개변수로 넣어주었다.</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/87118337/127354201-cd14f759-9917-45ca-955b-83fa162c0193.png" alt="image"></p>
<ul>
<li>메인 함수에 있는 <code>Parseable parser = ParserManager.getParser(&quot;XML&quot;);</code> 를 실행하면, <code>parser</code>에는 스태틱 함수인 <code>getParser</code> 의 실행 결과가 저장되게 된다. 즉, <code>parser</code>는 <code>XMLParser</code> 의 주소값을 가지게 된 것이다.</li>
</ul>
<hr>
<h2 id="✨-상속-포함-의존">✨ 상속, 포함, 의존</h2>
<ol>
<li><p>상속관계 (is-a)
 우리가 여태까지 했던 부모-자식 관계
 → <code>a가 b를 상속한다 (a extends b)</code> 라고 했을 때, a의 객체가 생성됨과 동시에 b도 메모리에 올라간다.</p>
</li>
<li><p>포함관계 (has-a)
 b는 a에 포함된다는 것은 b가 a의 부품(멤버필드)이라는 것
 클래스 안에 <code>B b;</code> 와 같은 형식으로 선언됨</p>
<ul>
<li>전체집합
 차 - 엔진의 관계
 → 엔진은 차 없이 존재할 수 없다
 → 생명주기가 같다 (a가 생성될 때, b도 생성된다)</li>
<li>부분집합
학교 - 학생의 관계
→ 학생은 학교 없이도 존재할 수 있다 (따로 생성 OK)
→ 생명주기가 다를 수 있다 (a가 생성된다고 b가 자동으로 생성되지 않음)
→ 다만, 학생은 학교 안에서 부품(멤버필드)로 사용될 수 있다</li>
</ul>
</li>
<li><p>의존관계
 함수(method) 내에서 사용되는 것을 말함
 → 포함과는 다르게 부품(멤버필드)로 존재하지 않는다
 → 객체를 <code>지역변수</code> 또는 <code>매개변수</code>로 사용하는 것
 → 포함과는 다르게 함수 내에서만 사용되고 함수가 끝나면 증발</p>
<pre><code> (더 이상 객체를 참조하지 않는다)</code></pre></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥북 적응하기 #1]]></title>
            <link>https://velog.io/@hailey_dev/%EB%A7%A5%EB%B6%81-%EC%A0%81%EC%9D%91%ED%95%98%EA%B8%B0-1</link>
            <guid>https://velog.io/@hailey_dev/%EB%A7%A5%EB%B6%81-%EC%A0%81%EC%9D%91%ED%95%98%EA%B8%B0-1</guid>
            <pubDate>Wed, 28 Jul 2021 05:31:56 GMT</pubDate>
            <description><![CDATA[<h2 id="왜-맥북-샀어">왜 맥북 샀어?</h2>
<p>개발을 공부해야겠다고 마음 먹으면서, 가장 사고 싶었던 건 단연 새 노트북이었다. 물론 나의 3년된 그램도 아직 팔팔히 잘 돌아가지만, 까마귀 마냥 빛나는 새 물건들을 사 모으는 나에게 &#39;개발 공부 시작&#39;은 아주 좋은 핑곗거리였다.</p>
<p>새 노트북을 사려고 알아보면서, 그램보다 성능이 나은 (덕질도 해야하고, 영화도 봐야하고, 게임도 해야하니까) 윈도우 노트북을 들일까, 아니면 아예 데스크탑을 맞출까도 생각해봤다. 그렇지만 그램도 잘 돌아가는데 윈도우를 또 사는건 좀 아닌 것 같았고, 그놈의 코인 때문에 천정부지로 치솟는 그래픽카드 값을 감당하면서 갖고 다닐수도 없는 데스크탑을 맞추는 것도 그닥 땡기지 않았다.</p>
<p>일단 나의 컴퓨터 주 사용 목적은</p>
<ul>
<li>개발 공부 (주로 웹 프론트, 백엔드)</li>
<li>번역 작업 (SDL Trados, 그 외 문서작업)</li>
<li>간단한 영상, 사진 편집 작업 (하다만 영상 편집 공부도 같이 할 수 있으면 좋겠다)</li>
<li>각종 영상 시청 및 녹화 (4K 모니터에 물려서 영상 돌리거나 녹화가 가능한 수준)</li>
<li>심즈, 문명 같은 게임 (일단 심즈가 돌아가면 좋겠다)</li>
</ul>
<p>정도 였다.</p>
<p>예산은 되도록이면 200을 넘어가지 않는 수준이면 좋겠는데, 거기 딱 맞는 게 <code>갓성비</code>라고 불리는 <code>맥북 에어 M1</code>이었다. </p>
<p>영상 녹화를 할 수 있어야 하니 그래픽을 8코어로 업그레이드 하고, 파이널컷을 공부하고 싶어서, 같이 결제한다 해도 200이 넘지 않는 <em>놀라운 가격!!!</em> (교육할인 적용 시)</p>
<p>그렇게 나는 애플 교육 스토어에서, 맥북에어M1(8코어)를 주문하기에 이른다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Branch & Merge]]></title>
            <link>https://velog.io/@hailey_dev/Branch-Merge</link>
            <guid>https://velog.io/@hailey_dev/Branch-Merge</guid>
            <pubDate>Wed, 28 Jul 2021 04:03:33 GMT</pubDate>
            <description><![CDATA[<h2 id="git---branch--merge">Git - Branch &amp; Merge</h2>
<h3 id="branch란">Branch란</h3>
<p>같은 뿌리를 가지고 있으나 서로 다른 길을 걸어가고 있는 파일들
같은 파일 이라면 알아서 Git에서 병합을 해주지만
파일 내용이 다를 경우에는 충돌(conflict)이 발생</p>
<blockquote>
<p>ex) 고객사마다 다른 내용을 추가해야 할 때 사용</p>
</blockquote>
<h3 id="명령어--단어정리">명령어 / 단어정리</h3>
<p><code>git branch</code> : 브랜치 목록 보기
<code>git branch 브랜치이름</code> : <code>브랜치이름</code>의 새로운 브랜치 생성
<code>master</code> : 가장 상위 브랜치
<code>git checkout 브랜치이름</code> : <code>브랜치이름</code>의 브랜치로 이동
<code>git merge 브랜치이름</code> : 현재 내가 있는 브랜치에서 <code>브랜치이름</code> 브랜치의 파일을 병합
<code>git branch -d 브랜치이름</code> : <code>브랜치이름</code>을 삭제</p>
<h3 id="merge란">merge란</h3>
<p>서로 다른 브랜치를 병합 하는 것
같은 파일임에도 서로 다른 위치가 수정되었다면, 정상적으로 병합됨
같은 파일에 같은 위치를 수정했을 경우에는 문제가 발생</p>
<h3 id="fast-forward-와-merge">Fast-Forward 와 Merge</h3>
<p>merge 명령을 했을 경우에 수행되는 병합 스타일은 크게 둘로 나뉜다.
<img src="https://images.velog.io/images/hailey_dev/post/9a66d510-d77e-4350-bcb6-a98181fdfde3/merge01.png" alt="">
master에 checkout 한 상태로 hotfix를 merge 하는 경우
<img src="https://images.velog.io/images/hailey_dev/post/f08a2def-b107-4cdf-bab9-620785ce19d7/merge02.png" alt="">
master에 checkout 한 상태로 iss53을 merge하는 경우</p>
<ol>
<li><code>fast-forward</code> :  첫번째 그림에서처럼 hotfix의 C4는 master의 C2에 기반한 커밋이기 때문에, 별도의 merge 과정 없이 그냥 최신 커밋으로 이동한다. (커밋을 생성하지 않음) 이런 방식이 바로 <code>fast-forward</code> 이다.</li>
<li><code>3 way merge</code> : 두번째 그림에서처럼 iss53의 C5는 master의 C4와는 아무런 영향이 없는 커밋이기 때문에, fast-forward가 아닌  <code>3 way merge</code>가 수행되게 된다. (merge commit이 생성됨)</li>
</ol>
<h3 id="3-way-merge--conflict">3 WAY MERGE &amp; Conflict</h3>
<p><code>base</code>(branch들의 공통된 조상)와 나머지 2개의 branch를 비교하여 수정된 부분을 채택한다
즉, 2 way merge보다 훨씬 더 많은 부분을 자동화해서 병합할 수 있다
<img src="https://images.velog.io/images/hailey_dev/post/09ffd925-563d-47bc-a0a9-aadefb292900/merge03.png" alt="">
<code>3 Way Merge</code> 를 더 자세히 살펴보면, 위 그림과 같이 수행된다.
병합해야 할 2개의 별도의 커밋이 가지고 있는  공통된 조상 을 찾은 후, 결과를 저장할 별도의 커밋(merge commit)을 생성하여 병합을 수행한다</p>
<h3 id="conflict가-났을-때-수동으로-수정하기">Conflict가 났을 때, 수동으로 수정하기</h3>
<p><code>git merge 브랜치명</code> 으로 명령 했을 때, 서로 같은 부분을 수정했다면 충돌이 일어나 
자동으로 merge가 불가능 하다.
(이 경우에는 merge commit 또한 생성되지 않는다)
그럴 때는 git이 자동으로 해당 브랜치에 있는 파일을 아래와 같이 바꿔준다
<img src="https://images.velog.io/images/hailey_dev/post/7d540b61-bee3-4b76-87ab-769dce334f10/merge04.png" alt="">
<code>nano 파일명</code> 혹은 <code>vim 파일명</code> 으로 파일을 열어서 git이 표시해준 수정사항 내용을 보고 직접 수정해준다
수정 후에는 <code>git add 파일명</code> 으로 파일을 업로드 해 준 후, <code>git commit</code> 을 해주면,
<img src="https://images.velog.io/images/hailey_dev/post/094cb16a-7c9b-4f71-85c2-fa0c8c0f6b83/merge05.png" alt="">
다음과 같이 Merge 된 파일이 정상적으로 commit 된 것을 확인할 수 있다</p>
<h3 id="3-way-merge-tool">3 Way Merge Tool</h3>
<p>대표적으로 <code>p4merge</code> 라는 툴이 있으며, 다운받아서 머지툴로 설정해주면 머지할 때 좀 더 편리하게 툴을 이용하여 할 수 있다
<a href="https://youtu.be/ZVTtAOdHUGo">관련 생활코딩 영상 보기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[First Post]]></title>
            <link>https://velog.io/@hailey_dev/First-Post</link>
            <guid>https://velog.io/@hailey_dev/First-Post</guid>
            <pubDate>Wed, 28 Jul 2021 03:48:55 GMT</pubDate>
            <description><![CDATA[<h3 id="던져놓았던-블로그를-다시-시작하는-이유">던져놓았던 블로그를 다시 시작하는 이유</h3>
<p>블로그를 운영하는 것은 여러모로 귀찮은 일이다.
주기적으로 업데이트도 해야하고, 구독자 수나 클릭 수에 신경을 쓴다면 사람들의 이목을 끌만한 토픽도 늘 찾아야 한다.</p>
<p>어렸을 때는 일기장 대용으로, 일상 기록을 중심으로 열심히 블로그를 했었다. 그러면서 나이가 들고, 활자로 뭔가를 기록하는 것에 무뎌지면서 블로그도 잘 쓰지 않게 되었던 것 같다.</p>
<p>그랬던 내가 다시 한 번 새로운 플랫폼에서 블로그를 시작해 보려는 이유는 딱 한 가지다.</p>
<p>개발 공부를 시작하면서, 여러 언어와 정보들을 한 번에 정리하고 공유할 만한 플랫폼이 필요하다고 느꼈기 때문이다. 
실제로 공부를 해 나가면서, 여러 블로그에 있는 글들이 정말 많은 도움이 된다. 비록 이제 공부 3주차인 초보지만, 나와 같은 어려움(?)을 가진 누군가에게 도움이 되길 빌며, 첫 포스팅을 작성해본다.</p>
<p>일단은 현재 공부하고 있는 <code>java</code>, <code>html</code>, <code>css</code>, <code>javascript</code> 위주로 중구난방으로 포스팅을 하게 될 것 같다.</p>
<p>꾸준히 업로드가 가능하길 빌며... :)</p>
]]></description>
        </item>
    </channel>
</rss>