<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>tenacious_mzzz.log</title>
        <link>https://velog.io/</link>
        <description>매일매일 성장하기 : )</description>
        <lastBuildDate>Sun, 19 Mar 2023 23:54:42 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. tenacious_mzzz.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/tenacious_mzzz" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Java] BufferedReader, InputStreamReader 의미]]></title>
            <link>https://velog.io/@tenacious_mzzz/Java-BufferedReader-InputStreamReader-%EC%9D%98%EB%AF%B8</link>
            <guid>https://velog.io/@tenacious_mzzz/Java-BufferedReader-InputStreamReader-%EC%9D%98%EB%AF%B8</guid>
            <pubDate>Sun, 19 Mar 2023 23:54:42 GMT</pubDate>
            <description><![CDATA[<h1 id="문자-인코딩">문자 인코딩</h1>
<h2 id="아스키-코드">아스키 코드</h2>
<ul>
<li>7bit가 만들어 낼 수 있는 이진수 조합을 문자와 대응한 것</li>
<li>2^7 = 128가지의 표현이 가능하다.</li>
<li>세계 각국의 문자 표현은 불가능</li>
</ul>
<h2 id="유니코드">유니코드</h2>
<h3 id="ucs-2문자표">UCS-2(문자표)</h3>
<ul>
<li>16bit 고정폭으로 문자 표현</li>
<li>2^16 = 65536가지의 표현이 가능하다.</li>
<li>전 세계 문자를 담기엔 아직도 부족함</li>
<li>32bit로 늘리려고 했으나 하나의 문자를 표현하기엔 메모리를 너무 많이 차지함</li>
</ul>
<blockquote>
<p>인코딩 ? 문자표가 더 이상 수용하지 못하는 문자들을 수용하기 위한 여러가지 시도들</p>
</blockquote>
<h3 id="utf-16">UTF-16</h3>
<ul>
<li>16bit 유지하는 대신 언어판을 17개로 늘린 것</li>
<li>2^16 * 17가지의 문자 표현이 가능</li>
<li>BMP(기본언어판) : 가장 맨 앞에 위치, 가장 자주 사용하는 것</li>
<li>16bit를 고정적으로 사용하기 때문에 영어,숫자 표현할 때 메모리 공간 비효율적</li>
<li>한글은 2byte차지</li>
<li><strong>Java의 JVM은 문자열을 메모리에 저장할 떄 해당 인코딩 방식을 사용</strong></li>
</ul>
<h3 id="utf-8">UTF-8</h3>
<ul>
<li>7bit 표현 가능한 문자를 7bit로 표현</li>
<li>한글은 3byte차지</li>
</ul>
<h2 id="jvm의-인코딩-방식">JVM의 인코딩 방식</h2>
<ul>
<li>UTF-16을 사용</li>
<li>다양한 문자가 사용되는 공간이면 메모리 효율과 UTF-8 임의 접근에 비효율적이기 때문<ul>
<li>UTF-8인코딩은 헤더규칙을 고려하고 유니코드 문자표로 접근할 수 있음</li>
<li>UTF-16은 바로 접근 가능<h1 id="stream">Stream</h1>
</li>
</ul>
</li>
<li>문자 --인코딩--&gt; 이진수</li>
<li>데이터 = 이진수의 나열</li>
<li>스트림 = 이진수의 흐름</li>
<li>바이트 단위로 이진수의 흐름을 읽어들임</li>
<li>UTF-16인코딩 방식으로 바꾸는 것을 InputStreamReader가 한다.<h2 id="스트림의-종류">스트림의 종류</h2>
<code>InputStream</code>, <code>OutputStream</code>을 쓰면 <strong>바이트 스트림</strong>
<code>Reader</code>, <code>Writer</code> 쓰면 <strong>문자 스트림</strong>
<code>System.in</code>, <code>System.out</code> 은 Stream객체이고 기반스트림이다.
<code>BufferedInputStream</code>, <code>BufferedOutputStream</code> 은 보조스트림이고 입출력 속도 향상 때문에 쓴다.
입출력 속도 향상?
<code>BufferedInputStream</code>은 기반 스트림이 읽어 온 스트림 데이터를 내부버퍼에 저장한다. 입력버퍼에서 데이터를 받아야하는데, 프로그램 입출력 속도와 입력버퍼의 입출력 속도는 다르다. 그래서 둘 사이에 완충지대로 내부 버퍼를 놓는다면 입출력에 지연이 생겨도 내부 버퍼 안에 데이터가 미리 대기하고 있어서 지연 발생 없이 속도가 향상된다. 
<code>프로그램&lt;-내부버퍼(BufferedInputStream)&lt;-입력버퍼(기반스트림)</code> </li>
</ul>
<h1 id="inputstreamreader">InputStreamReader</h1>
<p>Java 레퍼런스를 참고해보면, 다음과 같이 쓰여있다.  </p>
<p><img src="https://velog.velcdn.com/images/tenacious_mzzz/post/de811cce-ffbe-4e91-85c5-1e0be0105205/image.png" alt=""></p>
<ul>
<li>byte stream에서 character stream으로 바꾸기 위한 다리 역할</li>
<li>bytes를 읽고 정의된 <code>charset</code>을 사용해서 character로 디코드한다.</li>
</ul>
<p><code>BufferedReader in
   = new BufferedReader(new InputStreamReader(System.in));</code>
는 효율성 top.</p>
<p>참고</p>
<ul>
<li><a href="https://lordofkangs.tistory.com/85">문자 인코딩이란?</a> </li>
<li><a href="https://stackoverflow.com/questions/36236364/why-java-char-uses-utf-16">Why java char uses utf16</a></li>
<li><a href="https://lordofkangs.tistory.com/87?category=868253">Stream이란?</a> </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[GitLab to GitHub mirroring]]></title>
            <link>https://velog.io/@tenacious_mzzz/GitLab-to-GitHub-mirroring</link>
            <guid>https://velog.io/@tenacious_mzzz/GitLab-to-GitHub-mirroring</guid>
            <pubDate>Sun, 26 Feb 2023 03:54:15 GMT</pubDate>
            <description><![CDATA[<p>GitLab에서 작업을 하다가 GitHub으로 저장소를 옮기고 싶을 때 <code>mirroring</code>을 사용한다.</p>
<h3 id="gitlab---github으로-미러링하면">GitLab -&gt; GitHub으로 미러링하면...</h3>
<ul>
<li>잔디가 옮겨서 심어진다.</li>
<li>Issue나 PR은 안 옮겨진다.</li>
</ul>
<h3 id="어떻게-옮기는가">어떻게 옮기는가</h3>
<ol>
<li>GitLab의 repository를 clone한다.</li>
<li><code>--mirror</code>를 사용해서 미러링한다.<pre><code class="language-bash">git push --mirror https://github.com/mjseok/SHabit.git</code></pre>
</li>
</ol>
<h2 id="error발생">Error발생</h2>
<h3 id="문제">문제</h3>
<p>100메가가 넘는 파일이 생겨서 mirroring이 불가함</p>
<h3 id="원인">원인</h3>
<p>GitHub에 올리는 파일 하나당 100MB의 제한이 있다.</p>
<h3 id="해결방법">해결방법</h3>
<ol>
<li>옮길 저장소를 아래와 같은 방법으로 clone한다(bare clone)<pre><code>git clone --mirror 옮길 저장소</code></pre>예시)<pre><code>git clone --mirror https://github.com/mjseok/SHabit.git</code></pre></li>
<li>필요한 GLF랑 BFG Repo Cleaner 설치</li>
</ol>
<ul>
<li><a href="https://git-lfs.com/">Git Large File Storage</a> </li>
<li><a href="https://rtyley.github.io/bfg-repo-cleaner/">BFG Repo Cleaner</a></li>
</ul>
<ol start="3">
<li>BFG Repo Cleaner에서 설치한 <code>bfg-버전정보.jar</code>파일을 git폴더 바로 상위 폴더로 옮긴다.(아래 처럼)
<img src="https://velog.velcdn.com/images/tenacious_mzzz/post/4d5bf605-1acf-47d3-a5bc-2e5184780376/image.png" alt=""></li>
<li>100M보다 큰 파일들을 커밋이력에서 지워준다.<pre><code>java -jar bfg-1.14.0.jar --strip-blobs-bigger-than 100M [bare clone한 저장소 이름]</code></pre>예시)<pre><code>java -jar bfg-1.14.0.jar --strip-blobs-bigger-than 100M SHabit.git</code></pre>위처럼 해주면, 100M가 넘는 파일들을 커밋에서 삭제해준다.</li>
<li>GitHub으로 옮길 저장소 위치로 이동한다.<pre><code>cd [bare clone한 저장소 이름]</code></pre>예시)<pre><code>cd SHabit.git</code></pre></li>
<li>실제로 원하지 않는 데이터를 삭제하는 명령어 <code>git-gc</code>를 사용해서 변경사항을 반영합니다.<pre><code>git reflog expire --expire=now --all &amp;&amp; git gc --prune=now --aggressive</code></pre></li>
</ol>
<ul>
<li>BFG로는 커밋,브랜치,태그는 업데이트 하지만, 실제 파일이 삭제되거나 변경되지는 않는다. 로컬에서 원하지 않는 데이터를 삭제하려면 위의 명령어를 통해 적용해야 합니다.</li>
</ul>
<ol start="7">
<li>옮길 저장소로 push합니다.<pre><code>git push --mirror &lt;git 저장소&gt;</code></pre></li>
</ol>
<h2 id="참고">참고</h2>
<ul>
<li>민감한 정보를 지우고 싶을 때도 bfg를 사용할 수 있습니다.(참고 블로그 확인)</li>
<li>해당 글은 아래의 블로그들을 참고 했습니다.<ul>
<li><a href="https://rexiann.github.io/2020/11/26/mirroring-failed-due-to-large-file.html">100메가가 넘는 파일로 인해 gitlab의 저장소를 github에 미러링이 불가능 할때</a></li>
<li><a href="https://www.lesstif.com/gitbook/bfg-repo-cleaner-git-repository-129007840.html">bfg-repo-cleaner 로 git repository 에 올린 민감한 정보 삭제하기</a></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java]Wrapper class란]]></title>
            <link>https://velog.io/@tenacious_mzzz/JavaWrapper-class%EB%9E%80</link>
            <guid>https://velog.io/@tenacious_mzzz/JavaWrapper-class%EB%9E%80</guid>
            <pubDate>Fri, 24 Feb 2023 00:31:31 GMT</pubDate>
            <description><![CDATA[<h1 id="java-wrapper-class">Java Wrapper class</h1>
<p>⚠ Wrapper Class를 알기 전에 알고 있어야 할 것</p>
<ul>
<li>기본형 변수는 Call by value(값에 의한 변경)</li>
<li>객체는 Call by Reference(참조에 의한 변경)</li>
</ul>
<h2 id="wrapper-class란">Wrapper class란?</h2>
<p><code>java.lang</code>패키지의 클래스들 중 기본형 변수(primitive type)를 감싸는 클래스들이다.
<img src="https://i.imgur.com/I3ORLpL.png" alt=""></p>
<h2 id="wrapper-class의-필요성">Wrapper class의 필요성</h2>
<ol>
<li><p>기본 타입의 데이터를 객체로 취급해야 할 때 필요하다.</p>
<ul>
<li>메서드에 전달된 인수를 수정할 경우</li>
<li>메서드의 인수로 객체 타입만이 요구될 경우</li>
</ul>
</li>
<li><p>java.util패키지의 클래스들은 참조형 변수(객체)만을 다루기 때문</p>
</li>
<li><p>ArrayList와 같은 Collection Framework의 데이터 구조는 객체만(참조형 변수만)을 다루기 때문</p>
</li>
<li><p>멀티쓰레딩에서 동기화를 지원하려면 참조형 변수가 필요</p>
</li>
</ol>
<h2 id="박싱--언박싱">박싱 &amp; 언박싱</h2>
<p>Wrapper Class는 산술 연산을 위해 정의된 클래스가 아니므로, 외부에서 인스턴스에 저장된 값을 변경할 수 없고 값을 참조하기 위해 새로운 인스턴스를 생성하고 생성된 인스턴스의 값만을 참조할 수 있다.</p>
<ul>
<li>박싱 : 기본타입의 데이터를 래퍼 클라스의 인스턴스로 변환하는 과정</li>
<li>언박싱: 래퍼 클래스의 인스턴스에 저장된 값을 다시 기본 타입의 데이터로 꺼내는 과정</li>
<li>JDK 1.5부터는 자바 컴파일러가 자동으로 이를 처리 해줌(오토박싱, 오토언방식)
예시</li>
</ul>
<pre><code class="language-java">Integer num = new Integer(17); // 박싱

int n = num.intValue();        // 언박싱

System.out.println(n); //출력:17



Character ch = &#39;X&#39;; // Character ch = new Character(&#39;X&#39;); : 오토박싱

char c = ch;        // char c = ch.charValue();           : 오토언박싱

System.out.println(c);//출력: X</code></pre>
<h2 id="더-알아보기">더 알아보기</h2>
<pre><code class="language-java">Integer x = 17, y = 17;
        if (x == y)
            System.out.println(&quot;Same&quot;);
        else
            System.out.println(&quot;Not Same&quot;);</code></pre>
<pre><code class="language-java">Integer x = new Integer(17), y = new Integer(17);
        if (x == y)
            System.out.println(&quot;Same&quot;);
        else
            System.out.println(&quot;Not Same&quot;);</code></pre>
<p>위의 두 예시 모두 서로 다른 객체를 참조하기 때문에 Not Same이 나온다.</p>
<p>하지만,</p>
<pre><code class="language-java">Integer x = new Integer(17), y = new Integer(17);
        if (x.intValue() == y.intValue())
            System.out.println(&quot;Same&quot;);
        else
            System.out.println(&quot;Not Same&quot;);</code></pre>
<p>위의 예시는 intValue()로 언박싱해서 기본 참조형(int)의 데이터를 꺼내서 비교하기 때문에 Same이 나온다.</p>
<pre><code class="language-java">Integer x = new Integer(17), y = new Integer(17);
        if (x.equals(y))
            System.out.println(&quot;Same&quot;);
        else
            System.out.println(&quot;Not Same&quot;);</code></pre>
<p>위의 예시는 <code>==</code> 와 <code>equals()</code>의 차이를 알고 있으면 좋다.
<code>==</code>연산자는 비교하고자 하는 두 개의 대상의 주소값을 비교한다.
equals메소드는 비교하고자 하는 두 개의 대상의 값 자체를 비교한다.</p>
<h2 id="오토박싱-오토-언박싱">오토박싱, 오토 언박싱</h2>
<pre><code class="language-java">Integer num = new Integer(17); //래퍼 클래스1
        Integer num2 = new Integer(17); //래퍼 클래스2
        int i = 17; //기본타입

        System.out.println(&quot;래퍼클래스 == 기본타입 : &quot;+(num == i)); //true
        System.out.println(&quot;래퍼클래스.equals(기본타입) : &quot;+num.equals(i)); //true
        System.out.println(&quot;래퍼클래스 == 래퍼클래스 : &quot;+(num == num2)); //false
        System.out.println(&quot;래퍼클래스.equals(래퍼클래스) : &quot;+num.equals(num2)); //true
    }
}</code></pre>
<p>Wrapper클래스와 기본 자료형의 비교에 ==,equals 둘 다 가능한 이유는 컴파일러가 자동으로 오토언박싱을 해주기 때문이다.</p>
<p>Wrapper class내의 equals메서드가 정의된 부분을 보면 알 수 있다.</p>
<pre><code class="language-java">public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }</code></pre>
<p>Wrapper Class안에는 오토박싱을 도와주는 캐시가 있다.</p>
<pre><code class="language-java">private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty(&quot;java.lang.Integer.IntegerCache.high&quot;);
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k &lt; cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high &gt;= 127;
        }

        private IntegerCache() {}
    }
