<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hoyoun_gg.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요. 열심히 해보겠습니다</description>
        <lastBuildDate>Wed, 16 Oct 2024 08:04:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hoyoun_gg.log</title>
            <url>https://velog.velcdn.com/images/hoyoun_gg/profile/e6dcb27a-0935-4ae1-b63b-35751fd901cd/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hoyoun_gg.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hoyoun_gg" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[객체지향과 SOLID 원칙 정리
]]></title>
            <link>https://velog.io/@hoyoun_gg/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EA%B3%BC-SOLID-%EC%9B%90%EC%B9%99-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hoyoun_gg/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EA%B3%BC-SOLID-%EC%9B%90%EC%B9%99-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 16 Oct 2024 08:04:30 GMT</pubDate>
            <description><![CDATA[<p>우테코 프리코스를 진행하기에 앞서 미션을 진행할 때, 객체지향을 잘 지켜 설계하고 구현해야겠다고 생각했습니다. 이 글은 객체지향에 대한 고민과 SOLID 원칙에 대한 내용을 담고 있습니다.</p>
<h2 id="💿-객체지향이란">💿 객체지향이란?</h2>
<blockquote>
<p>객체 지향 프로그래밍은 <strong>컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 &quot;객체&quot;들의 모임으로 파악하고자 하는 것이다</strong>. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. - 위키피디아</p>
</blockquote>
<p>일단 정확한 정의는 아니지만 위키피디아에서는 위와 같이 설명하고 있습니다. 이걸 생각해보면 그저 코드가 명령어의 모음집이 아니라, 객체라는 어떤 것으로 이루어진 집합으로 보겠다는 것 같습니다. </p>
<p>저는 <code>객체지향</code>이라는 말을 처음 전공 수업시간에 들었지만 이 말이 크게 와닿지 않았습니다. 그냥 객체지향프로그래밍이라는 과목에서는 c++ 언어만 알려주었고, 문법만 배웠던 기억이 있습니다.</p>
<p>그런데 아이러니하게도 <code>객체지향</code>이란 말이 저에게 와닿았을 때는 제가 객체지향을 무시했을 때였습니다. </p>
<p>제가 처음 좀 규모가 있는 프로젝트를 맡았을 때, 저는 단순한 구현 개발에 집중했습니다. 제 입장에서는 돌아가기만 했으면 되었으니까요. 그러나 문제는 구현단계가 아닌 그 다음단계에서 발생했습니다. 프로그램은 단순한 구현에서 끝나는게 아니라 개발자가 계속해서 수명을 연장해주는 유지보수라는 작업을 해줘야 합니다. 프로젝트의 요구사항이 변경되고 버그를 고쳐야 할 때, 정말 지옥을 경험했습니다. 모든 코드들이 얽히고 설켜서 하나만 변경해도 모든 것을 변경해야 하는 지경에 이르렀거든요. 객체지향이 이래서 필요하다는걸 이때서야 몸소 느꼈습니다.</p>
<p><code>객체지향</code> 프로그래밍은 유연하고 변경이 용이하게 만들기 때문에 소프트웨어 개발에 많이 사용됩니다. 좋은 객체지향 설계란 시스템에 새로운 요구사항이나 변경사항이 생기면, 영향을 적게 받는 것입니다. 객체지향의 특성으로는 보통 다음 네가지를 많이 꼽습니다.</p>
<ul>
<li>추상화</li>
<li>캡슐화</li>
<li>상속</li>
<li>다형성</li>
</ul>
<p>보면 자바 언어를 배우다보면 다 경험하게 되는 것들입니다. 그런데 이런 것을 이용하여 객체지향 프로그래밍을 하라고 하면 좀 막막합니다. 다형성을 이용하라고? 어떻게? 라고 생각이 드는게 당연합니다. 언어만 딱 배웠을 땐 그렇게 생각이 되는게 당연하다고 생각됩니다.</p>
<h3 id="역할과-구현으로-분리">역할과 구현으로 분리</h3>
<p>저는 위 특성들을 이용하기 위해 프로그램 세계에서 <strong>역할</strong>과 <strong>구현</strong>으로 분리하는 것을 추천합니다. 사용자는 자기가 쓸 대상의 역할만 알면 되고, 구현을 몰라도 됩니다. 예를 들어 우리가 운전을 하지만 자동차의 동작 원리를 알지 못하는 것과 같습니다. 구현이 변경된다고 하더라도 역할을 알고 사용할줄 알면 상관이 없습니다. 이걸 좀 더 자바 언어에 맞게 설명을 하자면 자바의 다형성을 이용하기 위해 역할을 인터페이스로 만들고, 구현은 그 인터페이스를 구현한 클래스로 만듭니다. 이렇게 되면 각자의 역할은 설계시점(인터페이스)에 결정되고, 구현은 얼마든지 달라져도 고쳐야 할 코드가 크게 많지 않게 됩니다. 즉, 유연하고 변경이 용이하게 됩니다. </p>
<h3 id="가이드라인">가이드라인..?</h3>
<p>이렇게 좀 객체지향 설계를 할때 어떻게 해야할지 알아보았는데, 이걸 실제로 구현할때 사용할 원칙같은게 있으면 좀 더 좋겠다는 생각을 했습니다. 쉽게 말하자면 가이드라인 같은게 필요했습니다. 여기서 찾은 것이 <code>SOLID</code> 원칙입니다.</p>
<h2 id="✅-solid-원칙">✅ SOLID 원칙</h2>
<p><code>SOLID</code> 원칙이란 객체지향 설계에서 지켜야 할 다섯 개의 소프트웨어 개발 원칙 입니다. 이 원칙을 지켜 프로그래밍을 하게 되면 코드의 응집도를 높이고 결합도를 떨어트리는 데 도움이 됩니다. 일단 다섯개의 원칙에 대해 살펴보겠습니다.</p>
<h3 id="srpsingle-responsibility-principle--단일-책임-원칙">SRP(<strong>Single Responsibility Principle)</strong> : 단일 책임 원칙</h3>
<ul>
<li>하나의 클래스는 단 하나의 책임(역할)만 가져야 한다. 라는 원칙입니다.</li>
</ul>
<p>여러 책임이 하나의 클래스 안에 섞여있으면, 서로 책임이 영향을 줄 수 있어 유지보수가 어려워집니다. 따라서 한 클래스는 단 하나의 책임만 갖게 하는 원칙입니다.</p>
<h3 id="ocpopen-closed-principle-개방-폐쇄-원칙">OCP<strong>(Open-Closed Principle)</strong>: 개방 폐쇄 원칙</h3>
<ul>
<li>Open for extension : 새로운 기능의 추가나 변경사항이 생기면 코드는 확장 가능해야 한다.</li>
<li>Closed for modification : 기존의 코드는 수정되지 않아야 한다.</li>
</ul>
<p>처음 <code>OCP</code>를 보면 진짜 무슨 소리인지 잘 이해가 안됩니다. 확장 가능해야한데 수정되지 않아야 한다는게 무슨 소리지 라고 하는게 충분히 이해됩니다.</p>
<p>OCP에서 확장 가능하다는 의미는 어떤 인터페이스를 구현해서 새로운 기능을 추가할 수 있다는 의미입니다. 예를 들면, Food 라는 인터페이스가 있다면 이것을 구현해 여러 음식들을 얼마든지 추가할 수 있습니다. </p>
<p>당연히 기능이 추가될 때 코드 수정은 되어야 합니다. 그런데 여기서 말하는 기존 코드 수정이 닫혀있다는 말은 사용자의 코드가 변경되지 않아야 된다는 말입니다. 즉 어떤 역할(인터페이스)을 사용하는 클라이언트의 코드가 변경되지 않아야 합니다. </p>
<h3 id="lspliskov-substitution-principle--리스코프-치환-원칙">LSP(Liskov Substitution Principle) : 리스코프 치환 원칙</h3>
<ul>
<li>서브타입은 언제나 기반(부모) 타입으로 교체할 수 있어야 한다.</li>
</ul>
<p>다형성의 원리를 이용하기 위한 원칙입니다. 정확성을 깨뜨리지않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 합니다. </p>
<p>쉽게 자바 코드로 예시를 들면, </p>
<pre><code class="language-java">        List&lt;Integer&gt; arrayList = new ArrayList&lt;&gt;();

        List&lt;Integer&gt; list = new LinkedList&lt;&gt;();</code></pre>
<p>위 코드를 보면, <code>List</code>라는 기반 타입으로 실행한 결과는 <code>ArrayList</code>로 실행해도 같고, <code>LinkeList</code>로 실행해도 동일합니다. 인터페이스의 의도와 다르게 구현하게 되면 <code>LSP</code> 위반입니다. 이 원칙을 적용해야 인터페이스를 믿고 사용할 수 있습니다.</p>
<h3 id="ispinterface-segregation-principle--인터페이스-분리-원칙">ISP(Interface Segregation Principle) : 인터페이스 분리 원칙</h3>
<ul>
<li>특정 클라이언트에 필요한 메서드들만 포함된 작은 인터페이스를 만들어야 한다.</li>
</ul>
<p>엄청나게 많은 기능을 가진 인터페이스 하나보다, 특정 클라이언트를 위한 인터페이스를 작성하는게 더 낫습니다. <code>SRP</code>와 비슷하게 인터페이스가 여러 역할을 모두 수행하는 것보다는 한 책임만 지는 것이 낫다는 의미입니다. 따라서 <code>ISP</code>는 큰 인터페이스를 만들기 보다는 이것을 분리해 각각으로 만드는 것입니다.</p>
<h3 id="dipdependency-inversion-principle--의존관계-역전-원칙">DIP(Dependency Inversion Principle) : 의존관계 역전 원칙</h3>
<ul>
<li>고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화된 인터페이스에 의존해야 한다.</li>
</ul>
<p>구현체에 의존하는 것이 아니라, 추상화에 의존해야 합니다. 자바로 변환하면 구현 클래스가 아닌 인터페이스에 의존하라는 원칙입니다. </p>
<p>실제로 DIP는 Java 언어만을 이용한 다형성으로는 지키기가 쉽지 않습니다.</p>
<pre><code class="language-java">PaymentService paymentService = new PaymentServiceImpl();</code></pre>
<p>이 코드를 보면 <code>PaymentService</code>를 이용하고 있는 사용자는 구현체와 인터페이스 둘다에 의존하는 걸 볼 수 있습니다. 이걸 해결하려면 의존관계 주입과 같은 기법을 사용해야 합니다.</p>
<h2 id="정리-및-회고">정리 및 회고</h2>
<p><code>객체지향</code> 원칙과 <code>SOLID</code> 원칙에 대해 알아봤습니다. 이런 개념들은 코드를 유지보수를 편하게 해주고, 좋은 설계를 하게 해줍니다. 든 원칙을 지키기에는 쉽지 않지만, 앞으로 우테코 프리코스 미션을 수행하면서 유지보수하기 좋은 코드를 작성하기 위해 노력하고 싶습니다.또 <code>객체지향의 사실과 오해</code> 라는 책도 추가적으로 읽는 중인데, 다 읽으면 다시 정리해 객체지향에 대한 글을 올리고 싶습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AngularJS commit convetions 정리]]></title>
            <link>https://velog.io/@hoyoun_gg/AngularJS-commit-convetions-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hoyoun_gg/AngularJS-commit-convetions-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 16 Oct 2024 04:25:47 GMT</pubDate>
            <description><![CDATA[<p>이번 우테코 프리코스를 시작하면서 커밋 메시지를 AngularJS commit convetions를 지켜 작성하기로 결정했습니다. 커밋 메시지를 작성하기 전에 AngularJS commit convetions에 대해 알아보고 정리하겠습니다. 이 글을 작성하면서<a href="https://gist.github.com/stephenparish/9941e89d80e2bc58a153#goals">https://gist.github.com/stephenparish/9941e89d80e2bc58a153#goals</a> 링크를 참고했습니다.</p>
<h1 id="📌-commit-메시지의-형식">📌 Commit 메시지의 형식</h1>
<pre><code class="language-jsx">&lt;type&gt;(&lt;scope&gt;): &lt;subject&gt; // Subject Line
&lt;BLANK LINE&gt;               
&lt;body&gt;                     // Message Body
&lt;BLANK LINE&gt;               
&lt;footer&gt;                   // Message Footer</code></pre>
<p>커밋 메시지 형식은 다음과 같습니다. Subject Line이 있고, 빈줄, 그리고 Message body, 빈줄, 마지막으로 Message footer로 이루어집니다. 하나하나씩 살펴보겠습니다.</p>
<h2 id="subject-line">Subject Line</h2>
<p>변경사항에 대한 간단한 설명을 적는 줄입니다.</p>
<ul>
<li><type> : 커밋의 종류를 정하는 부분입니다.<ul>
<li><strong>허용된 <code>&lt;type&gt;</code></strong><ul>
<li>feat (feature) : 기능 구현</li>
<li>fix (bug fix) : 버그 수정</li>
<li>docs (documentation) : 문서 관련</li>
<li>style (formatting, missing semi colons, …) : 스타일 관련</li>
<li>refactor : 리팩토링 관련</li>
<li>test (when adding missing tests) : 테스트 관련</li>
<li>chore (maintain) : 빌드, 패키지 관련 혹은 그 외 자잘한 수정</li>
</ul>
</li>
</ul>
</li>
<li><scope> : 커밋 변경의 위치를 지정하는 것이면 어떤 것이든 쓸 수 있습니다. 그리고 생략 가능합니다.<ul>
<li>ex) $location, $browser, $compile, $rootScope, ngHref, ngClick, ngView</li>
<li>잘 이해가 안갈수도 있지만, 그냥 어디가 바뀌었는지에 대해 쓰면 됩니다. 어떤 기능이 바뀌었다면 그 기능을, 문서가 바뀌었다면 문서이름을 적으면 됩니다.</li>
</ul>
</li>
<li><subject> : 간단한 설명을 적는 부분입니다.<ul>
<li>subject 적는 룰<ul>
<li>명령형, 현재형을 사용해야 합니다.</li>
<li>첫 글자를 대문자로 쓰지 않아야 합니다.</li>
<li>끝에 점을 쓰지 않아야 합니다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="message-body">Message body</h2>
<ul>
<li>subject와 마찬가지로 명령형, 현재형을 사용해야 합니다.</li>
<li>변경한 이유와 변경 전과의 차이점을 기술합니다.</li>
<li>필수는 아닙니다.</li>
</ul>
<h2 id="message-footer">Message Footer</h2>
<p>footer에서는 주요 변경 사항과 어떤 이슈를 해결했는지에 대해 설명합니다.</p>
<h3 id="주요-변경-내역들-breaking-changes">주요 변경 내역들 (Breaking Changes)</h3>
<ul>
<li>모든 주요 변경 내역들은 다음과 함께 하단에 언급되어야 합니다.<ul>
<li>변경점</li>
<li>변경사유</li>
<li>마이그레이션 지시</li>
</ul>
</li>
</ul>
<h3 id="해결된-이슈-트래킹">해결된 이슈 트래킹</h3>
<p>이슈가 해결되면 footer에 다음과 같이 기록합니다. </p>
<pre><code class="language-jsx">Closes #1234 </code></pre>
<p>만약 이슈가 여러개라면 여러개를 붙여서 나열합니다.</p>
<h2 id="🐣-공부하면서-느낀점-및-회고">🐣 공부하면서 느낀점 및 회고</h2>
<p>지금까지 AnglarJS Commit Message Convention에 대해 알아봤습니다. 지금껏 정확하게 커밋 메세지 컨벤션을 정해놓고 커밋을 하지 않았습니다. 그저 Subject Line만 어설프게 따라했던 것 같은데, 앞으로는 이 규약을 잘 지키면서 커밋을 진행하려고 합니다. 또한 Scope와 Footer에 대해 모호한 개념이 있었는데, 잘 정리가 된 것 같습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] 디자인 패턴]]></title>
            <link>https://velog.io/@hoyoun_gg/CS-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@hoyoun_gg/CS-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sat, 31 Aug 2024 13:41:45 GMT</pubDate>
            <description><![CDATA[<h2 id="디자인-패턴이란">디자인 패턴이란?</h2>
<p>쉽게 말하면 프로그래밍을 설계할 때 자주 발생하는 오류들을 피하기 위해서 정해놓은 규약 이라고 의미한다.</p>
<p>디자인 패턴에 대해서 하나씩 알아보자</p>
<h3 id="1-싱글톤-패턴">1. 싱글톤 패턴</h3>
<p>싱글톤 패턴은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
즉, 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴임</p>
<ul>
<li>하나의 인스턴스를 만들어 놓고 해당 인스턴스를 다른 모듈들이 공유하여 사용</li>
<li>인스턴스 생성비용이 줄어드는 효과</li>
<li>그러나 의존성이 높아져 유연성이 떨어지는 효과 발생</li>
</ul>
<p>자바에서의 싱글톤 패턴 예시</p>
<ul>
<li>static 영역에 객체를 딱 1개만 생성</li>
<li>static 메서드로 객체 불러와서 사용하도록 함</li>
</ul>
<pre><code class="language-java">class Singleton {

    static final Singleton instance = new Singleton();

    private Singleton() {
        //초기화
    }

    public static Singleton getInstance() {
        return instance;
    }

}
</code></pre>
<h4 id="스프링에서의-싱글톤-패턴">스프링에서의 싱글톤 패턴</h4>
<p>스프링 컨테이너는 싱글톤 패턴으로 객체를 만들지 않아도 알아서 객체 인스턴스를 싱글톤으로 관리함</p>
<h4 id="싱글톤-방식의-주의점">싱글톤 방식의 주의점</h4>
<p>싱글톤 객체는 상태를 stateful하게 설계하면 안되고 stateless하게 설계해야 함</p>
<ul>
<li>특정 클라이언트에 의존적인 필드가 있으면 안됨</li>
<li>특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안됨</li>
<li>가급적 읽기만 가능해야함</li>
<li>필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal등을 사용해야 함</li>
<li><blockquote>
<p>스프링 빈의 필드에 공유 값을 설정하면 안된다!</p>
</blockquote>
</li>
</ul>
<h3 id="2-팩토리-패턴">2. 팩토리 패턴</h3>
<p>팩토리 패턴은 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴</p>
<p>즉, 상속관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴</p>
<h3 id="3-전략-패턴">3. 전략 패턴</h3>
<p>전략 패턴은 객체의 행위를 바꾸고 싶은 경우 직접 수정하지 않고 전략이라는 부르는 캡슐화한 알고리즘을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴</p>
<pre><code class="language-java">// 전략(추상화된 알고리즘)
interface IStrategy {
    void doSomething();
}

// 전략 알고리즘 A
class ConcreteStrateyA implements IStrategy {
    public void doSomething() {}
}

// 전략 알고리즘 B
class ConcreteStrateyB implements IStrategy {
    public void doSomething() {}
}</code></pre>
<ul>
<li><p>컨텍스트에서는 전략을 바꿀수 있게 함</p>
<pre><code class="language-java">// 컨텍스트(전략 등록/실행)
class Context {
  IStrategy Strategy; // 전략 인터페이스를 합성(composition)

  // 전략 교체 메소드
  void setStrategy(IStrategy Strategy) {
      this.Strategy = Strategy;
  }

  // 전략 실행 메소드
  void doSomething() {
      this.Strategy.doSomething();
  }
}</code></pre>
</li>
<li><p>클라이언트에서는 전략을 설정함</p>
<pre><code class="language-java">// 클라이언트(전략 교체/전략 실행한 결과를 얻음)
class Client {
  public static void main(String[] args) {
      // 1. 컨텍스트 생성
      Context c = new Context();

      // 2. 전략 설정
      c.setStrategy(new ConcreteStrateyA());

      // 3. 전략 실행
      c.doSomething();

      // 4. 다른 전략 설정
      c.setStrategy(new ConcreteStrateyB());

      // 5. 다른 전략 시행
      c.doSomething();
  }
}</code></pre>
</li>
</ul>
<h3 id="4-옵저버-패턴">4. 옵저버 패턴</h3>
<p>옵저버 패턴은 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴</p>
<p>자바에서의 옵저버 패턴</p>
<pre><code class="language-java">// 관찰 대상자 / 발행자
interface ISubject {
    void registerObserver(IObserver o);
    void removeObserver(IObserver o);
    void notifyObserver();
}

class ConcreteSubject implements ISubject {
    // 관찰자들을 등록하여 담는 리스트
    List&lt;IObserver&gt; observers = new ArrayList&lt;&gt;();

    // 관찰자를 리스트에 등록
    @Override
    public void registerObserver(IObserver o) {
        observers.add(o);
        System.out.println(o + &quot; 구독 완료&quot;);
    }

    // 관찰자를 리스트에 제거
    @Override
    public void removeObserver(IObserver o) {
        observers.remove(o);
        System.out.println(o + &quot; 구독 취소&quot;);
    }

    // 관찰자에게 이벤트 송신
    @Override
    public void notifyObserver() {
        for(IObserver o : observers) { // 관찰자 리스트를 순회하며
            o.update(); // 위임
        }
    }
}</code></pre>
<pre><code class="language-java">// 관찰자 / 구독자
interface IObserver {
    void update();
}

class ObserverA implements IObserver {
    public void update() {
        System.out.println(&quot;ObserverA 한테 이벤트 알림이 왔습니다.&quot;);
    }

    public String toString() { return &quot;ObserverA&quot;; }
}

class ObserverB implements IObserver {
    public void update() {
        System.out.println(&quot;ObserverB 한테 이벤트 알림이 왔습니다.&quot;);
    }

    public String toString() { return &quot;ObserverB&quot;; }
}</code></pre>
<h4 id="옵저버-패턴-사용-시기">옵저버 패턴 사용 시기</h4>
<ul>
<li>대상 객체의 상태가 변경될 때마다 다른 객체의 동작을 트리거해야 할 때</li>
<li>한 객체의 상태가 변경되면 다른 객체도 변경해야 할 때</li>
<li>MVC패턴에서도 사용됨</li>
</ul>
<h4 id="옵저버-패턴-장점">옵저버 패턴 장점</h4>
<ul>
<li>상태 변경을 주기적으로 조회할 필요 없이 자동으로 감지할 수 있음</li>
<li>런타임 시점에 pub/sub 관계 정의 가능</li>
<li>상태를 변경하는 객체와 변경을 감지하는 객체의 관계를 느슨하게 유지 가능</li>
</ul>
<h4 id="옵저버-패턴-단점">옵저버 패턴 단점</h4>
<ul>
<li>구독자는 알림 순서를 제어할 수 없고, 무작위 순서로 알림을 받음</li>
<li>코드 복잡도 증가와 메모리 누수 발생 가능성</li>
</ul>
<h3 id="5-프록시-패턴과-프록시-서버">5. 프록시 패턴과 프록시 서버</h3>
<p>프록시 패턴은 대상 원본 객체를 대리하여 대신 처리하게 함으로써 로직의 흐름을 제어하는 행동 패턴</p>
<p>그냥 객체를 사용하지 않는 이유는, 해당 클래스에 민감한 정보가 포함되어 있거나, 추가 기능을 가미하고 싶을 때, 원본 객체를 수정할 수 없는 상황을 극복하기 위해 사용</p>
<h4 id="프록시-패턴을-사용하여-얻는-효과">프록시 패턴을 사용하여 얻는 효과</h4>
<ul>
<li>보안</li>
<li>캐싱 : 데이터가 캐시에 아직 존재하지 않는 경우에만 작업 실행</li>
<li>데이터 유효성 검사</li>
<li>Lazy 초기화 : 실제로 필요로 할 때까지 연기</li>
<li>Logging</li>
<li>원격 객체</li>
</ul>
<p>자바에서의 프록시 패턴</p>
<pre><code class="language-java">interface ISubject {
    void action();
}

class RealSubject implements ISubject {
    public void action() {
        System.out.println(&quot;원본 객체 액션 !!&quot;);
    }
}

class Proxy implements ISubject {
    private RealSubject subject; // 대상 객체를 composition

    Proxy(RealSubject subject) {
        this.subject = subject;
    }

    public void action() {
        subject.action(); // 위임
        /* do something */
        System.out.println(&quot;프록시 객체 액션 !!&quot;);
    }
}

class Client {
    public static void main(String[] args) {
        ISubject sub = new Proxy(new RealSubject());
        sub.action();
    }
}</code></pre>
<h4 id="프록시-서버">프록시 서버</h4>
<p>서버와 클라이언트 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램 ( 예 : nginx)</p>
<p>nginx를 프록시 서버로 두면, 실제 포트를 숨길 수 있고 정적 자원을 gzip 압축하거나, 메인 서버 앞단에서의 로깅을 할 수 있음</p>
<h3 id="이터레이터-패턴">이터레이터 패턴</h3>
<p>이터레이터 패턴은 이터레이터를 사용하여 컬렉션의 요소들에 접근하는 디자인 패턴</p>
<h3 id="노출모듈-패턴">노출모듈 패턴</h3>
<p>노출모듈 패턴은 즉시 실행 함수를 통해 private, public 같은 접근 제어자를 만드는 패턴</p>
<p>자바 스크립트에서는 접근제어자가 존재하지 않고 전역 범위에서 스크립트가 실행되기 때문에 노출모듈 패턴을 이용해 private와 public 접근 제어자를 구현</p>
<h3 id="mvc-패턴">MVC 패턴</h3>
<p>모델, 뷰, 컨트롤러로 이루어진 디자인 패턴</p>
<ul>
<li>어플리케이션의 구성 요소를 세 가지 역할로 구분하여 개발 프로세스에서 각각의 구성 요소에만 집중해서 개발할 수 있음,</li>
<li>재사용성과 확장성이 용이함</li>
<li>어플리케이션이 복잡할수록 모델과 뷰의 관계가 복잡해지는 단점이 있음</li>
</ul>
<h4 id="모델">모델</h4>
<p>모델은 어플리케이션의 데이터인 데이터베이스, 상수, 변수 등을 뜻함</p>
<h4 id="뷰">뷰</h4>
<p>뷰는 inputbox, checkbox, textarea 등 사용자 인터페이스 요소를 나타냄. 즉, 모델을 기반으로 사용자가 볼 수 있는 화면</p>
<h4 id="컨트롤러">컨트롤러</h4>
<p>컨트롤러는 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할을 하며 이벤트 등 메인 로직을 담당.
또한 모델과 뷰의 생명주기도 관리하고, 변경사항을 해당 요소에 알려줌</p>
<h3 id="mvp-패턴">MVP 패턴</h3>
<p>mvp 패턴은 mvc 패턴에서 컨트롤러가 프레젠터로 바뀐 패턴임.
프레젠터는 모델과 뷰를 이어주는 역할을 하고, 뷰와 프레젠터는 일대일 관계이기 때문에 MVC패턴보다 더 강한 결합을 가짐.</p>
<h3 id="mvvm-패턴">MVVM 패턴</h3>
<p>MVVM 패턴은 MVC의 C에 해당하는 컨트롤러가 View Model로 바뀐 패턴임
View Model은 View를 위한 모델이자 View를 나타내기 위한 데이터 처리를 하는 부분
MVC 패턴과는 다르게 커맨드와 데이터 바인딩을 가짐. 뷰와 뷰 모델 사이의 양방향 데이터 바인딩을 지원하며 UI를 별도의 코드 수정 없이 재사용할 수 있고 단위 테스트 하기 쉬움</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 시큐리티]]></title>
            <link>https://velog.io/@hoyoun_gg/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0</link>
            <guid>https://velog.io/@hoyoun_gg/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0</guid>
            <pubDate>Tue, 28 Nov 2023 07:17:07 GMT</pubDate>
            <description><![CDATA[<h2 id="spring-security">Spring Security?</h2>
<p>스프링 기반의 애플리케이션 인증을 담당하는 스프링 하위 프레임워크.</p>
<ul>
<li>애너테이션 기반 설정</li>
<li>CSRF 공격(사용자의 권한을 가지고 특정 동작을 수행하도록 유도하는 공격) 방어</li>
<li>세션 고정 공격(사용자의 인증 정보 탈취 또는 변경) 방어</li>
<li>요청 헤더도 보안 처리</li>
</ul>
<h2 id="인증과-인가">인증과 인가</h2>
<ul>
<li>인증은 사용자의 신원을 입증하는 과정<ul>
<li>ex) 사용자가 사이트에 로그인을 할때 확인하는 과정</li>
</ul>
</li>
<li>인가는 사이트의 특정 부분에 접근할 수 있는지에 권한을 확인하는 작업<ul>
<li>사이트의 특정 부분에 접근할 수 있는지에 권한을 확인하는 작업</li>
</ul>
</li>
</ul>
<h3 id="필터-기반으로-동작하는-스프링-시큐리티">필터 기반으로 동작하는 스프링 시큐리티</h3>
<p><img src="https://velog.velcdn.com/images/hoyoun_gg/post/c028ece7-f955-4ad0-b9b9-9a103ef75ee2/image.png" alt=""></p>
<p>다양한 필터들로 나누어져 있고, 각 필터에서 인증, 인가와 관련된 작업을 처리
<em>SecurityContextPersistenceFilter</em> 부터 시작해서 아래로 내려가며 
<em>FilterSecurityInterceptor</em> 까지 순서대로 필터를 거침</p>
<ul>
<li><em>UsernamePasswordAuthentication</em> : 아이디와 패스워드가 넘어오면 인증 요청을 위임하는 인증 관리자 역할</li>
<li><em>FilterSecurityInterceptor</em> : 권한 부여 처리를 위임해 접근 제어 결정을 쉽게 하는 접근 결정 관리자 역할</li>
</ul>
<h2 id="spring-security-인증-진행-절차">Spring Security 인증 진행 절차</h2>
<p><img src="https://velog.velcdn.com/images/hoyoun_gg/post/996dc8d4-9103-4ec7-91e3-ee2d951c387b/image.png" alt=""></p>
<ol>
<li>사용자가 폼에 아이디와 패스워드를 입력하면, HTTPServeletRequest에 아이디와 비밀번호 정보가 전달
이때 <em>AuthenticationFilter</em> 가 넘어온 아이디와 비밀번호의 유효성 검사를 함.</li>
<li>유효성 검사가 끝나면 실제 구현체인 <em>UsernamePasswordAuthenticatonToken</em> 을 만들어서 넘겨줌</li>
<li>전달받은 객체를 <em>AuthenticationManager</em> 에게 보냄</li>
<li><em>AuthenticationManager</em> 가 그 객체를 <em>AuthenticationProvider</em> 에게 보냄</li>
<li>사용자 아이디를 <em>UserDetailService</em> 에 보냄. <em>UserDetailService</em> 는 사용자 아이디로 찾은 사용자 정보를 <em>UserDetail</em> 객체로 만들어 _AuthenticationProvider_에게 전달</li>
<li>DB에 있는 사용자 정보를 가져옴</li>
<li>입력 정보와 UserDetails의 정보를 비교해 실제 인증 처리를 함
8~10 까지 인증이 완료되면 <em>SecurityContextHolder</em> 에 <em>Authentication</em> 을 저장
성공하면 <em>AuthenticationSuccessHandler</em> 를 실행, 실패하면 <em>AuthenticationFailureHandler</em> 를 실행</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] Generics]]></title>
            <link>https://velog.io/@hoyoun_gg/Java-Generics</link>
            <guid>https://velog.io/@hoyoun_gg/Java-Generics</guid>
            <pubDate>Tue, 07 Nov 2023 08:01:44 GMT</pubDate>
            <description><![CDATA[<h2 id="지네릭스란">지네릭스란?</h2>
<ul>
<li>다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입체크를 해주는 기능이다.</li>
<li>객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.<h2 id="지네릭-클래스의-선언">지네릭 클래스의 선언</h2>
</li>
</ul>
<p>클래스 옆에 &lt; T &gt; 를 붙이면 지네릭 클래스가 됨.</p>
<pre><code class="language-java">class Box&lt;T&gt;{
    T item;
    void setItem(T item) {this.item = item;}
    T getItem();
}</code></pre>
<p>이 의미는 만약 아래와 같이 사용하게 된다면,</p>
<pre><code class="language-java">Box&lt;String&gt; b = new Box&lt;String&gt;();</code></pre>
<p>T 타입을 String 으로 지정해 줬으므로</p>
<pre><code class="language-java">class Box{
    String item;
    void setItem(String item) {this.item = item;}
    String getItem();
}</code></pre>
<p>이와 같이 정의된 것으로 됨.</p>
<h2 id="지네릭스의-제한">지네릭스의 제한</h2>
<ul>
<li>static멤버에 타입 변수 T를 사용할 수 없음.</li>
<li>지네릭 타입의 배열을 생성하는 것도 허용되지 않음. (new T[10] 이런게 안된다는 것.)<ul>
<li>new 연산자 때문인데, 이 연산자는 컴파일 시점에 타입 T가 뭔지 정확히 알아야 된다.</li>
<li>꼭 지네릭 배열을 생성해야 하면 Reflection API의 newInstance()를 사용</li>
</ul>
</li>
</ul>
<h2 id="제한된-지네릭-클래스">제한된 지네릭 클래스</h2>
<pre><code class="language-java">class FruitBox&lt;T extends Fruit&gt; {
    ArrayList&lt;T&gt; list = new ArrayList&lt;T&gt;();
    ...
}</code></pre>
<p>다음과 같이 지네릭 타입에 &#39;extends&#39; 를 사용하면, 특정 타입의 자손들만 대입할 수 있게 제한할 수 있음</p>
<p>만일 클래스가 아니라 인터페이스를 구현해야 한다는 제약이 필요하다면 마찬가지로 &#39;extends&#39; 사용</p>
<p>클래스의 자손이면서 인터페이스도 구현해야 한다면 아래와 같이 &#39;&amp;&#39; 기호로 사용</p>
<pre><code class="language-java">class FruitBox&lt;T extends Fruit &amp; Eatable&gt; {...}</code></pre>
<h2 id="와일드-카드">와일드 카드</h2>
<p>와일드 카드는 어떠한 타입도 될 수 있고, &#39;?&#39;로 표현함.</p>
<blockquote>
<p>&lt; ? extends T &gt; 와일드 카드의 상한 제한. T와 그 자손들만 가능
&lt; ? super T &gt; 와일드 카드의 하한 제한. T와 그 조상들만 가능
&lt; ? &gt; 제한 없음. 모든 타입이 가능</p>
</blockquote>
<p>이를 이용하면 지네릭 클래스가 아닌 클래스의 스태틱 메서드에 지네릭 타입의 클래스를 선언이 가능하게 됨.</p>
<h2 id="지네릭-메서드">지네릭 메서드</h2>
<p>메서드의 선언부에 지네릭 타입이 선언된 메서드를 지네릭 메서드라고 함.</p>
<pre><code class="language-java">static &lt;T&gt; void sort(List&lt;T&gt; list, &lt;Comparator&lt;? super T&gt; c)</code></pre>
<p>static 멤버에는 타입 매개변수를 사용할 수 없지만, 위와 같이 static 메서드에 지네릭 타입을 선언하고 사용하는 것은 가능.</p>
<h2 id="지네릭-타입의-제거">지네릭 타입의 제거</h2>
<p>컴파일러는 지네릭 타입을 이용해 소스파일을 체크하고 필요한 곳에 형변환을 넣어줌. 그리고 지네릭 타입을 제거.</p>
<blockquote>
<p>즉 컴파일 된 파일에는 지네릭 타입에 대한 정보가 없음</p>
</blockquote>
<p>참고 : &lt;Java의 정석&gt;</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] Enum]]></title>
            <link>https://velog.io/@hoyoun_gg/JAVA-Enum</link>
            <guid>https://velog.io/@hoyoun_gg/JAVA-Enum</guid>
            <pubDate>Mon, 06 Nov 2023 16:55:16 GMT</pubDate>
            <description><![CDATA[<h2 id="열거형이란">열거형이란?</h2>
<ul>
<li>서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용함</li>
<li>C언어에서는 타입이 달라도 값이 같으면 조건식결과가 참이였지만, 자바의 열거형은 값이 같아도 타입이 다르면 컴파일 에러가 발생</li>
<li>따라서 equals()로 비교 안하고 &quot;==&quot;으로 비교가 가능</li>
<li>상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일 해야 하지만, 열거형을 쓰면 열거형만 컴파일 하면 됌<h2 id="사용법">사용법</h2>
<pre><code class="language-java">enum 열거형이름 { 상수명 1, 상수명 2, ...}</code></pre>
<h2 id="enum-메서드">Enum 메서드</h2>
</li>
<li><strong>getDeclaringClass()</strong> - 열거형의 Class 객체를 반환한다.</li>
<li><strong>name()</strong> - 열거형 상수의 이름을 문자열로 반환한다.</li>
<li><strong>ordinal()</strong> - 열거형 상수가 정의된 순서를 반환한다.</li>
<li><strong>valueOf(Class&lt; T &gt; enumType)</strong> - 지정된 열거형에서 name과 일치하는 열거형 상수 반환</li>
</ul>
<h2 id="열거형에-멤버-추가하기">열거형에 멤버 추가하기</h2>
<pre><code class="language-java">enum Driection {
    EAST(1,&quot;&gt;&quot;), SOUTH(2,&quot;V&quot;), ...
    Direction(int value, String symbol){
        this.value = value;
        this.symbol = symbol;
    }
}</code></pre>
<p>위와 같이 하나의 열거형 상수에 여러값을 추가할 수 있다. 다만 그에 맞게 생성자를 넣어줘야 함.</p>
<h2 id="열거형의-이해">열거형의 이해</h2>
<p>열거형이 내부적으로 어떻게 구현되어 있는가에 대한 이해</p>
<pre><code class="language-java">enum Direction{ EAST, SOUTH, WEST, NORTH}</code></pre>
<p>열거형이 위와 같이 정의되어 있을 때, 사실은 열거형 상수 하나하나가 Direction 객체이다.</p>
<pre><code class="language-java">class Direction{
    static final Direction EAST = new Direction(&quot;EAST&quot;)
    ...
}</code></pre>
<p>위와 같이 static 객체로 선언되어 있고, 각각의 값은 객체의 주소이므로 &quot;==&quot;비교가 가능해진다는 것이다.</p>
]]></description>
        </item>
    </channel>
</rss>