</code></pre>
<p>-&gt; Integer인스턴스를 미리 생성하고 있음</p>
<pre><code class="language-java">  public static Integer valueOf(int i) {
        if (i &gt;= IntegerCache.low &amp;&amp; i &lt;= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }</code></pre>
<p>위의 코드를 보면 캐싱된 값을 사용하고 있다는 것을 알 수 있다.</p>
<h3 id="참고">참고</h3>
<p><a href="https://velog.io/@doxxx93/Wrapper-Class%EB%9E%80">https://velog.io/@doxxx93/Wrapper-Class%EB%9E%80</a>
<a href="http://www.tcpschool.com/java/java_api_wrapper">http://www.tcpschool.com/java/java_api_wrapper</a>
<a href="https://sudo-minz.tistory.com/93">https://sudo-minz.tistory.com/93</a>
<a href="https://applefarm.tistory.com/145">https://applefarm.tistory.com/145</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring문서 - Core(Resuorce) 2]]></title>
            <link>https://velog.io/@tenacious_mzzz/Spring-Resources2</link>
            <guid>https://velog.io/@tenacious_mzzz/Spring-Resources2</guid>
            <pubDate>Sun, 15 Jan 2023 07:36:35 GMT</pubDate>
            <description><![CDATA[<p><em>2.4~2.6</em></p>
<h1 id="resourceloader-interface"><code>ResourceLoader</code> Interface</h1>
<p>[문서]<br><code>Resource</code> 인스턴스를 반환 할 수 있는 객체를 의미한다.
모든 application context는 <code>ResourceLoader</code>인터페이스를 구현할 수 있다. 즉, 어떤 application context를 사용해도 <code>Resource</code>인스턴스를 얻을 수 있다.</p>
<pre><code class="language-java">public interface ResourceLoader {

    Resource getResource(String location);

    ClassLoader getClassLoader();
}</code></pre>
<p>##</p>
<p>어떤 application context의 <code>getResource()</code>를 호출할 때 파라미터로 제공하는 location path에 적절한 prefix가 없으면 적합한 <code>Resource</code>타입을 리턴하게 된다.</p>
<p>예시)</p>
<pre><code class="language-java">Resource template = ctx.getResource(&quot;some/resource/path/myTemplate.txt&quot;);</code></pre>
<p>이 코드가 <code>ClassPathXmlApplicationContext</code>에서 실행되면 <code>ClassPathResource</code>가 리턴되고 <code>FileSystemXmlApplicationContext</code>에서 실행되면 <code>FileSystemResource</code>를 리턴한다. <code>WebApplicationContext</code>인스턴스라면 <code>ServletContextResource</code>를 리턴한다.</p>
<ol>
<li>특정 어플리케이션 컨텍스트에 적합한 방식으로 알아서 리소스를 로드할 수 있다.</li>
<li>prefix를 사용하면 해당 리소스를 리턴하도록 강제할 수도 있다.<br>ex) <code>classpath:</code>이라는 prefix를 사용하면 어플리케이션 컨텍스트 타입과 상관없이 <code>ClassPathResource</code>를 리턴할 수 있다.</li>
</ol>
<pre><code class="language-java">Resource template = ctx.getResource(&quot;classpath:some/resource/path/myTemplate.txt&quot;);
//classpath:로 resource를 강제시킴
Resource template = ctx.getResource(&quot;file:///some/resource/path/myTemplate.txt&quot;);
Resource template = ctx.getResource(&quot;https://myhost.com/resource/path/myTemplate.txt&quot;);</code></pre>
<h1 id="resourcepatternresolver-interface"><code>ResourcePatternResolver</code> Interface</h1>
<p>[문서]</p>
<ul>
<li><code>ResourceLoader</code>인터페이스를 확장한 것</li>
<li>목적 : location pattern 을 읽고 <code>Reource</code>객체로 해석하기</li>
</ul>
<pre><code class="language-text">❓ location pattern : *,**,?와 같은 특수문자를 이용한 경로 표현
대부분의 URL Mapping설정은 Ant Pattern으로 한다.
예시 ) &quot;/member/*.jsp&quot;</code></pre>
<pre><code class="language-java">public interface ResourcePatternResolver extends ResourceLoader {

    String CLASSPATH_ALL_URL_PREFIX = &quot;classpath*:&quot;;
    // class path에서 일치하는 모든 리소스를 의미하는 prefix를 정의
    Resource[] getResources(String locationPattern) throws IOException;
}</code></pre>
<p><code>PathMathcingResourcePatternResolver</code>는 <code>ApplicationContext</code>외부에서 사용할 수 있는 standalone(독립적인) 구현체입니다.<br><code>Resource[]</code> bean 프로퍼티를 채워넣기 위해 <code>ResourceArrayPropertyEditor</code>에서도 사용한다.<br><code>PathMathcingResourcePatternResolver</code>는 지정된 리소스 경로를 일치하는 하나 이상의 <code>Resource</code>객체들을 정할 수 있다. -&gt; source path는 대상 <code>Resource</code>에 대한 일대일 매핑가능한 경로를 쓰거나 <code>classpth:*</code>처럼 prefix를 쓰거나 또는 ant style로 작성하면 된다.
사용 예시)</p>
<pre><code class="language-java">PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
resource = resolver.getResource(&quot;file:pom.xml&quot;);</code></pre>
<p>파일시스템 파일을 가져올 때 prefix로 <code>file:</code>을 사용했고 현재 사용자 경로 아래의 <code>pom.xml</code>파일을 가져오는 코드입니다.</p>
<h1 id="resourceloaderaware-인터페이스"><code>ResourceLoaderAware</code> 인터페이스</h1>
<ul>
<li><code>ResourceLoader</code>를 제공받을 것으로 예상되는 구성요소를 식별하는 callback interface이다.</li>
</ul>
<pre><code class="language-java">public interface ResourceLoaderAware {

    void setResourceLoader(ResourceLoader resourceLoader);
}</code></pre>
<p><code>ApplicationContext</code>는 <code>ReourceLoader</code>이기 때문에 bean은 <code>ApplicationContextAware</code>를 구현할 수 있고 resource를 load할 수 있다.<br>하지만, 일반적으로 <code>ResourceLoader</code>인터페이스를 사용하는 것이 좋다.(why? resource로딩 인터페이스와만 관련이 있고 ApplicationContext인터페이스와는 관련없이 하는 것이 좋다.)</p>
<p>[정리]</p>
<h3 id="resourceloader"><code>ResourceLoader</code></h3>
<ul>
<li>자원을 가져오는 클래스들이다.</li>
<li><code>getResource()</code>를 사용하면 하나의 Resource를 얻는다.</li>
<li>모든 ApplicationContext들은 이 인터페이스를 구현하고 있기 때문에 <code>Resource</code>들을 가져오는 기능을 가지고 있다.</li>
</ul>
<h3 id="resourcepatternresolver"><code>ResourcePatternResolver</code></h3>
<ul>
<li><code>ResourceLoader</code>의 확장판</li>
<li>패턴에 맞는 Resource들을 전부 가져올 수 있다.</li>
<li>모든 ApplicationContext에 있는 ResourceLoader 구현체들은 사실 이 인터페이스를 구현하고 있다.</li>
</ul>
<h3 id="resourceloaderaware"><code>ResourceLoaderAware</code></h3>
<ul>
<li>다른 클래스가 context내에 있는 ResourceLoader를 사용하고 싶을 때 이를 구현하면 된다.</li>
<li>`resourceLoader를 아는(Aware)상태가 된다.</li>
<li>Context에 Bean으로 등록되어야 하니까 Component로 등록되어야 한다.</li>
<li>Context가 <code>ResourceLoaderAware</code>를 구현한 클래스에 넣어준다.(Context 자체가 ResourceLoader를 구현한 구현체)</li>
</ul>
<p>즉,<br>스프링은 Resource를 사용하는 클래스를 ResourceLoader로 지정해줘야하고 이에 또 확장 기능을 하는 ResourcePatternResolver를 만들고 이것을 다른 클래스에서 사용하도록 ResourceLoaderAware라는 클래스를 만듦</p>
<pre><code class="language-text">파일을 다른 이름으로 =&gt; Resource
파일을 가져온다 =&gt; ResourceLoader
그것을 전략적으로 더 세분화 시킨다 =&gt; ResourcePatternResolver
파일을 가져오는 것을 데려온다 =&gt; ResourceLoaderAware</code></pre>
<p>-&gt; 객체지향 프로그래밍을 위한 것<br>-&gt; 책임을 최대한 조각내는 것</p>
<h2 id="참고">참고</h2>
<p><a href="https://appleg1226.tistory.com/26">스프링 Core 문서 읽고 정리하기 - 2. Resource ~ 5. Aop</a>
<a href="https://wbluke.tistory.com/65">[RTFM] Spring Core - 02. Resources</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring문서 - Core(Resuorce)]]></title>
            <link>https://velog.io/@tenacious_mzzz/Spring%EB%AC%B8%EC%84%9C-CoreResuorce</link>
            <guid>https://velog.io/@tenacious_mzzz/Spring%EB%AC%B8%EC%84%9C-CoreResuorce</guid>
            <pubDate>Sun, 18 Dec 2022 02:18:46 GMT</pubDate>
            <description><![CDATA[<p><a href="https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources">공식문서</a></p>
<h2 id="spring의-resource란">Spring의 <code>Resource</code>란?</h2>
<p>[문서]
<code>java.net.URL</code> 클래스는 모든 low-level resource까지 접근 할 수 없다. 이런 한계를 넘어서기 위해서 스프링에서 추가로 구현한 것이며, Resource에 대한 접근을 추상화하기 위한 인터페이스이다.</p>
<ul>
<li><p><code>java.net.URL</code>을 Resource로 감싸서 추상화 한다.</p>
</li>
<li><p><code>org.springframework.core.io</code> 패키지에 속해 있다.</p>
<p>[정리]
<code>java.net.URL</code>은 class path기준으로 리소스를 읽어올 수 없다.
class path?<br>JVM이 프로그램을 실행할 때 클래스 파일을 찾는 데 기준이 되는 파일 경로(<code>.class</code>파일이 포함된 파일의 경로)
<code>java.net.URL</code> 자바를 이용하여 URL을 다루는 클래스</p>
<p>이 외에도
<code>java.net.URL</code>은 ServletContext를 기준으로 상대 경로를 읽어오는 기능이 없음<br> URL prefix를 이용해 새로운 핸들러 등록하여 URL접미사를 만들어 사용할 수 있지만 구현이 복잡하고 편의성이 없다.</p>
</li>
</ul>
<h2 id="resource-구현되어-있는-모습을-살펴보자">Resource 구현되어 있는 모습을 살펴보자.</h2>
<pre><code class="language-java">public interface Resource extends InputStreamSource {

    boolean exists();

    boolean isReadable();

    boolean isOpen();

    boolean isFile();

    URL getURL() throws IOException;

    URI getURI() throws IOException;

    File getFile() throws IOException;

    ReadableByteChannel readableChannel() throws IOException;

    long contentLength() throws IOException;

    long lastModified() throws IOException;

    Resource createRelative(String relativePath) throws IOException;

    String getFilename();

    String getDescription();
}</code></pre>
<p>참고로 <code>InputStreamSource</code>인터페이스는 다음과 같이 구현되어 있다.</p>
<pre><code class="language-java">public interface InputStreamSource {

    InputStream getInputStream() throws IOException;
}</code></pre>
<h2 id="resource-인터페이스의-주요-메서드"><code>Resource</code> 인터페이스의 주요 메서드</h2>
<p><code>exists()</code> : 리소스가 있는지 없는지 확인</p>
<p><code>isOpen()</code> : Stream이 열렸는지 확인</p>
<p><code>getDescription()</code> : 전체 경로를 포함한 파일 이름이나 실제 URL을 가져온다.</p>
<h2 id="built-in-resource-implementations">Built-in Resource Implementations</h2>
<p>Reousrce의 주요 구현체는 다음과 같다.</p>
<h3 id="urlresource">UrlResource</h3>
<ul>
<li><code>java.net.URL</code>을 wrapping한 것</li>
<li>다양한 종류의 Resource에 접근 가능하지만 기본적으로는 http, https로 원격 접근한다.</li>
<li><ul>
<li>url은 기본 프로토콜 http, https, ftp, file, jar와 같은 prefix를 지원한다.</li>
</ul>
</li>
</ul>
<h3 id="classpathresource">ClassPathResource</h3>
<ul>
<li>classpath로 부터 resource를 얻어올 때 필요.</li>
<li><code>classpath</code> prefix(접두어) 사용하면 classpath기준으로 리소스를 찾는다.</li>
</ul>
<h3 id="filesystemresource">FileSystemResource</h3>
<ul>
<li>file을 다루기 위한 것</li>
<li>filesystem기준으로 리소스를 찾는다.</li>
</ul>
<h3 id="pathresource">PathResource</h3>
<ul>
<li>Path api를 통해 <code>java.nio.file.Path</code>를 다루는 작업을 수행한다.</li>
<li>URL, File과 <code>WritableResources</code>를 다룬다.</li>
</ul>
<h3 id="inputstreamresource">InputStreamResource</h3>
<ul>
<li>다른 resource와는 다르게 already-opened 리소스이다.</li>
<li><code>isOpen()</code>메서드를 사용하면 true를 return한다.</li>
</ul>
<h3 id="bytearrayresource">ByteArrayResource</h3>
<ul>
<li>주어진 byte 배열을 구현하는 리소스</li>
<li>지정된 바이트 배열에서 contents를 load할 떄 유용하다.</li>
</ul>
<h3 id="servletcontextresource">ServletContextResource</h3>
<p>[문서]</p>
<ul>
<li>상대 웹 루트 주소내에서 상대 주소를 해석하는 <code>ServletContext</code> resource 구현체</li>
<li>Stream 접근, URL 접근이 가능하고 <code>java.io.File</code>접근도 가능하지만, 파일 접근은 리소스가 실제로 파일시스템에 있거나 웹 저장소(archive)가 확대될 때만 접근 가능하다.(java.io.File access only when the web application archive is expanded and the resource is physically on the filesystem. )
[정리]</li>
<li>웹 어플리케이션 루트에서 상대 경로로 리소스를 찾는 것</li>
<li>가장 많이 사용되는 구현체인데, 그 이유는 읽어 들이는 리소스 타입이 ApplicationContext와 관련이 있기 때문이다.</li>
</ul>
<h2 id="리소스-읽어오기">리소스 읽어오기</h2>
<p>읽어 들이는 Resource의 타입은 location문자열, ApplicationContext의 타입에 따라 결정된다.<br>즉,</p>
<pre><code>var ctx = new ClassPathXmlApplicationContext(&quot;app.xml&quot;);</code></pre><p>이 경우에는 <code>app.xml</code>을 가진 ApplicationContext의 타입이 <code>CalssPathXmlApplicationContext</code>이기 때문에 app.xml을 찾을 때 classpath를 기준으로 찾게 된다. (= ClassPathResource를 통해 빈을 찾아내거나 빈 주입을 해준다.)</p>
<p>여기서 ApplicationContext의 타입이 WebApplicationContext이하 인 경우에는 ServletContextResource를 쓰게 된다.<br>ApplicationContext의 타입에 따라 Resource의 타입이 결정된다.<br>예를 들어서, ApplicationContext의 타입이 ClassPathXmlApplicationContext이면 getResource() 메소드에 아무런 문자열을 주지 않아도 classpath 기준으로 읽어오게 된다는 뜻이다.</p>
<h2 id="참고">참고</h2>
<p><a href="https://it-mesung.tistory.com/50">[스프링 핵심] Resource 추상화</a>
<a href="https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources">스프링 문서</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[애자일 방법론]]></title>
            <link>https://velog.io/@tenacious_mzzz/%EC%95%A0%EC%9E%90%EC%9D%BC-%EB%B0%A9%EB%B2%95%EB%A1%A0</link>
            <guid>https://velog.io/@tenacious_mzzz/%EC%95%A0%EC%9E%90%EC%9D%BC-%EB%B0%A9%EB%B2%95%EB%A1%A0</guid>
            <pubDate>Sun, 27 Nov 2022 13:30:24 GMT</pubDate>
            <description><![CDATA[<h1 id="소프트웨어-개발-방법론">소프트웨어 개발 방법론</h1>
<p>소프트웨어 개발, 유지보수 등에 필요한 여러 가지 일들의 수행 방법과 이러한 일들을 효율적으로 수행하려는 과정에서 필요한 각종 기법 및 도구를 체계적으로 정리하여 표준화 한 것.</p>
<ul>
<li>목적 ? 생산성, 품질 향상</li>
<li>종류 : 구조적 방법론, 정보공학 방법론, 객체지향 방법론, 컴포넌트 기반(CBD)방법론, 애자일(Agile)방법론</li>
</ul>
<h2 id="구조적-방법론">구조적 방법론</h2>
<p>🚩point : <code>구조 중심 분석/설계</code>, <code>문서화</code>, <code>모듈화</code></p>
<ul>
<li>절차 중심의 개발 방법론</li>
<li>모듈화를 통해 기능적으로 분할하여 하향식으로 개발한다.</li>
<li>절차 : 요구사항 분석 -&gt; 구조적 분석 -&gt; 구조적 설계 -&gt; 구조적 프로그래밍</li>
</ul>
<h2 id="정보공학-방법론">정보공학 방법론</h2>
<p>🚩point : <code>자료(Data)</code></p>
<ul>
<li>정보 시스템의 개발을 위해 계획,분석,설계 ,구축에 정형화된 기법들을 상호 연관성있게 통합 및 적용하는 자료 중심의 방법론</li>
</ul>
<h2 id="객체지향-방법론">객체지향 방법론</h2>
<p>🚩point : <code>개체(entity)</code> , <code>객체(Object)</code>, <code>캡슐화</code>, <code>상속</code>, <code>다형성</code></p>
<ul>
<li>현실 세계의 개체를 기계의 부품처럼 하나의 객체로 만들어서 개발할 때 조립하듯이 객체들을 조립해서 필요한 소프트웨어 구현하는 방법론</li>
</ul>
<h2 id="컴포넌트-기반cbd">컴포넌트 기반(CBD)</h2>
<p>🚩point : <code>컴포넌트</code>. <code>재사용</code></p>
<ul>
<li>기존의 시스템, 소프트웨어를 구성하는 컴포넌트를 조합하여 새로운 어플리케이션을 만드는 방법</li>
</ul>
<h1 id="애자일-방법론">애자일 방법론</h1>
<p>🚩point : <code>요구사항</code></p>
<ul>
<li>Agile = 날렵한, 날쌘<br>고객의 요구사항 변화에 유연하게 대응할 수 있도록 일정한 주기를 반복하면서 개발 과정을 진행하는 방법론</li>
<li>요구사항이 자주 변화하는 프로젝트에 사용하는 것이 좋다. </li>
</ul>
<p><strong>잘못된 생각</strong><br><img src="https://t1.daumcdn.net/brunch/service/user/102g/image/2cNRrrRMRTnyA8zAHqmuKrbz7Zk" alt="image"> </p>
<p><strong>올바른 생각</strong><br><img src="https://t1.daumcdn.net/brunch/service/user/102g/image/7Me7XdqOa6Ys0-OMQh1XyiaMZfc.PNG" alt="image"></p>
<h2 id="절차">절차</h2>
<p><img src="https://user-images.githubusercontent.com/57527380/196162815-d0c0637a-693c-4375-b81e-41d6827f4891.png" alt="image"></p>
<p>요구사항 분석 후 우선순위가 높은 요구사항을 먼저 개발하고 개발된 부분에 대해 피드백을 받고 이를 반영해 다음 요구사항 개발에 참고하는 것을 반복하며 개발한다.</p>
<h2 id="특징">특징</h2>
<ul>
<li>고객과 개발자가 지속적으로 소통해서 변화하는 요구사항을 신속하게 수용함</li>
<li>고객의 의견을 가장 우선시함</li>
<li>팀원들과의 주기적인 회의 및 제품 시현하는 시간을 가진다.</li>
</ul>
<h2 id="장점">장점</h2>
<ul>
<li>프로젝트 계획 시간이 최소화된다.</li>
<li>점진적으로 테스트할 수 있어서 버그를 빠르게 찾을 수 있다.</li>
<li>계획, 기능 수정에 유연하다.</li>
</ul>
<h2 id="단점">단점</h2>
<ul>
<li>반복적인 유지보수 작업이 많다.</li>
<li>팀이 중심이 되는 개발방법이라서 공통 작업의 양이 많다.</li>
<li>계획이 확정된 상태로 개발하는 것이 아니라서 이해하지 못하고 진행하는 부분이 많을 수 있다.</li>
</ul>
<h2 id="종류">종류</h2>
<h3 id="칸반">칸반</h3>
<ul>
<li>게시판을 구성 방식에 따라 구간을 나누어 작업의 현재 상태와 흐름을 시각적으로 보여주는 방법</li>
<li>프로젝트의 모든 참가자가 프로젝트의 진행상태를 확인 가능</li>
<li>기본적인 구성 방식은 계획, 진행중, 완료</li>
<li>진행 중인 일의 개수를 최소한으로 제한하는 것이 중요</li>
</ul>
<h3 id="tdd">TDD</h3>
<ul>
<li>Test Driven Development(테스트 주도 개발)</li>
<li>구현 코드 작성 전에 테스트 코드를 작성한다.</li>
<li>코드의 확장성, 유지보수가 용이해진다.</li>
</ul>
<h3 id="bdd">BDD</h3>
<ul>
<li>Behavior Driven Development(행위 주도 개발)</li>
<li>테스트 케이스가 요구항이 되도록 하는 개발 방식</li>
<li>함수단위 테스트보다는 시나리오 기반의 테스트 케이스 작성</li>
</ul>
<h3 id="스크럼">스크럼</h3>
<ul>
<li>5~9명으로 구성된 소규모의 팀이 제품 개발을 하기 위해 스프린트(Sprint)를 반복한다.</li>
<li>❓스프린트 : 작업의 단위</li>
<li>❓스프린트 백로그 : 스프린트 각각의 작업 목록</li>
<li>스크럼 회의는 모든 팀원이 참가하고 짧게 진행하고 상황을 점검하는 시간</li>
</ul>
<h1 id="🙋♀️면접-질문">🙋‍♀️면접 질문</h1>
<ul>
<li>애자일 방법론은 무엇인가?</li>
<li>애자일하게 개발한 경험이 있는가?</li>
</ul>
<h2 id="출처">출처</h2>
<p><a href="https://velog.io/@munbeom/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91-Progamming">기술면접 - 애자일</a><br><a href="http://www.incodom.kr/%EC%95%A0%EC%9E%90%EC%9D%BC_%EB%B0%A9%EB%B2%95%EB%A1%A0">스크럼과 애자일</a><br><a href="https://www.samsungsds.com/kr/story/1261282_4655.html">회사에서 애자일하게 개발하는 법</a><br><a href="https://brunch.co.kr/@insuk/5">애자일이란</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Stateless vs Stateful(feat. Restful이란 무엇일까? 후속편)]]></title>
            <link>https://velog.io/@tenacious_mzzz/Stateless-vs-Statefulfeat.-Restful%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C-%ED%9B%84%EC%86%8D%ED%8E%B8</link>
            <guid>https://velog.io/@tenacious_mzzz/Stateless-vs-Statefulfeat.-Restful%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C-%ED%9B%84%EC%86%8D%ED%8E%B8</guid>
            <pubDate>Sun, 27 Nov 2022 13:27:51 GMT</pubDate>
            <description><![CDATA[<p><em><a href="https://github.com/mjseok/SSAFY_CS_Study/blob/main/Network/RESTful%EC%9D%B4%EB%9E%80.md">REST</a>에 대해 발표를 한 후 질문을 받았는데, 답을 하려고보니 내가 <code>WAS</code>, <code>stateless</code>,<code>stateful</code>에 대해 제대로 이해하지 못한 것 같아서 이를 정리해봤다.</em></p>
<h1 id="❓-question">❓ Question</h1>
<ul>
<li>일반적인(예를 들면 회원 관리하는) 웹 서비스 만드는데 REST 서버를 사용하고 싶다면 반드시 state를 관리할 수 있는 WAS도 같이 써야 하는지?</li>
</ul>
<h1 id="stateless-vs-stateful">Stateless vs Stateful</h1>
<p>상태가 있다, 없다
= 사용자나 클라이언트의 컨텍스트를 서버 쪽에서 유지한다, 안한다
= HTTP세션과 같은 컨텍스트 저장소에 상태 정보를 저장한다,안한다</p>
<h2 id="stateful">Stateful</h2>
<pre><code>Server와 Client끼리 세션의 State(상태)에 기반하여 Client에 Response를 보낸다.
이를 위해서 세션 상태를 포함한 Client와의 세션 정보를 Server에 저장한다.
이것이 Stateful하다는 것이다.</code></pre><p><strong>Stateful특성</strong></p>
<ol>
<li>세션 정보를 Server에 저장한다.</li>
<li>세션 State에 따라서 응답이 달라진다.</li>
</ol>
<p><strong>Stateful예시</strong></p>
<ul>
<li>Stateful한 구조를 가진 프로토콜은 TCP, SMTP 등등이 있다.</li>
</ul>
<h3 id="tcp">TCP</h3>
<p>그림 예시) TCP
<img src="https://user-images.githubusercontent.com/57527380/193814532-7fdbc651-3d5b-415e-b838-c0cf0974edc8.png" alt="image">
-&gt; 그림에 보이는 <code>SYN_SENT</code>, <code>LISTEN</code>, <code>ESTABLISHED</code> 등등이 여기서 말하는 <strong>&#39;상태&#39;</strong> 이다.</p>
<p>TCP는 Connection(3-handShake)을 맺고 서버가 클라이언트에 대한 정보와 상태를 유지시키고 있기 때문에 Stateful이라고 함.</p>
<p>client로부터 받은 패킷헤더를 파싱해서 앞으로 받을 데이터의 크기, sequence번호 등을 저장하는데 이 받은 크기의 데이터를 다 받을 때까지 세션을 유지하고 크기, sequence번호 등의 세션정보를 서버에 저장한다.</p>
<h3 id="smtp">SMTP</h3>
<p>SMTP -&gt; 메일 서버로 메일 보낼 때 상태를 가지고 송신자 주소, 수신자 주소, 메일 데이터 전송, 종료 등을 전송 종료 명령이 보내질 때까지 계속 유지됨</p>
<h2 id="stateless">Stateless</h2>
<pre><code>server의 응답이 client와의 세션 상태와 독립적이고 server는 단순히 요청이 오면 응답을 보내는 역할만 수행하고 서버에 저장되는 상태값이 없다.</code></pre><p><strong>Stateless특성</strong></p>
<ol>
<li>세션 정보를 Server에 저장하지 않는다.</li>
<li>세션 State와 응답은 독립적이다.</li>
</ol>
<p><strong>Stateless예시</strong></p>
<ul>
<li>Stateless 구조를 가진 프로토콜은 UDP, HTTP 등등이 있다.</li>
</ul>
<h3 id="http">HTTP</h3>
<p><img src="https://user-images.githubusercontent.com/57527380/193772744-1a1b9a9a-38ba-421d-8982-11b5c3a9d34c.png" alt="image"><br>HTTP는 통신 시 정보를 한 번씩 주고받은 후 바로 끊는 형태로 처리된다.<br> 이렇게 상태 정보를 저장하지 않는 통신형태를 stateless라고 하며, HTTTP는 대표적인 stateless 프로토콜입니다.</p>
<p>그렇기 때문에 웹 서비스에서는 상태 정보 유지를 위한 <strong>별도의 처리</strong>가 필요하다.</p>
<p>서버가 클라이언트를 식별할 수 없을 때, 식별하기 위한
<strong>별도의 처리</strong></p>
<ul>
<li>Cookie, Session 방식</li>
<li>OAuth, JWT와 같은 토큰 기반 인증 방식<br>토큰 기반 인증방식은 암호화를 해주기 때문에 보안적인 부분에서 쿠키,세션보다 더 뛰어남.</li>
<li>외부 DB에 저장<br>상태를 유지하면서 연속된 응답을 해야 할 때 쿠키라는 기술을 사용함<br>즉, http는 stateless이고 바로바로 연결을 끊기 때문에 여러 단계의 흐름을 처리 할 때 각 요청이 동일한 사용자가 보낸 것인지 다른 사용자가 보낸 것인지 판단하지 못한다.이런 경우 여러 건의 요청 처리를 동일한 사용자 접속 세션으로 인식할 수 있도록 cookie를 사용한다.</li>
</ul>
<h2 id="stateful-vs-stateless">Stateful VS Stateless</h2>
<h3 id="stateful-1">Stateful</h3>
<p><img src="https://user-images.githubusercontent.com/57527380/193823596-f694b416-3097-436c-aff5-62ede42cad0b.png" alt="image">
만약에, server1에 클라이언트의 세션정보가 저장되면 server2에는 해당 정보가 없으므로 세션인증을 처음부터 다시 해줘야하기 때문에 clientA의 요청은 server1으로 연결되도록 관리해줘야 한다.</p>
<h3 id="stateless-1">Stateless</h3>
<p><img src="https://user-images.githubusercontent.com/57527380/193823645-68373de8-07cb-4f1d-a211-88d5e494aca0.png" alt="image">
clientA의 요청이 sever1, server2 어디에 연결되더라도 DB를 통해 정보에 접근이 가능하다.</p>
<p>즉, Stateless한 구조를 따르면, Scailing이 자유롭다는 장점이 있다.<br>트래픽 급증으로 clientA가 server2로 연결된 경우 세션 정보를 다시 옮겨줘야하지만 stateless는 이런 걱정이 필요없습니다.</p>
<h1 id="was">WAS</h1>
<p><img src="https://user-images.githubusercontent.com/57527380/193819875-a494f5a5-dd67-4371-abc6-b7c045d41764.png" alt="image"></p>
<p>웹 서버와 웹 컨네이너를 합친 것으로, <strong>동적 컨텐츠</strong>를 제공하기 위해서 만들어진 Application서버입니다.<br> HTTP프로토콜을 기반으로 어플리케이션을 수행할 수 있도록 해주는 미들웨어이고 데이터베이스 서버와 같이 수행된다.<br>-&gt; DB접속 기능 제공, 여러 트랜잭션 및 비즈니스 로직 수행</p>
<h1 id="❗-answer">❗ Answer</h1>
<ol>
<li>정적 컨텐츠냐 동적 컨텐츠냐 -&gt; WAS쓰냐 마냐</li>
<li>여러 요청에 대해 사용자 식별이 필요하냐 마냐 -&gt; 따로 처리 해주냐 마냐</li>
<li>REST API -&gt; HTTP기반 -&gt; stateless -&gt; 연결 상태를 저장하지 않는다.</li>
</ol>
<p>즉, 정적 컨텐츠만 제공하는 서버일 경우에는 WAS없이 REST API 사용가능<br>REST와는 별개로 HTTP 동적 컨텐츠를 요청하면 WAS로 넘겨서 처리받고 이 결과를 WAS에게 받아서 클라이언트로 넘겨주는 것이고, 동적 컨텐츠를 사용하냐마냐와는 상관없이 여러 건의 요청을 동일한 사용자가 보내는 것인지 아닌지를 확인하기 위해서는 쿠키,세션이 필요하다</p>
<ul>
<li>그러나, 일반적으로(통상적으로) API 서버가 API형태의 WAS를 구현하는 것을 말하고 RESTful API도 API(=Application Programming Interface)이기 때문에, Restful한 API를 제공하는 것은 WAS를 개발하는 것과 같다고 볼 수 있다.</li>
</ul>
<h2 id="참고">참고</h2>
<p><a href="https://yangbongsoo.gitbook.io/study/undefined-1/rest">REST의 이해</a><br><a href="https://5equal0.tistory.com/entry/StatefulStateless-Stateful-vs-Stateless-%EC%84%9C%EB%B9%84%EC%8A%A4%EC%99%80-HTTP-%EB%B0%8F-REST">Stateless vs Stateful</a><br><a href="https://code-lab1.tistory.com/199">WebServer와 WAS</a><br><a href="https://okky.kr/articles/965447">REST API와 WAS</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Restful이란]]></title>
            <link>https://velog.io/@tenacious_mzzz/Restful%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@tenacious_mzzz/Restful%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sun, 27 Nov 2022 13:25:13 GMT</pubDate>
            <description><![CDATA[<h1 id="rest">REST</h1>
<ul>
<li><code>Representational State Transfer(대표적인 상태 전략)</code></li>
<li>웹의 장점을 최대한 활용할 수 있는 아키텍처(표준이 아니라 설계 가이드일 뿐이다.)
  why? 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하기 때문  </li>
<li>웹에 존재하는 모든 자원(이미지, 동영상, DB자원,등)에 고유한 URI를 부여해서 자원을 주고받는 것
EX) &#39;DB의 학생 정보&#39;라는 자원을 &#39;students&#39;로 표현할 수 있고 이의 상태를 주고 받는 것</li>
</ul>
<h2 id="구성요소">구성요소</h2>
<ul>
<li><p>자원(resource) : URI
  자원을 구별하는 ID는 <code>/groups/:group_id</code>와 같은 HTTP URI이고 자원은 서버에 존재한다.<br>  클라이언트는 이 URI를 이용해서 자원을 지정하고 자원의 상태에 대한 조작을 요청한다.</p>
</li>
<li><p>행위: Method
  HTTP 프로토콜의 Method를 사용<br>  프로토콜 메서드는 <code>GET</code>,<code>POST</code>,<code>PUT</code>,<code>DELETE</code>가 있다.</p>
</li>
<li><p>표현(Representation)
  클라이언트가 서버로 요청을 보냈을 때 서버가 응답으로 보내주는 자원의 상태<br>  REST에서 하나의 자원은 JSON,XML,TEXT,RSS등 여러 형태의 Representationmd로 나타낼 수 있다.<br>  JSON,XML이 일반적임  </p>
<h2 id="특징">특징</h2>
</li>
</ul>
<ol>
<li>server- client 구조</li>
<li>stateless</li>
<li>Cacheable</li>
<li>Layered System</li>
<li>자체 표현 구조</li>
<li>Uniform Interface</li>
</ol>
<h3 id="server-client-구조">Server-Client 구조</h3>
<pre><code>REST서버: API 제공, 비즈니스 로직 처리 및 저장
클라이언트: 사용자 인증, 컨텍스트(세션,로그인 정보)등을 직접 관리</code></pre><p>자원이 있는 쪽이 서버, 자원을 요청하는 쪽이 클라이언트인 구조로 역할이 확실하게 구분이 되기 때문에 클라이언트, 서버에서 개발해야 할 내용이 명확해지고 서로간의 의존성이 줄어든다.</p>
<h3 id="stateless-무상태성">Stateless 무상태성</h3>
<p>HTTP 프로토콜이 stateless 프로토콜이므로 REST 또한 무상태성을 가짐<br>상태 정보를 따로 저장, 관리하지 않는다. 즉, 세션정보나 쿠키정보를 별도로 저장 및 관리하지 않기 때문에 API서버는 들어오는 요청만 처리하면 된다.<br>-&gt; 서비스의 자유도가 높아지고 구현이 단순해진다.  </p>
<h3 id="cacheable-캐시가능">Cacheable 캐시가능</h3>
<p>HTTP가 가진 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Caching">캐싱 기능</a>이 적용 가능하다.<br>HTTP protocol 표준에서 사용하는 <code>Last-Modified 태그</code>나 <code>E-tag</code>를 이용하면 캐싱 구현이 가능<br>대량의 요청을 효율적으로 처리하기 위해 캐시가 요구된다.  </p>
<h3 id="layere-system">Layere System</h3>
<p>API 서버로 순수 비즈니스 로직을 수행하고 그 앞단에 사용자 인증, 암호화 등을 하는 계층을 추가하는 등 유연성있는
구조로 구현할 수 있다.</p>
<h3 id="자체-표현-구조">자체 표현 구조</h3>
<p>Method(동사) + URI(명사)로 이뤄져 있어서 API자체만 보고도 이해할 수 있다.</p>
<h3 id="uniform-interface-인터페이스-일관성">Uniform Interface 인터페이스 일관성</h3>
<p>URI로 지정한 자원에 대한 조작을 통일되고 한정적인 인터페이스로 수행<br>HTTP 표준 프로토콜에 따르는 모든 플랫폼에서 사용이 가능하다.(특정 언어, 기술에 따라 사용이 안되거나 바뀌는 경우가 없다.)  </p>
<h1 id="rest-api">REST API</h1>
<h2 id="api">API</h2>
<p><code>Application Programmingn Interface</code><br> 요청과 응답을 사용하여 두 애플리케이션이 서로 통신하는 방법  </p>
<h2 id="rest-api-1">REST API</h2>
<p>REST를 기반으로 서비스 API를 구현한 것  </p>
<h3 id="rest-api-설계">REST API 설계</h3>
<ol>
<li>URI는 정보의 자원을 표현해야 한다.  </li>
</ol>
<ul>
<li>resource는 동사가 아닌 <strong>명사</strong>로, 대문자보다는 <strong>소문자</strong>를 사용  </li>
</ul>
<ol start="2">
<li>자원에 대한 행위는 HTTP Method로 표현  </li>
</ol>
<ul>
<li><code>GET</code> : 조회  </li>
<li><code>PUT</code> : 수정</li>
<li><code>DELETE</code> : 삭제</li>
<li><code>POST</code> : 생성
EX) <pre><code>GET /members/delete/1 보다는
DELETE /members/1이 맞는 표현  </code></pre><h3 id="uri-규칙">URI 규칙</h3>
</li>
<li><code>/</code>는 계층 관계를 나타내는데 사용  </li>
<li>마지막 문자로 <code>/</code>를 사용하지 않는다.  </li>
<li><code>-</code>는 가독성을 높이는데 사용할 수 있다</li>
<li><code>_</code>는 URI에 사용하지 않는다</li>
<li>URI 경로에는 소문자가 적합하다</li>
<li>파일 확장자는 URI에 포함되지 않는다. </li>
</ul>
<h1 id="restful">RESTful</h1>
<ul>
<li><p><code>REST</code>라는 아키텍처를 구현하는 웹 서비스를 나타내기 위해 사용되는 용어
  즉, <code>REST API</code>를 제공하는 웹 서비스를 <code>RESTful</code>하다고 할 수 있습니다.  </p>
</li>
<li><p>목적: 이해하기 쉽고 사용하기 쉬운 REST API 만드는 것</p>
</li>
<li><p>근본 목적이 성능 향상이 아닌 api의 이해, 호환성을 높이는 것이므로, 성능이 중요한 상황에서는 굳이 RESTful한 API를 구현할 필요는 없다. </p>
</li>
</ul>
<h3 id="참고">참고</h3>
<p><a href="https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html">[Network] REST란? REST API란? RESTful이란?</a>
<a href="https://hckcksrl.medium.com/rest%EB%9E%80-c602c3324196">REST란</a>
<a href="https://meetup.toast.com/posts/92">REST API 제대로 알고 사용하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA]String vs StringBuffer vs StringBuilder]]></title>
            <link>https://velog.io/@tenacious_mzzz/JAVAString-vs-StringBuffer-vs-StringBuilder</link>
            <guid>https://velog.io/@tenacious_mzzz/JAVAString-vs-StringBuffer-vs-StringBuilder</guid>
            <pubDate>Sun, 27 Nov 2022 13:23:41 GMT</pubDate>
            <description><![CDATA[<h1 id="string-vs-stringbuffer-stringbuilder">String vs StringBuffer, StringBuilder</h1>
<h2 id="공통점">공통점</h2>
<ul>
<li>문자열을 다루는 대표적인 클래스</li>
<li>모두 String을 저장하고 관리하는 클래스</li>
</ul>
<h2 id="차이점">차이점</h2>
<table>
<thead>
<tr>
<th></th>
<th>String</th>
<th>StringBuffer</th>
<th>StringBuilder</th>
</tr>
</thead>
<tbody><tr>
<td>저장위치</td>
<td>StringPool</td>
<td>Heap</td>
<td>Heap</td>
</tr>
<tr>
<td>Modifiable</td>
<td>불변</td>
<td>가변</td>
<td>가변</td>
</tr>
<tr>
<td>thread-safe</td>
<td>O</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>동기화</td>
<td>O</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>성능</td>
<td>빠름</td>
<td>느림</td>
<td>빠름</td>
</tr>
</tbody></table>
<ul>
<li>연산이 많은 경우 성능만 보면, StringBuilder &gt; StringBuffer &gt;&gt; String
하지만, 상황에 맞게 사용하는게 좋음</li>
</ul>
<pre><code>String   :  문자열  연산이  적고  멀티쓰레드  환경일  경우

StringBuffer   :   문자열  연산이  많고  멀티쓰레드  환경일  경우

StringBuilder   :   문자열  연산이  많고  단일쓰레드이거나  동기화를  고려하지  않아도  되는  경우</code></pre><h1 id="string">String</h1>
<p>📌 <code>불변(immutable)</code> , <code>Strnig pool</code></p>
<h2 id="불변">불변</h2>
<p>불변 = 한 번 저장된 값이 절대 변하지 않는다.</p>
<pre><code class="language-java">String str = &quot;hello&quot;;
str = str + &quot;world&quot;;
System.out.println(str); //hello world</code></pre>
<p><img src="https://user-images.githubusercontent.com/57527380/199336438-1176978a-15d2-4f79-a43b-748b22b26351.png" alt="그림1"></p>
<h2 id="string-pool">String Pool</h2>
<p>String 객체 생성하는 방식은 <code>new String()</code>, <code>리터럴(&quot;&quot;)</code> 이 있다.</p>
<h3 id="string-str--new-stringhello">String str = new String(&quot;hello&quot;)</h3>
<ul>
<li>Heap영역에 메모리가 할당된다.</li>
<li>같은 문자열이라도 다른 객체이기 때문에 새로운 객체가 메모리에 할당된다.</li>
</ul>
<h3 id="string-str--hello">String str = &quot;hello&quot;</h3>
<ul>
<li>String pool에 저장</li>
<li>내부적으로 <code>intern()</code>메소드 호출된다.<br>❓ <code>intern()</code></li>
<li>주어진 문자열(&quot;hello&quot;)이 String pool에 존재하는지 확인한 후, 리터럴을 가리키는 참조를 가져오고 없으면 String pool에 리터럴을 넣고 그 주소를 가져오는 메서드</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57527380/199326368-d0387187-c435-4fc2-b156-a19cd6150ff0.png" alt="image"></p>
<pre><code class="language-java">@Test
public void stringInternTest() {
    String a = &quot;Hello&quot;;
    String b = new String(&quot;Hello&quot;);

    System.out.println(&quot;a == b ? : &quot; + (a == b)); // false
    System.out.println(&quot;a == b.intern() ? : &quot; + (a == b.intern())); // true
}</code></pre>
<p>-&gt; <code>intern()</code>메서드를 사용하면 메모리 낭비를 줄일 수 있다.</p>
<h2 id="왜-string-객체는-불변일까불변으로-얻는-장점이-뭘까">왜 String 객체는 불변일까?(불변으로 얻는 장점이 뭘까)</h2>
<ol>
<li><p>캐싱 기능에 의한 메모리 절약과 속도 향상</p>
<ul>
<li>리터럴로 생성할 경우, 같은 문자열을 여러개 생성하지 않고 string pool에 등록되어 있는 객체를 참조하기 때문</li>
</ul>
</li>
<li><p>thread-safe</p>
<ul>
<li>String 객체는 불변이기 때문에 여러 쓰레드에서 동시에 특정 String 객체를 참조하더라도 안전하다.</li>
</ul>
</li>
<li><p>보안기능</p>
<ul>
<li>중요한 데이터를 문자열로 다루는 경우 강제로 해당 참조에 대한 문자열 값을 바꾸는 것이 불가능하기 때문에 보안에 유리하다.</li>
</ul>
</li>
</ol>
<p>하지만, 문자열 추가,수정,삭제와 같은 연산이 많아지면 힙에 Garbage가 많이 생성되고 힙 메모리 부족으로 성능이 저하될 수 있다. 그래서, <code>StringBuffer</code>, <code>StringBuilder</code>클래스가 도입됨.</p>
<h1 id="stringbuffer-stringbuilder">StringBuffer, StringBuilder</h1>
<p>📌 <code>가변</code> , <code>append()</code>, <code>delete()</code> 메소드 사용</p>
<pre><code class="language-java">StringBuffer sb = new StringBuffer(&quot;hello&quot;);
sb.append(&quot;world&quot;);
</code></pre>
<p><img src="https://user-images.githubusercontent.com/57527380/199337289-d084df98-046a-4693-a395-bb49a25bdd3a.png" alt="image"></p>
<h2 id="차이점-1">차이점</h2>
<p><code>StringBuffer</code></p>
<ul>
<li>멀티쓰레드 환경에서 주로 사용(동기화(<code>synchronized</code>) 지원)</li>
<li>예시
A스레드, B스레드 모두 StringBuffer 객체의 append()메서드를 사용하려고 할 경우,</li>
</ul>
<ol>
<li>A스레드 : sb의 append()동기화 블록에 접근 및 실행</li>
<li>B스레드 : A스레드 sb의 append() 동기화 블록에 들어가지 못하고 <code>block</code>상태가 됨</li>
<li>A스레드 : sb의 append()동기화 블록에서 탈출</li>
<li>B스레드 : <code>block</code> -&gt; <code>running</code>상태로 변하고 sb의 append()접근 및 실행<br><code>StringBuilder</code></li>
</ol>
<ul>
<li>싱글 쓰레드 환경에서 주로 사용(동기화 지원x)</li>
</ul>
<pre><code class="language-java">//////////StringBuffer//////////
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

//////////StringBuilder///////////
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }</code></pre>
<h2 id="참고">참고</h2>
<p><a href="https://dev-coco.tistory.com/153#%F-%-F%--%A-%--String%-C%--StringBuffer%-C%--StringBuilder%EC%-D%--%--%EC%B-%A-%EC%-D%B-%EB%A-%BC%--%EC%--%A-%EB%AA%--%ED%--%B-%EC%A-%BC%EC%--%B-%EC%-A%---">신입 개발자 기술면접 질문 정리 - 자바</a><br><a href="https://dev-coco.tistory.com/25">[Java] String, StringBuffer, StringBuilder 차이와 장단점</a><br><a href="https://www.digitalocean.com/community/tutorials/what-is-java-string-pool">what is java String pool</a>
<a href="https://jake-seo-dev.tistory.com/17">자바스프링 풀</a>
<a href="https://velog.io/@heoseungyeon/StringBuilder%EC%99%80-StringBuffer%EB%8A%94-%EB%AC%B4%EC%8A%A8-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EC%9E%88%EB%8A%94%EA%B0%80">StringBuffer와 StringBuilder는 무슨 차이가 있는가</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Observer pattern]]></title>
            <link>https://velog.io/@tenacious_mzzz/Observer-pattern</link>
            <guid>https://velog.io/@tenacious_mzzz/Observer-pattern</guid>
            <pubDate>Sun, 27 Nov 2022 13:22:15 GMT</pubDate>
            <description><![CDATA[<h1 id="observer-pattern">Observer pattern</h1>
<ul>
<li>옵저버 패턴은 디자인 패턴 중 하나</li>
<li>주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려준다.</li>
<li>이 주체와 옵저버 사이의 연결은 인터페이스를 이용해서 느슨한 결합을 유지하며, 주체, 옵저버 인터페이스를 사용한다.</li>
</ul>
<pre><code>❓ 주체 : 객체의 상태 변화를 보고 있는 관찰자
❓ 옵저버 : 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 &#39;추가 변화 사항&#39;이 생기는 객체들을 의미.</code></pre><p>객체와 주체가 분리되어 있을 수도 있고, 합쳐져 있을 수도 있고 주체와 객체를 구분짓지 않을 수도 있다.</p>
<h3 id="객체-주체-분리-합체">[객체 주체 분리, 합체]</h3>
<p><img src="https://user-images.githubusercontent.com/57527380/189568546-5d0a9f30-1558-4d2c-85df-d7995a56897d.png" alt="image"></p>
<h3 id="주체객체-구분-x">[주체,객체 구분 x]</h3>
<p>예시 : 트위터<br>주체를 팔로우 한 사람들이 옵저버, 주체가 새로운 트윗을 올리면 옵저버들에게 알려줌.</p>
<h2 id="옵저버-패턴-구조">옵저버 패턴 구조</h2>
<ul>
<li>이벤트 기반 시스템에 사용</li>
<li>MVC패턴에도 사용된다.</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57527380/189569628-3de8601a-6f24-4914-ae22-9a59be21b00b.png" alt="image">
모델에서 변경사항이 생기면 view에 update()메서드를 통해 알려주고, controller는 이를 기반으로 동작한다.</p>
<h2 id="예시">예시</h2>
<p><a href="https://github.com/gilbutITbook/080326">코드 출처</a></p>
<h3 id="java">Java</h3>
<details>
<summary>JAVA코드</summary>

<pre><code class="language-java">/*
코드 출처 : https://github.com/gilbutITbook/080326
*/
import java.util.ArrayList;
import java.util.List;

interface Subject { //객체
    public void register(Observer obj);
    public void unregister(Observer obj);
    public void notifyObservers();
    public Object getUpdate(Observer obj);
}

interface Observer { //옵저버
    public void update();
}

class Topic implements Subject { //주체이자 객체
    private List&lt;Observer&gt; observers;
    private String message;

    public Topic() {
        this.observers = new ArrayList&lt;&gt;();
        this.message = &quot;&quot;;
    }

    @Override
    //옵저버로 등록
    public void register(Observer obj) {
        if (!observers.contains(obj)) observers.add(obj);
    }

    @Override
    //옵저버 목록에서 제거
    public void unregister(Observer obj) {
        observers.remove(obj);
    }

    @Override
    //옵저버에게 update했다고 알리기
    public void notifyObservers() {
        this.observers.forEach(Observer::update);
    }

    @Override
    //update내용 가져오기
    public Object getUpdate(Observer obj) {
        return this.message;
    }
    // 메시지 update(변화를 관찰하고 있는 부분)하고 옵저버에게 알리기
    public void postMessage(String msg) {
        System.out.println(&quot;Message sended to Topic: &quot; + msg);
        this.message = msg;
        notifyObservers();
    }
}
//옵저버(topic 구독)
class TopicSubscriber implements Observer {
    private String name;
    private Subject topic;

    public TopicSubscriber(String name, Subject topic) {
        this.name = name;
        this.topic = topic;
    }

    @Override
    //옵저버 update()메서드 -&gt; 주체,객체의 notifyObservers()를 통해 작동됨
    public void update() {
        //update된 msg받아서 출력
        String msg = (String) topic.getUpdate(this);
        System.out.println(name + &quot;:: got message &gt;&gt; &quot; + msg);
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        Topic topic = new Topic();
        Observer a = new TopicSubscriber(&quot;a&quot;, topic); //옵저버 선언
        Observer b = new TopicSubscriber(&quot;b&quot;, topic);
        Observer c = new TopicSubscriber(&quot;c&quot;, topic);
        topic.register(a);//topic의 옵저버로 등록
        topic.register(b);
        topic.register(c);

        topic.postMessage(&quot;amumu is op champion!!&quot;); //메시지가 변화함
    }
}
/*
Message sended to Topic: amumu is op champion!!
a:: got message &gt;&gt; amumu is op champion!!
b:: got message &gt;&gt; amumu is op champion!!
c:: got message &gt;&gt; amumu is op champion!!
*/</code></pre>
</details>

<p>Java에는 옵저버 패턴을 적용할 수 있는 <code>Observer</code>인터페이스와 <code>Observable</code>클래스를 기본적으로 제공해준다.<br>Observable은 클래스로 구현되어 있기 때문에 상속을 해야하고, 자바는 다중 상속이 안되기 때문에 이로 인한 한계가 있다.</p>
<h3 id="javascript">JavaScript</h3>
<p>프록시 객체를 통해 구현</p>
<pre><code>❓ 프록시 객체 : 어떤 대상의 기본적인 동작의 작업을 가로챌 수 있는 객체
자바스크립트에서 프록시 객체는 target,handler 두개의 매개변수를 가집니다.
target : 프록시할 대상
handler : 프록시 객체의 target동작을 가로채서 실행될 함수</code></pre><details>
<summary>JavaScript코드</summary>

<pre><code class="language-js">/*
target : 대상 객체
property: 설정할 속성의 이름
value: 설정할 속성의 새 값
reveiver vmfhrtl wkcp
set()메서드는 boolean 값을 반환함
*/
new Proxy(target, {
  set(target, property, value, receiver) {},
});</code></pre>
<pre><code class="language-js">/*
코드 출처 : https://github.com/gilbutITbook/080326
*/
function createReactiveObject(target, callback) {
  const proxy = new Proxy(target, {
    set(obj, prop, value) {
      //obj는 a, prop은 형규, value는 커플
      if (value !== obj[prop]) {
        const prev = obj[prop]; //prev는 솔로
        obj[prop] = value;
        callback(`${prop}가 [${prev}] &gt;&gt; [${value}] 로 변경되었습니다`);
      }
      return true;
    },
  });
  return proxy;
}
const a = {
  형규: &quot;솔로&quot;,
};
const b = createReactiveObject(a, console.log);
//b.형규 = &quot;솔로&quot;;
b.형규 = &quot;커플&quot;;
// 형규가 [솔로] &gt;&gt; [커플] 로 변경되었습니다</code></pre>
</details>
<br />

<h3 id="vuejs-30">Vue.js 3.0</h3>
<p>Vue.js 3.0에서 <code>ref</code>나 <code>reactive</code>로 정의하면 해당 값이 변경되었을 때 자동으로 DOM에 있는 값이 변경된다. 이는 프록시 객체를 이용한 옵저버 패턴을 이용하여 구현한 것</p>
<details>
<summary>Vue.js 3.0</summary>

<p>Vue.js의 옵저버 패턴이 담긴 코드<br>proxyMap이라는 프록시 객치를 사용</p>
<pre><code class="language-js">function createReactiveObject(
    target: Target,
    isReadonly: boolean,
    baseHandlers: ProxyHandler(any),
    collectionHandlers: ProxyHandler(any),
    proxyMap: WeakMap&lt;Target, any)
    ){
    if (!isObject(target)) {
        if (DEV) {
            console.warn(&quot;value cannot be made reactive: ${String(target)!&quot;)
        }
        return target
    }
    // target is already a Proxy, return it.
    // exception: calling readonly() on a reactive object
    if (
    target [ReactiveFlags.RAW] &amp;&amp;
                !(isReadonly &amp;&amp; target[ReactiveFlags.IS_REACTIVE])
    ){
    return target
    }
    // target already has corresponding Proxy
    const existingProxy = proxyMap. get (target)
    if (existingProxy) {
        return existingProxy
    }
    // only a whitelist of value types can be observed
    const targetType = getTargetType (target)
    if (targetType === TargetType.INVALID) {
        return target
    }
    const proxy = new Proxy (
    target,
    targetType=== TargetType.COLLECTION ? collectionHandlers:
            baseHandlers
    )
    proxyMap.set(target, proxy)
    return proxy
}</code></pre>
</details>

<h2 id="참고">참고</h2>
<ul>
<li>책 : 면접을 위한 CS 전공지식 노트</li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/set">js proxy</a></li>
<li><a href="https://velog.io/@haero_kim/%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4-%EA%B0%9C%EB%85%90-%EB%96%A0%EB%A8%B9%EC%97%AC%EB%93%9C%EB%A6%BD%EB%8B%88%EB%8B%A4">옵저버 패턴 개념 떠먹여드립니다 🥄</a></li>
<li><a href="https://gyoogle.dev/blog/design-pattern/Observer%20Pattern.html">옵저버 패턴(Observer pattern)</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Math vs 삼항연산자]]></title>
            <link>https://velog.io/@tenacious_mzzz/Math-vs-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@tenacious_mzzz/Math-vs-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Sun, 23 Oct 2022 07:28:40 GMT</pubDate>
            <description><![CDATA[<h2 id="문제--파티"><a href="https://www.acmicpc.net/problem/1238">문제- 파티</a></h2>
<p>백준의 파티 문제를 풀면서 플로이드 워샬 알고리즘을 사용할 때 <code>Math.max()</code>와 <code>삼항연산자</code>의 차이에 대해 알게되었다.  </p>
<h3 id="삼항연산자-or-if문-사용">삼항연산자 or if문 사용</h3>
<table>
<thead>
<tr>
<th>메모리</th>
<th>시간</th>
</tr>
</thead>
<tbody><tr>
<td>36704 kb</td>
<td>2796 ms</td>
</tr>
</tbody></table>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Boj_1238 {
    static int INF = 1_000_000_000;
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        //BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = null;
        st = new StringTokenizer(in.readLine(), &quot; &quot;);
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int X = Integer.parseInt(st.nextToken()); // 파티장소
        int[][] town = new int[N + 1][N + 1];
        for (int i = 1; i &lt;= N; i++) {
            for (int j = 1; j &lt;= N; j++) {
                if (i != j)
                    town[i][j] = INF;
            }
        }

        for (int i = 0; i &lt; M; i++) {
            st = new StringTokenizer(in.readLine(), &quot; &quot;);
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int T = Integer.parseInt(st.nextToken());
            town[start][end] = T;
        }

        for (int k = 1; k &lt;= N; k++) {
            for (int i = 1; i &lt;= N; i++) {
                for (int j = 1; j &lt;= N; j++) {
                    int tmp = town[i][k] + town[k][j];
                    //삼항연산자 사용
                    town[i][j] = town[i][j] &gt; tmp ? tmp : town[i][j];
                    //if문 사용
                    /*
                     if(town[i][j]&gt;tmp){
                        town[i][j] = tmp;
                    }
                    */
                }
            }
        }

        int answer = Integer.MIN_VALUE;
        for (int i = 1; i &lt;= N; i++) {
            answer = answer &lt; (town[i][X] + town[X][i]) ? (town[i][X] + town[X][i]) : answer;
        }
        System.out.println(answer);
    }
}</code></pre>
<h3 id="mathmin-mathmax-사용">Math.min(), Math.max() 사용</h3>
<table>
<thead>
<tr>
<th>메모리</th>
<th>시간</th>
</tr>
</thead>
<tbody><tr>
<td>24336 kb</td>
<td>1328 ms</td>
</tr>
</tbody></table>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Boj_1238 {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = null;
        st = new StringTokenizer(in.readLine(), &quot; &quot;);
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int X = Integer.parseInt(st.nextToken()); // 파티장소
        int[][] town = new int[N + 1][N + 1];
        for (int i = 1; i &lt;= N; i++) {
            for (int j = 1; j &lt;= N; j++) {
                if(i!=j)
                    town[i][j] = 1000000;
            }
        }

        for (int i = 0; i &lt; M; i++) {
            st = new StringTokenizer(in.readLine(), &quot; &quot;);
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int T = Integer.parseInt(st.nextToken());
            town[start][end] = T;
        }

        for (int k = 1; k &lt;= N; k++) {
            for (int i = 1; i &lt;= N; i++) {
                for (int j = 1; j &lt;= N; j++) {

                    town[i][j] = Math.min(town[i][j],town[i][k]+town[k][j]);

                }
            }
        }

        int answer = Integer.MIN_VALUE;
        for (int i = 1; i &lt;= N; i++) {
            answer = Math.max(town[i][X]+town[X][i], answer);
        }
        out.write(answer + &quot;&quot;);
        out.flush();
        out.close();
        in.close();
    }
}</code></pre>
<p>무려 시간이 반이나 줄었다.<br>그러나, 플로이드 워샬 알고리즘이 아닌 다른 데에서는 대부분 삼항연산자의 속도가 더 빠르다.(<a href="https://choicurly.tistory.com/20">참고</a>)
왜 플로이드 워샬 알고리즘에서는 삼항연산자에 비해 Math메서드의 속도가 더 빠른걸까?</p>
<p>Math.max()의 코드를 살펴보자</p>
<pre><code class="language-java">public final class Math{
    private Math() {}
    .
    .
    .
    /**
     * Returns the greater of two {@code int} values. That is, the
     * result is the argument closer to the value of
     * {@link Integer#MAX_VALUE}. If the arguments have the same value,
     * the result is that same value.
     *
     * @param   a   an argument.
     * @param   b   another argument.
     * @return  the larger of {@code a} and {@code b}.
     */
    public static int max(int a, int b) {
        return (a &gt;= b) ? a : b;
    }
        /**
     * Returns the smaller of two {@code int} values. That is,
     * the result the argument closer to the value of
     * {@link Integer#MIN_VALUE}.  If the arguments have the same
     * value, the result is that same value.
     *
     * @param   a   an argument.
     * @param   b   another argument.
     * @return  the smaller of {@code a} and {@code b}.
     */
    public static int min(int a, int b) {
        return (a &lt;= b) ? a : b;
    }

    .
    .
    .
}
</code></pre>
<p>... <code>Math</code>의 메서드도 내부적으로 삼항연산자로 구현되어 있다.
진짜 왜일까......? JIT컴파일러? 최적화?
<a href="https://codeforces.com/blog/entry/80834">https://codeforces.com/blog/entry/80834</a> </p>
<p>Java8버전에서는 시간 차이가 나고 Java11버전에서는 시간 차이가 나지 않고 거의 비슷했다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU 스케줄링]]></title>
            <link>https://velog.io/@tenacious_mzzz/CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81</link>
            <guid>https://velog.io/@tenacious_mzzz/CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81</guid>
            <pubDate>Sun, 11 Sep 2022 15:26:29 GMT</pubDate>
            <description><![CDATA[<h1 id="cpu-스케줄링은-무엇이고-알고리즘-종류에-대해-설명하시오">CPU 스케줄링은 무엇이고 알고리즘 종류에 대해 설명하시오.</h1>
<p>CPU 스케줄러는 CPU스케줄링 알고리즘에 따라서 프로세스에서 해야 하는 일을 스레드 단위로 CPU에 할당한다. </p>
<h1 id="cpu-스케줄링">CPU 스케줄링</h1>
<p>최고의 성능을 내기 위해서 자원을 어떤 프로세스에 얼마나 할당하는지 정책을 만드는 것
CPU 스케줄링 알고리즘의 목표는 CPU이용률은 높게, 주어진 시간에 많은 일을 하게, 준비 큐(ready queue)에 있는 프로세스는 적게, 응답 시간은 짧게 설정하는 것을 목표로 한다. </p>
<p>CPU 스케줄링 알고리즘 </p>
<ul>
<li>비선점형<ul>
<li>FCFS</li>
<li>SJF</li>
<li>우선순위</li>
</ul>
</li>
<li>선점형<ul>
<li>라운드로빈</li>
<li>SRF</li>
<li>다단계 큐</li>
</ul>
</li>
</ul>
<h2 id="📌-비선점형non-preemmptive">📌 비선점형(Non-preemmptive)</h2>
<ul>
<li>프로세스가 스스로 CPU 소유권을 포기하는 방식</li>
<li>강제로 프로세스를 중지하지 않는다.</li>
<li>컨텍스트 스위칭으로 인한 부하가 적다. (컨텍스트 스위칭 : PCB(Process Control Block)를 교환하는 과정인데 프로세스에 할당된 시간이 끝나거나 인터럽트에 의해 발생)</li>
</ul>
<h3 id="1-fcfs-first-come-first-served">1. FCFS (First Come, First Served)</h3>
<p>가장 먼저 온 것을 가장 먼저 처리하는 알고리즘
수행시간이 긴 프로세스는 준비큐에서 오래 기다릴 수도 있다는 문제점이 있습니다. 이 현상을 convoy effect라고 합니다.</p>
<h3 id="2-sjfshortest--job-first">2. SJF(Shortest  Job First)</h3>
<p>실행 시간이 가장 짧은 프로세스를 가장 먼저 실행하는 알고리즘
긴 시간을 가진 프로세스가 실행되지 않는 현상(starvation)이 발생하고 평균 대기 시간이 가장 짧습니다.
실제로는 실행 시간을 알기 어렵기 때문에 과거의 실행 시간을 토대로 추측해서 사용합니다.</p>
<h3 id="3-우선순위">3. 우선순위</h3>
<p>오래된 작업일수록 우선순위를 높이는(aging)방법 을 통해서 SJF가 긴 실행 시간을 가진 프로세스가 실행되지 않는다는 단점을 보완한 알고리즘
<img src="https://user-images.githubusercontent.com/57527380/187922996-297dc3c5-9729-423b-b057-9eb27b29e43a.png" alt="image">  </p>
<h2 id="📌-선점형preemptive">📌 선점형(Preemptive)</h2>
<ul>
<li>현대 OS가 쓰는 방식</li>
<li>지금 사용하고 있는 프로세스를 알고리즘에 의해 중단시키고 강제로 다른 프로세스에 CPU소유권을 할당하는 방법
(즉, CPU가 어떤 프로세스에 의해 점유 중일 떄, <strong>우선 순위가 높은</strong> 프로세스가 CPU를 차지할 수 있다.)</li>
<li>우선 순위가 높은 프로세스를 빠르게 처리해야할 경우에 유용하다.</li>
<li>선점이 일어날 경우, 오버헤드가 발생하며 처리시간을 예측하기 힘들다.  </li>
</ul>
<h3 id="1-rrroundrobin">1. RR(RoundRobin)</h3>
<p>우선순위 스케줄링의 일종
각 프로세스는 동일한 할당 시간을 주고 그 시간 안에 끝나지 않으면 다시 준비 큐의 뒤로 가는 알고리즘
할당 시간이 너무 클 경우 : FCFS알고리즘 처럼 작동한다.
할당 시간이 너무 짧을 경우 : 컨텍스트 스위칭이 잦아져서 오버헤드(비용이)가 커진다.</p>
<ul>
<li>전체 작업 시간은 길어지지만 평균 응답 시간은 짧아진다.<h3 id="2srf-srtf-or-stf">2.SRF (=SRTF or STF)</h3>
Shortest Remaining Time Fist 알고리즘
SJF와는 다르게, 중간에 실행 시간이 더 짧은 작업이 들어오면 수행하던 프로세스를 중지하고 해당 프로세스를 수행하는 알고리즘</li>
</ul>
<h3 id="3-다단계-큐">3. 다단계 큐</h3>
<p>우선순위에 따른 준비 큐를 여러 개 사용하고 큐마다 라운드 로빈이나 FCFS등 다른 스케줄링 알고리즘을 적용한 것
큐 간의 프로세스 이동이 안되니까 스케줄링 부담이 적지만 유연성이 떨어진다는 특징이 있다.</p>
<p><img src="https://user-images.githubusercontent.com/57527380/187923010-f19ca280-5b3a-4fe8-9484-82105409d8b6.png" alt="image">  </p>
<h4 id="🔶참고">🔶참고</h4>
<p><a href="https://velog.io/@ss-won/OS-CPU-Scheduling-Algorithm">[O/S] CPU 스케줄링 알고리즘 (CPU Scheduling Algorithm)</a> 
<a href="https://preamtree.tistory.com/19">[IT 기술면접 준비자료] CPU 스케줄링 기법 (선점 스케줄링, 비선점 스케줄링)
출처: https://preamtree.tistory.com/19 [Preamtree의 행복로그:티스토리]</a>
책 - 면접을 위한 CS 전공지식 노트</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CORS란 무엇인가]]></title>
            <link>https://velog.io/@tenacious_mzzz/CORS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@tenacious_mzzz/CORS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Sun, 11 Sep 2022 15:25:00 GMT</pubDate>
            <description><![CDATA[<h1 id="cors">CORS</h1>
<p>Cross Origin Resource Sharing(교차 출처 리소스 공유)
개발자가 가져오는 리소스들이 안전한지 검사하는 관문</p>
<ul>
<li>특정 도메인 간의 교차, Ajax요청은 동일-출처 보안 정책에 의해 금지된다.</li>
</ul>
<h2 id="cors가-발생하는-이유">CORS가 발생하는 이유</h2>
<p>HTTP 요청에 대해서 어떤 요청을 하느냐에 따라 각기 다른 특징을 갖고 있어서</p>
<h3 id="html">HTML</h3>
<ul>
<li>기본적으로 Cross-Origin 정책을 따름</li>
<li>link 태그의 href에서 다른 origin의 css 등의 리소스에 접근하는 것이 가능</li>
<li>img 태그의 src에서 다른 리소스에 접근하는 것이 가능</li>
</ul>
<h3 id="xmlhttprequest-fetch-api-등-script-태그-내">XMLHttpRequest, Fetch API 등 script 태그 내</h3>
<ul>
<li>기본적으로 Smae-Origin 정책을 따름<br>Same-Origin정책 ? 자바스크립트는 서로 다른 도메인에 대한 요청을 보안상 제한함(브라우저 기본 설정은 하나의 서버 연결만 허용)</li>
</ul>
<h2 id="출처origin">출처(Origin)</h2>
<p>EX) <code>https://www.google.com/search?q=asdas&amp;oq=asdas&amp;aqs=chrome..69i57j69i59j69i60l4j69i65l2.1703j1j7&amp;sourceid=chrome&amp;ie=UTF-8</code>
라는 URL이 있으면, 이 URL은 Protocoal,Host,Port,Path,Query String, Fragment등으로 이뤄져있다.
여기서 출처란, Protocol,Host,Port를 모두 합친 것을 말한다.
즉, <code>https://google.com</code>이 부분이 출처다.</p>
<h2 id="same-origin-vs-cross-origin">Same Origin vs Cross Origin</h2>
<p>웹에는 크게 SOP(Same Origin Policy) 와 CORS(Cross Origin Resource Sharing)이 있다.</p>
<h3 id="sop">SOP</h3>
<p>같은 출처에서만 리소스를 공유할 수 있다.
즉, 프로토콜이나 호스트, 포트가 다른 곳에서는 공유를 할 수 없다. Cross Origin이 된다.<br>출처를 비교하는 로직은 서버에 구현된 스펙이 아니라 브라우저에 구현된 스펙이다.<br>즉, 서버가 정상적으로 응답을 하더라도 브라우저 상에서 CORS정책에 위반되면 해당 응답은 무시된다.<br>(Internet Explorer는 Origin 비교시 포트를 무시하기 때문에 보안이 취약하다.)</p>
<h3 id="개발-중에-만날-수-있는-오류예시">개발 중에 만날 수 있는 오류(예시)</h3>
<p>프론트 개발을 React와 같은 라이브러리를 사용해서 개발할 때, 백엔드 서버와 별도의 프론트 서버가 존재하게 된다.<br>프론트 개발 도중, 로컬의 백엔드 서버에 연동하거나 개발 서버에 연결해서 API연동을 할 때,
프론트 서버 : <a href="http://localhost:3000">http://localhost:3000</a> 백엔드 서버: <a href="http://localhost:8080">http://localhost:8080</a> 로 띄웠다면, 서버에서 응답이 넘어올 때 브라우저에서 CORS오류가 발생하게 된다.</p>
<h3 id="cors-1">CORS</h3>
<ul>
<li>HTTP header를 추가적으로 사용해서 다른 출처에 있는 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 것</li>
</ul>
<h3 id="cors-등장-배경">CORS 등장 배경</h3>
<p>초창기 웹에서 다른 웹사이트로 request를 보낼 때 쿠키와 같이 전송되기 때문에 다른 웹 사이트에서도 쿠기 값을 확인할 수 있었다.<br>또한, 출처가 다른 것끼리 요청을 주고받기 위해서 JSONP라는 방식을 사용했는데, 이는 html스크립트 상에서는 다른 도메인에 대한 요청을 허용하기 때문에 <code>&lt;script&gt;</code>를 이용해서 다른 도메인에서 데이터를 가져오는 방법입니다. 이는 우회적인 방법이고 이를 막으려고 하니 많은 웹사이트에서 쓰고 있던 방법이라서, 다른 공식적인 방법이 필요해서 만들게 되었다.</p>
<h2 id="cors-동작">CORS 동작</h2>
<p>[개발자]</p>
<ul>
<li>서버에서 Access-Control-Allow-Origin 세팅<br> <code>res.setHeader(&#39;Access-Control-Allow-origin&#39;, &#39;https://inpa.tistory.com&#39;);</code><br>예시</li>
</ul>
<pre><code>Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers:  Content-Type
Access-Control-Max-Age: 86400</code></pre><ul>
<li>POST, GET, OPTIONS의 method가 가능</li>
<li>Content-Type의 Header만 받을 수 있다.</li>
<li>86400초동안 다시 preflight를 날릴 필요가 없음</li>
</ul>
<p>[CORS 동작원리]</p>
<h3 id="preflight요청">[preflight요청]</h3>
<p><img src="https://user-images.githubusercontent.com/57527380/188455853-f44d2e23-3fb4-4991-b67c-bf85cb6b38fa.png" alt="image"></p>
<ol>
<li>browser -&gt; server로 <code>preflight request</code>를 날린다.</li>
</ol>
<ul>
<li>preflight request(예비요청): 본 요청을 보내기 전에 브라우저가 안전한 요청인지 확인하는 것(개발자가 허용한 출처인지 확인) <code>OPTIONS</code>라는 메서드로 보내짐</li>
</ul>
<ol start="2">
<li>server -&gt; browser 응답으로 header에 <code>Access-Control-Allow-Origin</code>를 담아서 보낸다.</li>
</ol>
<ul>
<li>Access-Control-Allow-Origin에는 어떤 응답을 허용하고 금지하는지에 대한 정보가 담겨있다.</li>
</ul>
<ol start="3">
<li>browser -&gt; server 서버의 응답과 비교해서 안전한지 확인하고 본요청을 본낸다.</li>
<li>server -&gt; browser 원하는 응답을 보내준다.</li>
</ol>
<h3 id="단순-요청">[단순 요청]</h3>
<p><img src="https://user-images.githubusercontent.com/57527380/188455922-231ea71e-f2f4-4c2d-896c-23e0825bd448.png" alt="image"></p>
<ol>
<li>preflight를 보내지 않고 바로 서버에 직행으로 본 요청을 보낸다.</li>
<li>서버가 <code>Access-Control-Allow-Origin</code>를 보낸다.</li>
<li>브라우저가 CORS 위반 여부 검사</li>
</ol>
<h4 id="단순-요청이-일어나는-경우">단순 요청이 일어나는 경우</h4>
<ol>
<li>요청의 메소드는 <code>GET</code>, <code>HEAD</code>, <code>POST</code> 중 하나</li>
<li>수동으로 설정할 수 있는 header를 <a href="https://fetch.spec.whatwg.org/#cors-safelisted-request-header"><code>CORS-safelisted request-header</code>로 정의한 헤더</a>만 사용
(예:Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width)</li>
</ol>
<ul>
<li>여기서 Content-Type이여도 application/x-www-form-urlencoded, multipart/form-data, text/plain 값만 허용</li>
</ul>
<h3 id="인증정보-포함-요청">[인증정보 포함 요청]</h3>
<p>credentials에 옵션을 설정해줄 때 사용하는 방법<br>credentials 옵션에는</p>
<ol>
<li>omit :절대로 cookie들을 전송하거나 받지 않는다</li>
<li>same-origin은 동일 출처라면 user credential(cookies, basic http auth등등)을 전송한다.</li>
<li>include는 cross-origin호출이여도 언제나 user credential을 전송한다.<br>예시</li>
<li>fetchAPI</li>
</ol>
<pre><code class="language-js">fetch(&quot;주소&quot;, {
  credentials: &quot;include&quot;,
});</code></pre>
<ol start="2">
<li>Axios통신</li>
</ol>
<pre><code class="language-js">axios.post(주소, 데이터, { withCredentials: true });</code></pre>
<h2 id="참고">참고</h2>
<p><a href="https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F#CORS_(Cross_Origin_Resource_Sharing)">WEB-📚-CORS-💯-정리-해결-방법-👏</a><br><a href="https://ko.wikipedia.org/wiki/%EA%B5%90%EC%B0%A8_%EC%B6%9C%EC%B2%98_%EB%A6%AC%EC%86%8C%EC%8A%A4_%EA%B3%B5%EC%9C%A0">위키백과_교차 출처 리소스 공유</a><br><a href="https://ingg.dev/cors/">[Web] CORS 동작 방식과 해결 방법</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[뮤텍스 vs 세마포어]]></title>
            <link>https://velog.io/@tenacious_mzzz/%EB%AE%A4%ED%85%8D%EC%8A%A4-vs-%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4</link>
            <guid>https://velog.io/@tenacious_mzzz/%EB%AE%A4%ED%85%8D%EC%8A%A4-vs-%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4</guid>
            <pubDate>Sun, 11 Sep 2022 15:22:34 GMT</pubDate>
            <description><![CDATA[<h1 id="뮤텍스-세마포어의-차이점에-대해서-설명하시오">뮤텍스, 세마포어의 차이점에 대해서 설명하시오</h1>
<p>키워드 : 뮤텍스, 세마포어, 임계영역</p>
<h2 id="공유자원-임계영역">공유자원, 임계영역</h2>
<h3 id="공유자원">공유자원</h3>
<p>시스템 안에서 프로세스, 스레드가 함께 접근 할 수 있는 자원이나 변수 등을 의미한다.<br>공유자원을 두 개 이상의 프로세스가 동시에 읽거나 쓰는 상황을 경쟁 상태라고 한다.</p>
<h3 id="임계-영역critical-section">임계 영역(critical section)</h3>
<p>공유 자원에 접근할 때 순서 등의 이유로 결과가 달라지는 영역을 임계 영역이라고 한다.
이 영역을 해결하기 위한 방법으로 뮤텍스,세마포어, 모니터 세 가지가 있다. 이 방법들은 모두 상호배제, 한정 대기, 융통성이라는 조건을 만족한다. 세 방법의 토대는 lock이다.</p>
<ul>
<li>상호배제: 한 프로세스가 임계 영역에 들어갔을 떄 다른 프로세스는 들어갈 수 없다.</li>
<li>한정 대기 : 특정 프로세스가 영원히 임계 영역에 들어가지 못하면 안된다</li>
<li>융통성 : 한 프로세스가 다른 프로세스의 일을 방해해서는 안된다. </li>
</ul>
<h2 id="뮤텍스">뮤텍스</h2>
<ul>
<li>간단하게, 공유 자원을 사용하기 전에 설정하고 사용한 후에 해제하는 잠금</li>
<li>하나의 상태(잠금 or 잠금해제)만 가진다.  </li>
</ul>
<p>한 프로세스에 의해 소유될 수 있는 key를 기반으로 한 상호배제 기법이고 key에 해당하는 어떤 객체가 있고 이 객체를 소유한 스레드나 프로세스만이 공유자원에 접근할 수 있다.  </p>
<p>동기화 대상이 하나이며 락을 사용해서 두 스레드가 동시에 접근 할 수 없게 한다. 
<img src="https://i.imgur.com/jfZC3oV.png" alt=""></p>
<h2 id="세마포어">세마포어</h2>
<ul>
<li>일반화된 뮤텍스</li>
<li>간단한 정수 값과 두가지 함수(wait,signal 또는 P,V)로 공유 자원에 대한 접근을 처리한다.</li>
<li><code>wait()</code> 자신의 차례가 올 떄까지 기다리는 함수</li>
<li><code>signal()</code> 다음 프로세스로 순서를 넘겨주는 함수<br>프로세스가 공유 자원에 접근하면 세마포어에서 wait() 수행하고 공유 자원 접근 해제하면 세마포어에서 signal()을 수행한다.<br>프로세스가 세마포어 값을 수정할 떄 다른 프로세스는 동시에 세마포어 값을 수정할 수는 없다.  </li>
</ul>
<p>공유된 자원의 데이터 혹은 임계영역 등에 여러 Process 혹은 Thread가 접근하는 것을 막아준다. 
공통으로 관리하는 하나의 값을 이용합니다.  </p>
<p>동기화 대상이 하나 이상이다.
<img src="https://i.imgur.com/VsmTFVq.png" alt=""></p>
<h2 id="공통점">공통점</h2>
<p>동기화 방법</p>
<h2 id="차이점">차이점</h2>
<p>동기화 대상의 갯수</p>
<h3 id="질문">질문</h3>
<p><em>스터디에서 받은 질문 정리</em>
Q .Binary semaphore와 Mutex를 동일하게 볼 수 있나요? 
A .binary semaphore는 0과 1의 두 가지 값만 가질 수 있는 세마포어입니다.
구현의 측면에서 보면, 둘이 유사하기 때문에 뮤텍스는 바이너리 세마포어라고 할 수 있습니다.
하지만, 메커니즘 측면에서 보면, 동일하게 보기는 어렵습니다.
뮤텍스는 잠금 메커니즘 (리소스에 대한 접근을 동기화하는 데 사용되는 메커니즘)
세마포어는 신호 메커니즘 (신호를 기반으로 상호 배제가 일어나는 메커니즘)</p>
<h4 id="참고문헌">참고문헌</h4>
<ul>
<li>책 : 면접을 위한 CS 전공지식 노트</li>
<li>블로그 : <a href="https://velog.io/@woosung0420k/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%8F%99%EA%B8%B0%ED%99%94-Process-Synchronization">https://velog.io/@woosung0420k/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%8F%99%EA%B8%B0%ED%99%94-Process-Synchronization</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ 멀티스레딩 vs 멀티 프로세스]]></title>
            <link>https://velog.io/@tenacious_mzzz/%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%94%A9-vs-%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</link>
            <guid>https://velog.io/@tenacious_mzzz/%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%94%A9-vs-%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</guid>
            <pubDate>Sun, 11 Sep 2022 15:19:59 GMT</pubDate>
            <description><![CDATA[<h1 id="멀티스레딩과-멀티-프로세스의-차이점과-무엇이-더-좋은가">멀티스레딩과 멀티 프로세스의 차이점과 무엇이 더 좋은가?</h1>
<p>키워드 : 프로세스, 스레드, 멀티 프로세스, 멀티 스레딩</p>
<h2 id="프로세스와-스레드">프로세스와 스레드</h2>
<h3 id="프로세스">프로세스</h3>
<ul>
<li>컴퓨터에서 연속적으로 실행되고 있는 프로그램</li>
<li>사용자가 작성한 프로그램이 운영체제에 의해서 메모리 공간을 할당받아 실행 중인 것</li>
<li>프로그램이 메모리에 올라가면 프로세스가 되는 인스턴스화가 일어나고 이후 CPU스케줄러에 따라서 CPU가 프로세스를 실행</li>
</ul>
<h3 id="스레드">스레드</h3>
<ul>
<li>프로세스내에서 실행되는 흐름의 단위(실제로 작업을 수행하는 주체)</li>
<li>프로세스의 실행 가능한 가장 작은 단위</li>
<li>프로세스는 여러 스레드를 가진다.</li>
</ul>
<h2 id="멀티-프로세스">멀티 프로세스</h2>
<p>여러 프로세스를 통해 동시에 두 가지 이상의 일을 수행할 수 있는 것<br>하나 이상의 일을 병렬로 처리할 수 있다.<br>특정 프로세스의 메모리, 프로세스 중 일부에 문제가 발생해도 다른 프로세스를 이용해서 처리할 수 있기 때문에 신뢰성이 높다.</p>
<h3 id="예시">예시</h3>
<p>웹 브라우저 : 브라우저 프로세스, 렌더러 프로세스, 플러그인 프로세스, GPU프로세스</p>
<ul>
<li>브라우저 프로세스 : 주소 표시줄, 뒤로 가기 앞으로가기 ,네트워크 요청 등</li>
<li>렌더러 프로세스: 웹사이트가 보이는 부분의 모든 것</li>
<li>플러그인 프로세스 : 플러그인 제어</li>
<li>GPU 프로세스 : GPU를 이용해서 화면을 그리는 부분 제어
IPC(Inter Process Communication) : 프로세스끼리 데이터를 주고받고 공유 데이터를 관리하는 메커니즘(클라이언트와 서버의 데이터 요청,응답도 IPC의 예) </li>
<li>스레드보다는 속도가 떨어진다. </li>
</ul>
<h2 id="멀티-스레드">멀티 스레드</h2>
<p>하나의 프로세스 내에서 둘 이상의 스레드가 동시에 작업을 수행하는 것을 의미
스레드끼리 서로 자원을 공유하기 때문에 효율성이 높다.<br>예를 들어, 웹 요청을 처리할 떄 스레드를 사용하면 한 스레드가 중단되어도 다른 스레드는 실행 상태 일 수 있다.  </p>
<h3 id="장단점">장단점</h3>
<p><strong>장점</strong>
CPU가 여러 개일 경우에 각각의 CPU가 스레드 하나씩을 담당하는 방법으로 속도를 높일 수 있다.
<strong>단점</strong>
어떤 스레드가 먼저 실행될지 순서를 알 수 없다.공유 자원에 동시에 접근할 경우 원하지 않은 결과값을 가져올 수 있어서 동기화가 필요하다.<br>(동기화를 통해 스레드의 작업 처리 순서, 공유 자원에 대한 접근을 컨트롤할 수 있지만 과도한 lock으로 병목현상을 발생시켜서 성능이 저하될 가능성이 높다.)
스레드에서 에러가 나면 해당 스레드가 포함된 프로세스 전부에 영향을 준다. </p>
<h3 id="공통점">공통점</h3>
<p>여러 흐름을 동시에 수행</p>
<h3 id="차이점">차이점</h3>
<p>멀티 프로세스는 각 프로세스가 독립적인 메모리를 가지고 별도로 실행된다.</p>
<p>멀티 스레드는 각 스레드가 자신이 속한 프로세스의 메모리를 공유한다. 멀티 스레드는 각 스레드가 자신이 속한 프로세스의 메모리를 공유하기 때문에 시스템 자원의 낭비가 적다. 하나의 스레드가 작업을 할 때 다른 스레드가 별도의 작업이 가능하기 때문에 사용자와의 응답성도 좋다.</p>
<p>그러나, 멀티 스레드는 에러에 더 취약하다는 점에서는 멀티 프로세스보다 좋지 않다. </p>
<h3 id="나올-수-있는-질문형태">나올 수 있는 질문형태</h3>
<ul>
<li>차이점</li>
<li>뭐가 더 좋은가<h3 id="질문정리">질문정리</h3>
<em>스터디하면서 받은 질문 정리</em>
Q. Chrome이 multi process를 채택한 이유는 무엇인가요?
A. 프로세스는 스케줄링 대상이므로 멀티프로세스를 사용하면, 문맥교환(컨텍스트스위칭)이 많이 일어나고 이는 오버헤드로 이어집니다. 스레드 또한 스케줄링 대상이고 문맥교환이 발생하지만, 자원을 공유하기 때문에 오버헤드가 프로세스에 비해 적습니다.
chrome은 각각의 tab이 process-per-tab방식을 사용하고 있는데, 만약 모든 탭들이 동일한 프로세스를 사용한다면 하나의 탭에서 에러가 발생하면 모든 탭에 에러가 발생할 것이기 때문에 멀티프로세스 방식을 채택했습니다.</li>
</ul>
<h4 id="참고문헌">참고문헌</h4>
<ul>
<li>책: 면접을 위한 CS 전공지식 노트</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1463번]]></title>
            <link>https://velog.io/@tenacious_mzzz/%EB%B0%B1%EC%A4%80-1463%EB%B2%88</link>
            <guid>https://velog.io/@tenacious_mzzz/%EB%B0%B1%EC%A4%80-1463%EB%B2%88</guid>
            <pubDate>Sat, 06 Aug 2022 12:26:19 GMT</pubDate>
            <description><![CDATA[<h1 id="문제"><a href="https://www.acmicpc.net/problem/1463">문제</a></h1>
<p>DP를 제대로 이해하지 못해서 엄청 헤매서 정리를 해보려고 한다.  </p>
<h2 id="dp">DP</h2>
<p>Dynamic Programming으로 큰 문제를 해결하기 위해서 작은 문제부터 차례로 해결해나가서 그것들로 큰 문제를 해결하는 방법이다. 피보나치 수열 (<code>f(N) = f(N-1)+f(N-2);</code>)이 DP문제의 대표적인 예시이다. </p>
<h2 id="dp-문제-해결-방법">DP 문제 해결 방법</h2>
<ol>
<li>어떤 것이 재사용되는 값인지 파악하고 이를 변수로 지정한다.</li>
<li>그 변수들로 점화식을 만든다.</li>
<li>변수의 값들을 모두 저장해둔다.</li>
<li>기저조건 파악한다.</li>
</ol>
<h3 id="bottom-up-방식">Bottom-Up 방식</h3>
<p>반복문 사용
dp[0]부터 계산해서 dp[N]을 구하는 방법</p>
<h3 id="top-down방식">Top-Down방식</h3>
<p>재귀 사용
dp[N]을 구하기 위해서 dp[0]까지 내려간 다음에 해당 값을 재귀로 전달시켜서 재사용하는 방식</p>
<h2 id="1463번-_-1로-만들기">1463번 _ 1로 만들기</h2>
<p>맨 처음에는 Top-Down방식으로 풀었는데, 시간초과가 나서 Bottom-Up방식으로 다시 풀었다.
여러 블로그를 참고해도 이해가 잘 안가서 직접 손으로 그려보니까 이해가 잘 되었다!
<code>minCnt[] = min(minCnt[i-1]+1,minCnt[i/2]+1,minCnt[i/3]+1)</code>을 구하면 되는데, 여기서 각 방법에 1을 더해주는 이유는 밑의 그림 중 N=4일때를 참고하면, 
<code>4 -&gt; 3 -&gt; 1</code> 일 때 
<code>4 -&gt; 3</code>으로 가는 방법 1번
<code>3 -&gt; 1</code>로 가는 방법 1번으로 이뤄지는데, 
<strong><code>4 -&gt; 3</code> 번에서 생기는 1번을 더해주는 것이다.</strong><br><img src="https://velog.velcdn.com/images/tenacious_mzzz/post/a0742404-fe62-489e-a7de-b2886dda29aa/image.png" alt="">
그래서 짠 코드는 다음과 같다.  </p>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Boj1463 {
    public static int min = Integer.MAX_VALUE;
    public static int cnt =0;
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(in.readLine());
        //최소 연산 값 저장
        int minCnt[] = new int[N+1];
        for(int i=2;i&lt;=N;i++) {
            //-1연산은 무조건 수행
            minCnt[i]=minCnt[i-1]+1;
            //-1연산이랑 2로나누는 연산 중 최소로 연산 수행하는 값
            if(i%2==0) minCnt[i]=Math.min(minCnt[i],minCnt[i/2]+1);
            //6으로 나눠지는 값이라면 2로 나눌 때의 최소연산값과 3으로 나눈 연산 비교
            //아니면, -1연산이랑 3으로 나누는 연산 중 최소로 연산 수행하는 값
            if(i%3==0) minCnt[i]=Math.min(minCnt[i],minCnt[i/3]+1);
        }
        System.out.println(minCnt[N]);
    }
}
</code></pre>
<p>참고로, 6으로 나눠지는 값이여도(2,3둘 다 나눠지는 값) 2로 나눌 때 최소값을 minCnt[i]에 저장해두기 때문에 잘 동작한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[StringBuilder와 +연산자]]></title>
            <link>https://velog.io/@tenacious_mzzz/StringBuilder%EC%99%80-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@tenacious_mzzz/StringBuilder%EC%99%80-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Tue, 02 Aug 2022 05:34:00 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-java">        .
        .
        .
        ArrayList&lt;Integer&gt; zero = new ArrayList&lt;&gt;();
        ArrayList&lt;Integer&gt; one = new ArrayList&lt;&gt;();
        .
        .
        .
        String str= &quot;&quot;;
        str=in.readLine();
        StringBuilder sb = new StringBuilder(str,&quot; &quot;);
        sb.append(zero.get(n)+&quot; &quot;+one.get(n)+&quot;\n&quot;); //2974875900
        sb.append(zero.get(n)).append(&quot; &quot;).append(one.get(n)).append(&quot;\n&quot;); //2542502200
        System.out.println(zero.get(n)+&quot; &quot;+one.get(n)+&quot;\n&quot;);//3718124400</code></pre>
<p>StringBuilder를 사용하는 경우와 +연산자를 사용하는 경우 중 어떤 경우가 시간적으로 빠른지 궁금했다.</p>
<p>+연산자를 사용하는 것이 가장 많은 시간이 들고,  StringBuilder와 +연산자를 같이 사용하는 것이 그 다음으로 많은 시간이 들고, 순수하게 StringBuilder만 쓰는 것이 가장 짧은 시간이 걸렸다.<br>StringBuilder를 쓴다면, +연산자를 같이 쓰지 않도록 하는 것이 중요하겠다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[배열 최대값,최소값 구하기 시간(JAVA)]]></title>
            <link>https://velog.io/@tenacious_mzzz/%EB%B0%B0%EC%97%B4-%EC%B5%9C%EB%8C%80%EA%B0%92%EC%B5%9C%EC%86%8C%EA%B0%92-%EA%B5%AC%ED%95%98%EA%B8%B0-%EC%8B%9C%EA%B0%84</link>
            <guid>https://velog.io/@tenacious_mzzz/%EB%B0%B0%EC%97%B4-%EC%B5%9C%EB%8C%80%EA%B0%92%EC%B5%9C%EC%86%8C%EA%B0%92-%EA%B5%AC%ED%95%98%EA%B8%B0-%EC%8B%9C%EA%B0%84</guid>
            <pubDate>Tue, 02 Aug 2022 05:30:10 GMT</pubDate>
            <description><![CDATA[<p>최대값, 최소값 구하는 방법에는 for문, Arrays.sort(), Stream 이용하는 방법이 있다.</p>
<pre><code class="language-java">import java.util.Arrays;

public class practice {
    public static void main(String[] args) {
        int arr[] = {1,2,3,4,5};

        long start1=System.nanoTime();
        // for문 사용
        int max = arr[0]; 
        for (int i = 0; i &lt; arr.length; i++) {
             if (arr[i] &gt; max) {
                 max = arr[i];
             }
        }
        System.out.println(max); //최대값
        long end1=System.nanoTime();

        long start2=System.nanoTime();
        // Arrays.sort 사용
        Arrays.sort(arr); // 정렬
        System.out.println(arr[arr.length-1]); // 최대값

        long end2=System.nanoTime();

        long start3=System.nanoTime();
        // Stream을 이용한 방법
        System.out.println(&quot;Stream을 이용한 방법&quot;);
        // Arrays.stream(배열명) 으로 배열 생성
        System.out.println(Arrays.stream(arr).max().getAsInt()); /;//최대값
        long end3=System.nanoTime();

        System.out.println(end1-start1); //138700
        System.out.println(end2-start2); //178000
        System.out.println(end3-start3); //28392900
    }
}</code></pre>
<p>for 문 &gt; 정렬 &gt; stream 순으로 빠르다.(for문이 제일 빠르다)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java]]></title>
            <link>https://velog.io/@tenacious_mzzz/Java</link>
            <guid>https://velog.io/@tenacious_mzzz/Java</guid>
            <pubDate>Sun, 31 Jul 2022 16:21:32 GMT</pubDate>
            <description><![CDATA[<h1 id="type">Type</h1>
<p>데이터의 종류</p>
<ul>
<li>기본형(primitive type)
  미리 정해진 크기의 Memory size로 표현, 변수 자체에 값을 저장</li>
<li>참조형(reference type)
  크기가 미리 정해질 수 없는 데이터의 표현, 변수에는 실제 값을 참조할 수 있는 주소만 저장<h2 id="primitive-type">Primitive type</h2>
논리형(boolean), 문자형, 숫자형
byte 8bit
short 16bit
int 32bit -&gt; overflow 주의
long 64bit
float 32bit
double 64bit</li>
<li><blockquote>
<p>실수 연산은 부정확함(유효 자리수를 이용한 반올림 처리)
<code>float var1 = 10.0 //Type mismatch: cannot convert from double to float 오류남</code>
<code>float var1 = 10.0f</code> 또는 <code>double var1=10.0</code>으로 작성해야함
char 16 bit</p>
</blockquote>
</li>
<li><blockquote>
<p>기억할 ASCII 코드 (&#39;0&#39; = 48, &#39;A&#39; = 65, &#39;a&#39; = 97)</p>
</blockquote>
<h2 id="type-casting형변환">Type casting(형변환)</h2>
</li>
<li>변수의 type을 다른 type 으로 변환하는 것</li>
<li>primitive &lt;-&gt; primitive</li>
<li>reference &lt;-&gt; reference 가능</li>
<li>boolean은 호환되지 않는다</li>
<li>기본 타입과 참조형의 형 변환을 위해서 Wrapper 클래스를 사용함<h3 id="묵시적-형-변환promotion-vs-명시적-형-변환">묵시적 형 변환(promotion) vs 명시적 형 변환</h3>
묵시적 형 변환은 타입의 크기가 아니라 표현 범위가 커지는 방향으로 할당할 경우에 발생하며, 자료의 손실이 없기 때문에 JVM이 알아서 해주는 반면, 명시적 형 변환은 값 손실이 발생할 수 있기 때문에 형 변환한다고 <code>()</code>를 이용해서 작성해줘야한다. </li>
</ul>
<h2 id="연산자">연산자</h2>
<p>최후위연산자 : 대입연산자
최전위연산자: 괄호
변수의 초기값은 일반적으로 부정적인 의미로 두는 게 좋다.</p>
<p>논리연산자 || 을 사용할 때, 앞이 True이면 뒤에는 실행하지 않기 때문에 앞이 True인게 좋다.
&amp;&amp;을 사용할 때는 앞이 False인게 좋다. </p>
<pre><code class="language-java">piblic static void main(String[] args){
    a=10;
    b=20;
    System.out.println((a+=10) &gt; 15 || (b-=10) &gt; 15); // true
    System.out.println(&quot;a = &quot; + a+&quot;, b = &quot; + b); // a=20, b=20

}</code></pre>
<h1 id="배열">배열</h1>
<p>type이 동일한 데이터를 하나의 연속된 메모리 공간에서 관리하는 것</p>
<ul>
<li>배열 요소의 초기화 : int,byte,short의 기본값 0, boolean기본값 false, 참조형 변수 : null</li>
<li>주의사항
<code>{}</code>을 통한 배열 생성은 변수 선언과 동시에 진행해야함<pre><code class="language-java">boolean [] bools;
bools={true,false,false};
//------------위처럼 하면 오류남
boolean[] bools= new boolean[]{true,false,false}; // 맞는 표현</code></pre>
</li>
<li>배열 생성과 메모리 사용
  배열 선언 -&gt; 배열 생성 -&gt; 참조 값 할당 -&gt; 요소에 값 할당</li>
<li>for - each문
  for(int x: intArray){};</li>
<li><em>Array is immutable*</em>
배열은 최초 메모리 할당 이후에 변경할 수 없다.
개별 요소는 다른 값으로 변경은 가능하지만, 요소를 추가하거나 삭제할 수는 없다.</li>
</ul>
<h1 id="객체지향-프로그래밍">객체지향 프로그래밍</h1>
<p>OOP(Object Oriented Programming)
객체? 주체가 아닌 것, 주체가 활용하는 것
객체지향 프로그래밍? 주변의 많은 것들을 객체화해서 프로그래밍 하는 것 
장점 : 신뢰성 높은 프로그래밍 가능, 추가,수정,삭제가 용이함, 재사용성이 높음</p>
<h2 id="class와-객체">class와 객체</h2>
<p>프로그래밍 -추상화-&gt; 클래스 -구체화-&gt; 객체
현실의 객체가 갖는 속성과 기능이 추상화(abstraction)되어서 클래스에 정의됨
클래스는 구체화가 되어서 프로그램의 객체(instance,object)가 됨</p>
<ul>
<li>객체를 정의해 놓은 객체의 설계도, 틀</li>
<li>객체는 클래스를 데이터 타입으로 메모리에 생성한 것<h3 id="class의-접근제어자">class의 접근제어자</h3>
</li>
<li>private 불가능
  class는 객체를 만들기 위해서 쓰는 것인데 private은 쓸모 없게 되기 때문에 사용하지 않습니다. </li>
<li>protected 불가능
  상속관계에서 써야하기 때문에 불가능합니다.</li>
<li>static 불가능
  static은 메서드,변수에만 붙을 수 있다. <h2 id="jvm의-메모리-구조">JVM의 메모리 구조</h2>
Class Area, Method Stack, Heap으로 이뤄져 있다.<h3 id="class-area">class Area</h3>
클래스 원형 로딩하는 곳(Field 정보, Method정보, 타입 정보, 상수 풀)<h3 id="method-stack">method stack</h3>
메서드들의 실행 공간
thread별로 별도로 관리한다. 
메서드 호출 순서대로 이 스택에 쌓인다.
메서드 프레임에 로컬 변수도 쌓임
로컬변수는 선언된 영역을 벗어나면 삭제된다.<h3 id="heap">Heap</h3>
객체를 저장하기 위한 영역
thread에 의해서 공유된다.
생성된 객체는 프로그래머가 삭제할 수 없고 GC(Grabage Collector)만이 제어할 수 있다.</li>
</ul>
<h2 id="선언위치에-따른-변수의-종류">선언위치에 따른 변수의 종류</h2>
<ul>
<li>멤버 변수(클래스 멤버 변수, 인스턴스 멤버 변수)
선언위치: 클래스 멤버 변수, 인스턴스 멤버 변수는 클래스 영역</li>
<li>지역변수(지역 변수, 파라미터 변수)
선언위치: 지역변수는 함수 내부, 파라미터 변수는 함수 선언부</li>
</ul>
<h3 id="생성소멸-시점">생성,소멸 시점</h3>
<p><strong>인스턴스 멤버 변수</strong>
객체가 만들어질 때 객체 별로 생성되고 생성되는 메모리 영역은 heap이다.
소멸 시점은 GC에 의해 객체가 없어질 때이며 명시적으로 소멸시킬 수 없다.
<strong>클래스 멤버 변수</strong>
<code>static</code>키워드를 붙여서 선언한다.
클래스 영역에 클래스 로딩 시에 메모리 등록함
소멸 시점은 프로그램 종료할 때이다. 
<strong>지역변수 &amp; 파라미터 변수</strong>
선언된 라인이 실행될 때 thread별로 생성된 stack에 생성된다.
소멸 시점은 선언된 영역이 {}을 벗어날 때 이다.</p>
<h2 id="method">method</h2>
<p>메서드 : 기능처리
메서드 접근 : 메모리에 호출하려는 멤버가 있으면 호출 가능, 없으면 먼저 메모리에 로딩 후 사용
static member는 클래스 로딩 시에 자동으로 등록되기 때문에 언제나 메모리에 있다.
instance member는 객체 생성 전에는 메모리에 없다. </p>
<ul>
<li>메서드 호출 시 파라미터로 입력된 값을 <strong>복사</strong>해서 전달<h3 id="오버로딩-vs-오버라이딩">오버로딩 vs 오버라이딩</h3>
오버로딩은 동일한 기능을 수행하는 메서드의 추가 작성
println, printf등도 오버로딩의 일종이다. 
메서드 이름은 동일하고 인자값의 갯수나 인자값의 type등이 달라야 오버로딩이다.(return type은 상관없다.)
오버로딩의 장점은 중복 코드에 대한 효율적인 관리가 가능하다.</li>
</ul>
<p>오버라이딩은 부모클래스에서 정의된 메서드를 자식 클래스에서 적합하게 수정하는 것
조건</p>
<ul>
<li>메서드의 이름이 동일해야한다</li>
<li>매개 변수의 개수, 타입, 순서가 같아야한다.</li>
<li>리턴 타입이 동일해야한다</li>
<li>접근 제한자는 부모 보다 범위가 넓거나 같아야한다.</li>
<li>조상보다 더 큰 예외를 던질 수 없다</li>
</ul>
<h1 id="생성자">생성자</h1>
<h2 id="this">this</h2>
<p>참조 변수, 객체 자신을 가리킨다. (객체 참조)
로컬 변수와 멤버 변수의 이름이 동일할 경우 this를 사용해서 멤버 변수임을 명시적으로 나타낼 수 있다. </p>
<h2 id="this-1">this()</h2>
<p>메서드와 마찬가지로 생성자도 오버로딩 가능함.
맨 첫줄에서만 호출 가능함
객체 생성 시 필요한 멤버 변수만 초기화 진행 -&gt; 생성자 별 코드의 중복 발생
한 생성자에서 다른 생성자를 호출할 때 사용 </p>
<h2 id="super">super</h2>
<p>조상 클래스 멤버에 접근</p>
<h2 id="super-1">super()</h2>
<p>조상 클래스의 생성자 호출
맨 첫줄에서만 호출 가능하다.
this() or super()를 호출하지 않으면, 컴파일러가 super()를 삽입해준다.</p>
<h1 id="객체-지향-언어의-특징">객체 지향 언어의 특징</h1>
<p>추상화 , 다형성, 상속, 데이터 은닉과 보호
추상화: 현실의 객체를 추상화 해서 클래스를 구성함
다형성: 하나의 객체를 여러가지 타입으로 참조할 수 있다.
상속: 부모 클래스의 자산을 물려받아 자식을 정의함으로 코드의 재사용이 가능하다
Encapsulation: 데이터를 외부에 노출 시키지 않고 메서드를 이용해서 보호할 수 있다.</p>
<h2 id="상속">상속</h2>
<p>모든 클래스는 Object class를 상속 받는다. 
상속의 관계는 <code>is a</code>관계라고 한다.
자바는 단일 상속만 가능하며, interface의 포함관계(<code>has a</code>관계)로 다중 상속할 수 없다는 단점을 극복할 수 있다. </p>
<h2 id="annotation">Annotation</h2>
<p>JVM,컴파일러,프레임워크 등이 보는 주석</p>
<h2 id="-vs-equals">== vs equals()</h2>
<p>객체의 주소 비교 : ==
객체의 내용 비교 : equals 재정의</p>
<h2 id="hashcode">hashCode</h2>
<p>시스템에서 객체를 구별하기 위해서 사용되는 정수 값으로, 객체의 해시 코드를 사용한다.</p>
<h1 id="package-import">package, import</h1>
<h2 id="package">package</h2>
<p>패키지 : 의미 있는 이름으로 만들고 .을 통해서 계층적 접근 모든 클래스는 반드시 하나의 패키지에 속함 default package가 만들어지기는 하지만 안쓰는게 좋음 package 일반적인 naming룰 소속.프로젝트.용도 도메인이 쓰이면 거꾸로 쓰면됨 ex) com.ssafy.hrm.common -&gt; hrm프로젝트, 용도는 일반적이다,</p>
<h2 id="import">import</h2>
<p> 다른 패키지에 선언된 클래스를 사용하기 위해서 필요한 키워드 패키지와 클래스 선언 사이에 위치 패키지와 달리 여러 번 선언 가능 default import package는 java.lang.*</p>
<h1 id="접근-제한자-encapsulation">접근 제한자, Encapsulation</h1>
<p>제한자 : public, protected, default(=package), private
그 외: final, abstract, static, synchronized</p>
<p><strong>final</strong> 마지막, 더 이상 바뀔 수 없음 용도 final class - 더 이상 확장 할 수 없다. 상속 금지-&gt; 오버라이드 방지 final method -&gt; 더 이상 재 정의 할 수 없음 오버라이딩 금지 final variable 더 이상 값을 바꿀 수 없다. 상수</p>
<p>protected : 상속 받은 클래스, 같은 패키지에서만 접근 가능(다른 패키지의 자손 클래스도 ok)
default: 자신 클래스 내부와 같은 패키지내에서만 접근 가능
private : 외부에서 접근 불가능, 같은 클래스 내에서만 접근 가능</p>
<h2 id="singleton-pattern">Singleton pattern</h2>
<p>외부에서 생성자에 접근 금지 -&gt; 생성자의 접근 제한자를 private으로 설정 내부에서는 private에 접근 가능하므로 직접 객체 생성 -&gt; 멤버 변수이므로 private설정 외부에서 private member에 접근 가능한 getter생성 -&gt; setter 불필요 객체 없이 외부에서 접근할 수 있도록 getter와 변수에 static추가</p>
<p>외부에서는 언제나 getter를 통해서 객체를 참조하므로 하나의 객체 재사용</p>
<h1 id="다형성">다형성</h1>
<ul>
<li>많은 type을 가질 수 있는 성질</li>
<li>정의: 상속 관계에 있을 때 조상 클래스의 타입으로 자식 클래스 객체를 레퍼런스 할 수 있다. <pre><code class="language-java">public class B extedns A {}
A a = new A();
B b = new B();
A a = new B();
//B b= new A();는 불가, 하위 클래스를 만드는데 상위 클래스 참조 불가</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[GitHub]private Repository wiki 사라짐]]></title>
            <link>https://velog.io/@tenacious_mzzz/GitHubprivate-Repository-wiki-%EC%82%AC%EB%9D%BC%EC%A7%90</link>
            <guid>https://velog.io/@tenacious_mzzz/GitHubprivate-Repository-wiki-%EC%82%AC%EB%9D%BC%EC%A7%90</guid>
            <pubDate>Thu, 28 Jul 2022 12:48:53 GMT</pubDate>
            <description><![CDATA[<p><em>매우 사소한 이슈지만 혹시나 저처럼 헤매는 사람이 있을까봐 작성하는 글 입니다.</em></p>
<p>지금까지 학교계정으로 GitHub pro기능을 사용하면서, private Repository를 잘 사용하고 있었습니다. 이 저장소에서 코드도 관리하고 wiki도 열심히 작성하고 있었는데, 어느 날 wiki에 들어가려고 하니 아래 그림처럼 wiki 탭이 사라져있었습니다!!</p>
<h3 id="문제점">문제점</h3>
<p>private저장소에 작성하고 있던 wiki가 사라짐.
<img src="https://velog.velcdn.com/images/tenacious_mzzz/post/758e554d-9666-4b17-8bb4-89113c2214dc/image.png" alt=""></p>
<p>바로 구글링으로 private repository wiki 사라짐 이런식으로 검색해봤는데 해결방법이 나와있지 않았지만 왜 사라졌는지는 알 수 있었습니다.</p>
<h3 id="원인">원인</h3>
<p>GitHub가 private repository를 무료로 사용할 수 있게 해주면서, pro가 끝났는데도 private repository는 남아있고 wiki는 사라진것이였습니다.
(참고로 pro계정을 사용하는 사람은 private repository에서 wiki 사용할 수 있고, 무료로 사용하는 private repository에서는 wiki를 사용할 수 없습니다.)</p>
<h3 id="해결방법">해결방법</h3>
<ol>
<li>private repository -&gt; public repository로 바꾸니 예전에 작성해둔 wiki를 볼 수 있었습니다.</li>
<li>pro계정으로 upgrade하기(private repository를 유지하면서 wiki도 사용할 수 있습니다.)</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>