<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>taemin-steve.log</title>
        <link>https://velog.io/</link>
        <description>Hi~</description>
        <lastBuildDate>Sun, 20 Oct 2024 06:34:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>taemin-steve.log</title>
            <url>https://velog.velcdn.com/images/taemin-steve/profile/96781c03-f3f8-44a8-9f9a-4342d606e7fc/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. taemin-steve.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/taemin-steve" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[MISC]]></title>
            <link>https://velog.io/@taemin-steve/MISC</link>
            <guid>https://velog.io/@taemin-steve/MISC</guid>
            <pubDate>Sun, 20 Oct 2024 06:34:52 GMT</pubDate>
            <description><![CDATA[<h2 id="1-memento-pattern">1. Memento Pattern</h2>
<blockquote>
<p>** 1.1. 의도 **</p>
</blockquote>
<ul>
<li>캡슐화(외부에서 맴버 변수의 값을 변경할 수 없도록 함)를 위배하지 않으면서 <strong><span style= "color: #FF7518;"> 객체 내부의 상태를 캡슐화 해서 저장하고, 나중에 객체가 해당 상태로 복구</span></strong> 가능하도록 한다. <img src="https://velog.velcdn.com/images/taemin-steve/post/7be906ed-c294-4d00-b072-7662f378dd69/image.png" alt=""></li>
</ul>
<hr>
<p>** 1.2. 예제 ** </p>
<ul>
<li>Memento 구조체를 생성하여 필수 정보 저장 </li>
<li>이후 Save()와 Restore()를 통해서 저장 복구 가능<pre><code class="language-cpp">#pragma once
#include &lt;map&gt;
&gt;
enum color { red = 1, green = 2, blue = 3};
&gt;
class Graphic
{
  struct Memento
  {
      int penWidth;
      int penColor;
      Memento(int w, int c) : penWidth(w), penColor(c) {}
  };
  std::map&lt;int, Memento*&gt; memento_map; 
&gt;
  int penWidth = 1;
  int penColor = 0;
  int temporary_data;
public:
&gt;
  int save()
  {
      static int key = 0;
      ++key;
&gt;
      Memento* p = new Memento(penWidth, penColor);
      memento_map[key] = p;
&gt;
      return key;
  }
  &gt;
  void restore(int token)
  {
      penColor = memento_map[token]-&gt;penColor;
      penWidth = memento_map[token]-&gt;penWidth;
  }
&gt;
  void draw_line(int x1, int y1, int x2, int y2)
  {
  }
  void set_stroke_color(int c) { penColor = c; }
  void set_stroke_width(int w) { penWidth = w; }
};</code></pre>
</li>
</ul>
<hr>
<p>뭔가를 그리는 상황에서 모든 변경값을 함수 인자로 받아와서 진행도 가능하지만, 객체에 저장된 기본정보를 수정하게 하고, 함수에서는 객체의 기본정보를 활용할 수도 있음 </p>
<h2 id="2-state-pattern">2. State Pattern</h2>
<blockquote>
<p>사실상 Strategy Pattern과 동일하지만, 알고리즘을 교체할 때는 Strategy, 상태는 동작을 변경하는 경우 State로 명명 한다.</p>
</blockquote>
<h2 id="3-builder-pattern">3. Builder Pattern</h2>
<blockquote>
<p>Strategy Pattern과 동일하지만, 객체를 생성하는 관점에서는 Builder는 객체를 변경하는 경우에 적용하는 개념이라고 생각하면 된다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체를 생성하는 방법]]></title>
            <link>https://velog.io/@taemin-steve/%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@taemin-steve/%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 16 Oct 2024 13:59:41 GMT</pubDate>
            <description><![CDATA[<h2 id="1-singleton-pattern">1. Singleton Pattern</h2>
<blockquote>
<p>** 1.1 의도 **</p>
</blockquote>
<ul>
<li>클래스의 인스턴스는 <strong><span style= "color: #FF7518;"> 오직 하나임</span></strong>을 보장하며 어디에서나 <strong><span style= "color: #FF7518;">동일한 방법</span></strong>으로 접근 하는 방법을 제공. <img src="https://velog.velcdn.com/images/taemin-steve/post/ab0dcdf5-a00b-4cde-b34c-a3d5c94c6bdb/image.png" alt=""></li>
<li>단점과 비판 <ul>
<li>전역변수와 유사하다. </li>
<li>멀티스레드간의 접근 문제 </li>
<li>객체간의 결합도가 증가하고 재사용성이 감소한다. </li>
</ul>
</li>
<li>그럼에도 많은 오픈소스에서 애용하는 패턴이다. </li>
</ul>
<hr>
<p>** 1.2. 규칙 ** </p>
<ul>
<li>외부에서는 객체를 생성할 수 없어야 한다. &gt;&gt; private 생성자를 활용 </li>
<li>한 개의 객체는 만들수 있어야 한다. &gt;&gt; 오직 한개의 객체를 만들어서 반환하는 static 맴버 함수를 사용 </li>
<li>복사 생성자도 사용할 수 없어야 한다 &gt;&gt; 복사/대입을 금지 (= delete)</li>
</ul>
<hr>
<p><strong><span style= "color: #FF7518;"> 1.3. Meyer&#39;s singleton  </span></strong> </p>
<ul>
<li>오직 <strong>한개의 객체를 static 지역변수</strong>로 생성</li>
<li><strong>지연된 초기화</strong> : get_instance()를 호출할 때 초기화 된다. 사용하지 않으면 생성자가 호출되지 않고, 메모리를 사용하지 않는다. </li>
<li><strong>thread-safe</strong> : static 지역 변수이기 때문에 가능<pre><code class="language-cpp">class Cursor
{
private:
  Cursor() 
  {
      std::cout &lt;&lt; &quot;start  Cursor()&quot; &lt;&lt; std::endl;
      std::this_thread::sleep_for(3s); // 3초가 걸린다고 하더라도 늦게 도착한 애들은 앞의 생성자가 생성될 때까지 대기한다. 
      std::cout &lt;&lt; &quot;finish Cursor()&quot; &lt;&lt; std::endl;        
  }
  Cursor(const Cursor&amp; ) = delete;
  Cursor&amp; operator=(const Cursor&amp;) = delete;
&gt;
public:
  static Cursor&amp; get_instance()
  {
      std::cout &lt;&lt; &quot;start  get_instance&quot; &lt;&lt; std::endl;
      static Cursor instance;
      std::cout &lt;&lt; &quot;finish get_instance&quot; &lt;&lt; std::endl;
      return instance;
  }
};</code></pre>
</li>
</ul>
<hr>
<p>** 1.4. Heap 영역에 singleton을 생성하는 방법 **</p>
<ul>
<li>멀티스레드 접근에 안전하기 위해서 동기화가 필요 &gt;&gt; <strong><span style= "color: #FF7518;"> lock_guard를 통해서 동기화</span></strong>가 가능하다. <ul>
<li>직접적으로 lock을 걸어주는 코드는 좋은 코드가 아닌다 ( mutex를 통해서 lock을 해주는 경우 lock이 걸린 상태로 예외가 발생하면, lock 을 해제하지 못하는 경우 발생)</li>
<li>lock_guard를 사용하는 경우 생성자에서 자동으로 lock을 해줌</li>
<li>만약 예외가 발생하더라도 cpp에서는 예외 발생시 지역변수는 안전하게 파괴되며, lock_guard 소멸자에서 lock을 안전하게 해제할 수 있음</li>
<li>{}을 통해서 lock을 빨리 해제하는 방법도 존재(지역을 벗어나면 소멸자가 불림)<pre><code class="language-cpp">class Cursor
{
private:
Cursor() {}
Cursor(const Cursor&amp; ) = delete;
Cursor&amp; operator=(const Cursor&amp;) = delete;
&gt;
static std::mutex m;
static Cursor* instance;
public:
static Cursor&amp; get_instance()
{        
  std::lock_guard&lt;std::mutex&gt; g(m); // g의 생성자에서 m.lock()
&gt;
  // m.lock();
  if ( instance == nullptr )
      instance = new Cursor;
  // m.unlock();
  &gt;
  return *instance;
}
};
Cursor* Cursor::instance = nullptr;
std::mutex Cursor::m;</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<p>** 1.5. Double Check Locking Pattern (DCLP)**</p>
<ul>
<li>위의 코드와 같이 진행하는 경우 이미 Singleton객체가 생성된 후 불러오기만 할때도 불필요하게 lock을 걸고 해제하는 과정이 존재 </li>
<li>이를 해결하기 위해 DCLP를 아래와 같이 사용 가능 <pre><code class="language-cpp">static Cursor&amp; get_instance()
  {
      if ( instance == nullptr )
      {
          m.lock();
&gt;
          if ( instance == nullptr )
          {
              instance = new Cursor;
&gt;
          //    instance = Cursor 크기 메모리할당;
          //    Cursor::Cursor();
          }
&gt;
          m.unlock();
      }</code></pre>
</li>
<li>위와 같이 진행하면 이미 singleton 객체가 존재하는 경우 lock 없이 진행가능하나, CPP에서는 해당 방식은 오류로 정의됨. </li>
<li>컴파일러가 최적화하면서 위의 주석과 같은 일이 발생하여 아직 초기화가 끝나지 않았는데도 instance는 메모리 주소가 할당되어 있음<img src="https://velog.velcdn.com/images/taemin-steve/post/e3085ef2-c22c-48e4-b042-8b3ce229bdfd/image.png" alt=""></li>
<li>따라서 Cursor::Cursor()가 오래걸리는 경우 아직 초기화가 끝나지 않았는데 다시 접근을 한다면 intance는 nullptr이 아니기에 <strong><span style= "color: #FF7518;"> 초기화되지 않은 intance 주소를 전달함.</span></strong> </li>
<li>Double-Checked Locking is Fixed in C++11에서 해결되었음 </li>
</ul>
<hr>
<p>*<em>1.6. Singleton 코드를 재사용하는 방법 *</em> </p>
<ul>
<li><strong><span style= "color: #FF7518;"> 매크로를 활용하는 방법 </span></strong><pre><code class="language-cpp">#define MAKE_SINGLETON(classname)            \
private:                                    \
  classname() {}                            \
  classname(classname&amp;) = delete;            \
  void operator=(classname&amp;) = delete;    \
public:                                        \
  static classname&amp; getInstance()            \
  {                                        \
      static classname instance;            \
      return instance;                    \
  }                                        \
private:// 요게 있어주는게 좋음. 디폴트가 private으로 끝나게 지정해 주는 구조 
#include &quot;singleton.h&quot;
&gt;
class Cursor
{
  MAKE_SINGLETON(Cursor)
};</code></pre>
</li>
<li><strong><span style= "color: #FF7518;"> 상속을 활용하는 방법 </span></strong></li>
<li><strong>CRTP(Curiously Recurring Template Pattern)</strong> : 기반 클래스에서 미래에 만들어질 파생 클래스의 이름을 사용할 수 있게 하는 기술 </li>
<li>상속 받아서 사용할 수 있도록 생성자는 private이 아닌 protected에 위치 </li>
<li>intance와 mutex 객체를 만들때도 template|&lt; typename T&gt;로 선언해 주어야함 <pre><code class="language-cpp">template&lt;typename T&gt; //CRTP라는 방법 
class Singleton
{
protected:
  Singleton() {} // 싱속 받아서 사용할 수 있도록 변경해 주었음 
private:    
  Singleton(const Singleton&amp; ) = delete;
  Singleton&amp; operator=(const Singleton&amp;) = delete;
  &gt;
  static std::mutex m;
  static T* instance;
public:
  static T&amp; get_instance()
  {        
      std::lock_guard&lt;std::mutex&gt; g(m);
      if ( instance == nullptr )
          instance = new T; // 전달받은 Type의 객체가 생성됨
      return *instance;
  }
};
template&lt;typename T&gt; T* Singleton&lt;T&gt;::instance = nullptr; //T는 위의 클래스 내에서만 토용되므로 다음과같이 적어주어야 함 
template&lt;typename T&gt; std::mutex Singleton&lt;T&gt;::m;
&gt;
class Mouse : public Singleton&lt; Mouse &gt; // 상속을 통해서 싱글톤 코드를 재사용하는 방법도 가능
{};</code></pre>
</li>
</ul>
<h2 id="2-flyweight-pattern">2. flyweight pattern</h2>
<blockquote>
<p>*<em>2.1. 의도 *</em></p>
</blockquote>
<ul>
<li>속성이 동일한 <strong><span style= "color: #FF7518;"> 객체를 공유</span></strong>하게 한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/54c3b99e-5bfd-418d-b7a1-dc3d3b1a8dff/image.png" alt=""></li>
<li>Word에서 폰트 값은 동일하지만 값만 다른 수많은 객체들이 존재함</li>
<li>이때 일일이 동일한 속성의 font를 따로 저장하게 되면 메모리 소모가 크기 때문에, flyweight 패턴을 적용하여 <strong><span style= "color: #FF7518;"> 동일한 속성 값은 한개만 </span></strong> 생성하여 공유한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/c3a5b6eb-6be6-4519-8087-5dc7dadcabf9/image.png" alt=""></li>
</ul>
<hr>
<p>*<em>2.2. 예제 *</em></p>
<ul>
<li>생성자는 private에 두고, 자신을 생성하는 함수를 factory에서 생성 (<strong><span style= "color: #FF7518;"> friend class </span></strong> 로 지정하여 private에 접근 가능함 / cpp에서만 friend지원)</li>
<li>factory는 그동안 생성한 객체의 속성을 기억하는 map을 생성하고 <strong><span style= "color: #FF7518;"> 중복하지 않는 경우에만 새로 생성</span></strong>.<pre><code class="language-cpp">class Image
{
  std::string image_url;
&gt;
  Image(const std::string&amp; url) : image_url(url)
  {
      std::cout &lt;&lt; url &lt;&lt; &quot; Downloading...\n&quot;;
  }
public:
  void draw() 
  { 
      std::cout &lt;&lt; &quot;draw &quot; &lt;&lt; image_url &lt;&lt; &#39;\n&#39;;
  }
  friend class ImageFactory; // 친구는 private에 접근할 수 있음
  //cpp에는 가능하지만 다른곳에서는 안되는 코드임. 
};
&gt;
class ImageFactory
{
  std::map&lt;std::string, Image*&gt; image_map;
public:
  Image* create(const std::string&amp; url)
  {
      Image* img;
      auto ret = image_map.find(url);
      &gt;
      if (ret == image_map.end())
      {
          img = new Image(url);
          image_map[url] = img;
      }
      return image_map[url];
  }
};</code></pre>
</li>
</ul>
<hr>
<p>** 2.3 핵심정리 **</p>
<ul>
<li>Singleton pattern은 class에 대하여 단 한개의 객체를 생성하지만, flyweight은 class의 맴버 변수의 값이 다르다면 여러번 생성할 수 있다.</li>
<li>결국 하나의 객체 안에 동일한 값들을 중복적으로 저장하는 것을 막는 pattern 이다. </li>
</ul>
<h2 id="3-factory-pattern">3. Factory Pattern</h2>
<blockquote>
<p>*<em>3.1. 기원 *</em></p>
</blockquote>
<ul>
<li>정통적인 Design Pattern에 factory는 없다. Abstract Facotry만 존재하지만, Abstract Factory를 이해하기 위해서 factory를 먼저 이해하는 것이 유리. </li>
</ul>
<hr>
<p>** 3.2. 예제 ** </p>
<ul>
<li>새로운 도형이 추가되더라도, <strong><span style= "color: #FF7518;"> Client의 코드는 변경이 없는 구조</span></strong>로 구현함.</li>
<li>Factory를 통해서 객체를 생성<ul>
<li><strong><span style= "color: #FF7518;"> 동일한 곳에서 객체를 생성 </span></strong> 하기에 한곳에서만 관리하여 추가되더라도 factory의 수정만으로 변경 가능(큰 시스템에서는 main이 아닌 다른 곳에서 객체를 생성할 수도 있음)</li>
<li>static 맴버 함수를 통한 객체 생성 : cpp에서는 클래스의 이름을 자료형에 보관이 불가능하지만, <strong><span style= "color: #FF7518;"> 클래스를 생성하는 생성함수는 자료구조에 보관 할 수 있음.</span></strong>  <img src="https://velog.velcdn.com/images/taemin-steve/post/faa87f4d-c216-4755-81a8-d39be97d1fe6/image.png" alt=""><pre><code class="language-cpp">class Shape // 업케스팅으로 동일한 방식으로 create을 할수 있게 해줌
{
public:
virtual void draw() = 0;
virtual ~Shape() {}
};
&gt;
class ShapeFactory // 모양을 찍어내는 공장
{
MAKE_SINGLETON(ShapeFactory) // 싱글턴 구조를 활용하여 단 한개만 생성할수 있게 보장
&gt;
using F = Shape*(*)(); // Shpae 내의 어떤 함수를 포인터로 받아오겠다. 
&gt;
std::map&lt;int, F&gt; create_map; 
&gt;
public:
&gt;
void register_shape(int key, F create_function) // 
{
    create_map[key] = create_function;
}
&gt;
Shape* create(int type)
{
    Shape* p = nullptr;
&gt;
    if (create_map[type] != nullptr)
    {
        p = create_map[type](); // map에 등록해뒀던 입력받은 타입 객체를 생성하는 함수가 호출됨
    }
    return p;
}
};
&gt;
class RegisterFactory // 등록해주는 factory
{    
public:
RegisterFactory(int type, Shape* (*f)())
{
&gt;        ShapeFactory::get_instance().register_shape(type, f);
}
};
&gt;
&gt;
#define REGISTER(classname)                        \
static Shape* create() { return new classname; }    \
static RegisterFactory rf; // static으로 불러 동일한 RegisterFactory에 항상 접근 하겠다
&gt;
#define REGISTER_IMPL(type, classname)            \
RegisterFactory classname::rf(type, &amp;classname::create);
&gt;
class Rect : public Shape
{
public:
void draw() override { std::cout &lt;&lt; &quot;draw Rect&quot; &lt;&lt; std::endl; }
&gt;
REGISTER(Rect)
};
REGISTER_IMPL(1, Rect)
&gt;
int main()
{
std::vector&lt;Shape*&gt; v;
&gt;
ShapeFactory&amp; factory = ShapeFactory::get_instance();
&gt;
while (1)
{
    int cmd;
    std::cin &gt;&gt; cmd;
&gt;
    if (cmd &gt; 0 &amp;&amp; cmd &lt; 8)
    {
        Shape* s = factory.create(cmd);
&gt;
        if ( s )
            v.push_back(s);
    }
    else if (cmd == 9)
    {
        for (auto s : v)
            s-&gt;draw();
    }
}
}</code></pre>
</li>
</ul>
</li>
<li>각 도형은 동일한 Registor Factory에 자신을 생성하는 함수를 등록</li>
<li>Registor Factory는 Shape Factory를 초기화하고, 해당 Factory의 Map(key = 입력받을 값 / value = 생성 함수)에 값을 저장 (이때 Factory는 처음 초기화되며 Singleton구조를 가지고 있음)</li>
<li>factory의 create 함수에서 각각의 도형들이 Pointer로 생성되어 Return. </li>
</ul>
<h2 id="4-prototype-pattern">4. Prototype Pattern</h2>
<blockquote>
<p>** 3.1. 의도 **</p>
</blockquote>
<ul>
<li>견본적(porotypical) 인스턴스를 사용하여 생성할 객체의 종류를 명시하고, <strong><span style= "color: #FF7518;"> 견본을 복사하여 새로운 객체를 생성 </span></strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/e0e17234-1905-4710-93df-bfeb228a05c6/image.png" alt=""></li>
<li>같은 클래스더라도 Blue circle, Red Circle과 같이 특정 속성이 다르다면 미리 해당 객체를 생성해두고 복사하여 사용 가능</li>
</ul>
<hr>
<p>** 3.2. 예제 ** </p>
<ul>
<li>Factory는 생성 함수를 등록했다면, Prototype은 객체를 등록</li>
<li>Map 또한 실제 객체를 저장.<pre><code class="language-cpp">class ShapeFactory
{
  MAKE_SINGLETON(ShapeFactory)
&gt;
  std::map&lt;int, Shape*&gt; prototype_map; 
public:
  void register_sample(int key, Shape* sample)
  {
      prototype_map[key] = sample;
  }
&gt;
  Shape* create(int type)
  {
      Shape* p = nullptr;
&gt;
      if (prototype_map[type] != nullptr)
      {
          p = prototype_map[type]-&gt;clone(); // 복사해서 사용
      }
      return p;
  }
};
int main()
{
  std::vector&lt;Shape*&gt; v;
  ShapeFactory&amp; factory = ShapeFactory::get_instance();
&gt;
  Rect* red_rect = new Rect; 
  Rect* blue_rect = new Rect; 
  Circle* blue_circle = new Circle;
&gt;
  // 자주 사용하는 객체를 등록
  factory.register_sample( 1, red_rect);
  factory.register_sample( 2, blue_rect);
  factory.register_sample( 3, blue_circle);
&gt;
  while (1)
  {
      int cmd;
      std::cin &gt;&gt; cmd;
&gt;
      if (cmd &gt; 0 &amp;&amp; cmd &lt; 8)
      {
          Shape* s = factory.create(cmd);
          if ( s )
              v.push_back(s);
      }
      else if (cmd == 9)
      {
          for (auto s : v)
              s-&gt;draw();
      }
  }
}
</code></pre>
</li>
</ul>
<h2 id="5-abstract-factory">5. Abstract factory</h2>
<blockquote>
<p>** 5.1. 의도 **</p>
</blockquote>
<ul>
<li>상세화된 서브 클래스를 정의하지 않고 서로 관련성이 있거나 독립적인 여러 객체군을 생성하기 위한 인터페이스를 제공 </li>
<li>결국 <strong><span style= "color: #FF7518;"> Factory의 Interface를 둬</span></strong>서 어떤 제품이 생성되든지 동일한 코드로 생성하게 하자! 
<img src="https://velog.velcdn.com/images/taemin-steve/post/ee3bdf6d-fdae-4cc3-95f9-cecf9c461b02/image.png" alt=""></li>
</ul>
<hr>
<p>** 5.2. 예제 ** </p>
<ul>
<li>게임 엔진은 다양한 플랫폼(PC, 모바일, 콘솔 등)을 지원해야 하며, 각 플랫폼에 맞는 그래픽 렌더러, 오디오 시스템, 입력 장치 터페이스를 제공해야함 </li>
<li>추상 팩토리 패턴을 통해 플랫폼별로 서로 다른 시스템을 생성하지만, 클라이언트(게임 로직)에서는 이 모든 것을 동일한 인터페이스를 통해 접근할 수 있음 ex( GraphicsFactory는 플랫폼에 맞는 그래픽 시스템(DirectXRenderer, OpenGLRenderer, VulkanRenderer)을 생성)<pre><code class="language-cpp">class RichControlFactory : public IControlFactory
{
public:
  IButton* create_button() { return new RichButton; }
  IEdit*   create_edit() { return new RichEdit; }    
};
&gt;
class SimpleControlFactory : public IControlFactory
{
public:
  IButton* create_button() { return new SimpleButton; }
  IEdit*   create_edit() { return new SimpleEdit; }
};
&gt;
int main(int argc, char** argv)
{
  IControlFactory* factory;
&gt;
  if (strcmp(argv[1], &quot;-style:rich&quot;) == 0)
      factory = new RichControlFactory;
  else
      factory = new SimpleControlFactory;
&gt;
  IButton* btn = factory-&gt;create_button();
  &gt;
  btn-&gt;draw();
}</code></pre>
</li>
</ul>
<hr>
<p>**<span style= "color: #FF7518;"> 동일한 기능을 가진 서로 다른 제품군이 있을때 유용.</span> **</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[통보, 열거, 반복문]]></title>
            <link>https://velog.io/@taemin-steve/%ED%86%B5%EB%B3%B4-%EC%97%B4%EA%B1%B0-%EB%B0%98%EB%B3%B5%EB%AC%B8</link>
            <guid>https://velog.io/@taemin-steve/%ED%86%B5%EB%B3%B4-%EC%97%B4%EA%B1%B0-%EB%B0%98%EB%B3%B5%EB%AC%B8</guid>
            <pubDate>Sat, 12 Oct 2024 07:50:31 GMT</pubDate>
            <description><![CDATA[<h2 id="1-observer-pattern">1. Observer pattern</h2>
<blockquote>
<p>** 1.1. 의도 **</p>
</blockquote>
<ul>
<li>객체 사이의 <strong><span style= "color: #FF7518;"> 1:N의 종속성을 정의 하고 한 객체의 상태가 변하면 종속된 다른 객체들의 통보가 가고 자동으로 수정</span></strong>이 일어나게 한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/6dcba1a5-4d9d-48af-8fa3-28a060b74547/image.png" alt=""></li>
<li>정보를 보관하는 클래스에서 정보를 필요로 하는 클래스들을 기억하고, 변화가 발생하면 모두에거 notify해준다. </li>
<li>Subject에서 기본적인 attach, detach, notify를 구현하고, 이를 상속받는 클래스에서 필요한 데이터 타입만을 관리.</li>
</ul>
<h2 id="2-iterator">2. Iterator</h2>
<blockquote>
<p>** 2.1. 의도 **</p>
</blockquote>
<ul>
<li>컨테이너의 내부 구조를 노출하지 않고도, 동일한 방법으로 모든 요소에 순차적으로 접근할 수 있게 하자. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/fb2696ef-49d7-4e39-a658-9867fe2fbb0e/image.png" alt=""></li>
</ul>
<hr>
<p>** 2.2. 인터페이스 기반의 설계 **</p>
<ul>
<li>모든 Iterator의 사용법이 동일하기 위해서 Iterator의 인터페이스가 필요</li>
<li>반복 가능한 컨테이너 Enumerable은 Iterator를 꺼낼 수 있어야 한다. <pre><code class="language-cpp">template&lt;typename T&gt; struct IEnumerator
{
  virtual T&amp; getObject() = 0;
  virtual bool moveNext() = 0;
  virtual ~IEnumerator() {}
};
&gt;
template&lt;typename T&gt; struct IEnumerable  
{
  virtual IEnumerator&lt;T&gt;* getEnumerator() = 0;
  virtual ~IEnumerable() {}
};</code></pre>
</li>
<li>단점 <ul>
<li>getEnumerator()는 new로 할당하기 때문에 반드시 사용자가 delete 해주어야 하는데, 라이브러리가 할당하고 사람이 delete하는 구조는 좋은 디자인이 아님</li>
<li>moveNext(), getObject()등은 가상함수이기 때문에 자주 호출되면 성능 저하를 야기함 </li>
<li>모든 컨테이너가 동일한 방식으로 동작하지 않음.(연속된 배열을 가지는 container의 경우 ++을 이용해서 순차 접근)</li>
</ul>
</li>
</ul>
<hr>
<p>** 2.3. STL Style의 Iterator **</p>
<ul>
<li>인터페이스를 사용하지 않고, 인라인 치환 진행</li>
<li>연산자 재정의를 통해 ++, *을 통해서 moveNext(), getObject()등을 대체 </li>
<li>new 대신 <strong><span style= "color: #FF7518;"> 임시객체</span></strong>를 전달하기 때문에 메모리 관리도 수월<pre><code class="language-cpp">template&lt;typename T&gt; class slist 
{
  Node&lt;T&gt;* head = nullptr;
public:
  void push_front(const T&amp; a) { head = new Node&lt;T&gt;(a, head); }
&gt;
  inline slist_iterator&lt;T&gt; begin()
  {
      return slist_iterator&lt;T&gt;(head); // 임시 객체
  }
  inline  slist_iterator&lt;T&gt; end()
  {
      return slist_iterator&lt;T&gt;(nullptr);
  }
};</code></pre>
</li>
</ul>
<h2 id="3-visitor">3. Visitor</h2>
<blockquote>
<p>** 3.1. 의도 ** </p>
</blockquote>
<ul>
<li>객체 구조에 속한 요소에 수행될 오퍼레이션을 정의 하는 객체.</li>
<li>Visitor pattern은 처리되어야 하는 <strong><span style= "color: #FF7518;">요소에 대한 클래스를 변경하지 않고 새로운 오퍼레이션을 정의할 수 있게 한다</span></strong>. 
  <img src="blob:https://velog.io/f50f0bd2-da34-4331-8c5f-50059c0bd14f" alt=""></li>
</ul>
<hr>
<p>** 3.2. 예제 **
<img src="https://velog.velcdn.com/images/taemin-steve/post/b987ca02-cf39-4407-a614-15f858f3df81/image.png" alt=""></p>
<ul>
<li>visitElement() 함수는 방문하고자하는 객체 별로 수행해야할 역할을 정의</li>
<li>accept()는 Leaf 노드에서는 전달받은 visitor객체의 visitElement()만을 수행, internal 노드에서는 <strong><span style= "color: #FF7518;">자신의 childern의 accept()를 호출</span></strong>하도록 구현해야한다.<pre><code class="language-cpp">struct IMenuVisitor
{
  virtual void visit(MenuItem* mi) = 0;
  virtual void visit(PopupMenu* pm) = 0;
  virtual ~IMenuVisitor() {}
};
&gt;
struct IAcceptor
{
  virtual void accept(IMenuVisitor* visitor) = 0;
  virtual ~IAcceptor() {}
};
&gt;
class MenuItem : public BaseMenu // leaf node
{
  int id;
public:
  MenuItem(const std::string&amp; title, int id) : BaseMenu(title), id(id) {}
&gt;
  void accept(IMenuVisitor* visitor)
  {
      visitor-&gt;visit(this);
  }
&gt;
  void command() override {};
};
&gt;
class PopupMenu : public BaseMenu // internal node
{
  std::vector&lt;BaseMenu*&gt; v;
public:
&gt;
  PopupMenu(const std::string&amp; title) : BaseMenu(title) {}
  &gt;
  void accept(IMenuVisitor* visitor)
  {
      visitor-&gt;visit(this);
&gt;
      for ( auto child : v)
          //visitor-&gt;visit(child);
          child-&gt;accept(visitor); // 
  }
&gt;
  void add_menu(BaseMenu* p) { v.push_back(p); }
&gt;
  void command() override{}
};
&gt;
//Visitor
class PopupMenuTitleChangeVisitor : public IMenuVisitor
{
public:
  void visit(MenuItem* mi) {}  // 메뉴아이템 방문시 할일은 없다.
&gt;
  void visit(PopupMenu* pm) 
  {
      std::string s = &quot;[ &quot; + pm-&gt;get_title() + &quot; ]&quot;;
      pm-&gt;set_title(s);
  }
};</code></pre>
</li>
</ul>
<hr>
<p>** 3.3. Visitor의 의미 ** </p>
<ul>
<li>객체지향의 디자이니 특징 : 새로운 객체 타입을 추가하는 것은 쉬우나 가상함수를 추가하는 것은 어렵다(모든 객체 타입의 수정이 필요). <img src="https://velog.velcdn.com/images/taemin-steve/post/453d7d17-0cf4-4b1d-84d6-b7199f84f6e0/image.png" alt=""></li>
<li>반대로 Visitor를 사용하면 새로운 객체 타입을 추가하는 것은 어려워지지만, 새로운 오퍼레이션(visitor 작성)을 추가하는 것은 쉽다.<ul>
<li>새로운 객체 타입을 추가하면 visitor 인터페이스가 변경됨</li>
<li>각 Visitor 마다 전달되는 객체 타입에 맞는 동작을 구현 필요</li>
<li>결과적으로 기존의 모든 Visitor를 수정해야하는 문제점이 발생. <blockquote>
</blockquote>
<img src="https://velog.velcdn.com/images/taemin-steve/post/3e524f3f-d4cb-4fb4-986f-188c1532ec44/image.png" alt=""></li>
</ul>
</li>
<li><strong><span style= "color: #FF7518;"> 객체지향의 특징을 반대로 변경해주는 효과를 가진다. </span></strong></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[간접층의 원리 ]]></title>
            <link>https://velog.io/@taemin-steve/%EA%B0%84%EC%A0%91%EC%B8%B5%EC%9D%98-%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@taemin-steve/%EA%B0%84%EC%A0%91%EC%B8%B5%EC%9D%98-%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Thu, 10 Oct 2024 15:06:23 GMT</pubDate>
            <description><![CDATA[<h2 id="1-adapter">1. Adapter</h2>
<blockquote>
<p>** 1.1. 의도 **</p>
</blockquote>
<ul>
<li>인터페이스를 클라이언트가 <strong><span style= "color: #FF7518;"> 기대하는 형태의 인터페이스로 변환 </span></strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/d025fb83-0dec-4598-b791-7212922e2ed0/image.png" alt=""></li>
</ul>
<hr>
<p>** 1.2. 구현 방법 **</p>
<ul>
<li><strong><span style= "color: #FF7518;"> Class Adapter</span></strong>를 활용한 구현<ul>
<li>다중 상속을 활용하여 CoolText의 show()함수를 draw()함수로 탈바꿈</li>
<li>Object Adapter를 사용하는 경우에 비하여 가상함수를 통해 재정의 할 가능성이 남아 있음. <pre><code class="language-cpp">class ClsAdapter : public CoolText, public Shape 
{
public:
ClsAdapter(const std::string&amp; text) 
      : CoolText(text) {}
void draw() override { CoolText::show();}
};    </code></pre>
</li>
</ul>
</li>
<li><strong><span style= "color: #FF7518;">Object Adapter</span></strong>를 활용한 구현 <ul>
<li>이미 생성되어 있는 객체를 포인터 혹은 Reference 타입으로 불러와서 해당 객체의 함수를 호출<pre><code class="language-cpp">class ObjAdapter : public Shape  // 객체 어댑터
{
CoolText* ct; // 객체를 받아올 떄는 보통 이런 형식을 많이 사용한다.
public:
ObjAdapter(CoolText* ct) : ct(ct) {}
void draw() override { ct-&gt;show();}
};    </code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<p>** 1.3. STL 에서의 활용 **</p>
<blockquote>
<ul>
<li>stack을 구현하고자 할때 이미 다른 클래스에서 잘 만들어진 메모리 관리, 혹은 기본 기능들을 굳이 재정의하여 코드 메모리를 늘리고 싶지 않음</li>
</ul>
</blockquote>
<ul>
<li>object adapter를 활용하여 stack을 만들고, <strong><span style= "color: #FF7518;"> policy based design</span></strong>을 통해 사용자에게 선택권을 제공 <pre><code class="language-cpp">template&lt;typename T, typename C = std::deque&lt;T&gt; &gt; 
class stack 
{
  C c;
//    C* c; // object adapter
public:
  constexpr void push(const T&amp; a) { c.push_back(a); }
  constexpr void pop()            { c.pop_back();     }
  constexpr T&amp;   top()            { return c.back(); }
};
#include &lt;stack&gt;
int main()
{
  stack&lt;int, std::vector&lt;int&gt;&gt; s1; // cash 사용에 따라 유리할 수 있음
  stack&lt;int, std::list&lt;int&gt;&gt; s2;
  stack&lt;int&gt; s;
  s.push(10); // 인라인화가 이루어진다면 s.c.push_back(a) 가 되어 마치 stack은 없는 것처럼 작동하게 된다.
  s.push(20); // 기계어 코드에는 stack과 관련된 코드들은 없는 것 처럼 받아들여진다.
}</code></pre>
</li>
</ul>
<hr>
<p>*<em>1.4. private을 이용한 상속 *</em></p>
<blockquote>
<ul>
<li>구현은 물려받았지만 인터페이스는 물려받지 않았다  </li>
</ul>
</blockquote>
<ul>
<li>상속을 모두 private 영역 안에 받게 하여, 외부에 노출하고 싶지 않은 부모 클래스의 기능을 숨길 수 있음. (java에서의 stack이 vector로부터 일반 상속을 받아 구현되어 push_front와 같은 함수가 ide에 잡히는 문제 발생)</li>
</ul>
<h2 id="2-proxy">2. Proxy</h2>
<blockquote>
<p>** 2.1. 의도 **</p>
</blockquote>
<ul>
<li>다른 객체에 접근하기 위한 <strong><span style= "color: #FF7518;"> 중간 대리 역할을 하는 객체를 생성</span></strong>, 대리 역할하는 객체에서 다양한 문제를 해결(인증, 보안, 원격지 서버 대행)
<img src="https://velog.velcdn.com/images/taemin-steve/post/24d61445-2211-4ddd-b1ac-c1ed58f321b7/image.png" alt=""></li>
</ul>
<hr>
<p>** 2.2 예제 **</p>
<blockquote>
<ul>
<li>Image 객체를 호출하면 Image가 로드됨.</li>
</ul>
</blockquote>
<ul>
<li>하지만 주로 하고 싶은 작업은 이미지의 크기를 불러오는 것  &gt;&gt; 불필요하게 메모리가 소모됨.</li>
<li>ImageProxy 클래스를 생성하여 문제 해결(헤더파일만을 읽는 방식으로 진행)</li>
<li>이미지를 그려야 할때 Image 객체를 생성해서 그림을 그림 (<strong><span style= "color: #FF7518;"> 지연된 생성</span></strong> )<pre><code class="language-cpp">class Image : public IImage
{
  std::string name;
public:
  Image(const std::string&amp; name) : name(name)
  {
      std::cout &lt;&lt; &quot;open &quot; &lt;&lt; name &lt;&lt; &#39;\n&#39;;
  }
  void draw() { std::cout &lt;&lt; &quot;draw &quot; &lt;&lt; name &lt;&lt; &#39;\n&#39;; }
&gt;
  int width()  const { return 100;}
  int height() const { return 100;}
};
&gt;
class ImageProxy : public IImage
{
  std::string name;
  Image* img = nullptr;
public:
  ImageProxy(const std::string&amp; name) : name(name) {}
&gt;
  int width()  const { return 100;} // 파일헤더에서 정보 획득
  int height() const { return 100;} // 파일헤더에서 정보 획득
  void draw() 
  {
      if ( img == nullptr )
          img = new Image(name); // 꼭 그림을 그려 주어야 할때는 img 객체를 생성해서 진행
          // 지연된 생성이라 부름 
      img-&gt;draw();
  }
};</code></pre>
</li>
</ul>
<hr>
<p>** 2.3. 차별점 **</p>
<ul>
<li>브릿지와 유사하지만, 브릿지는 상호간의 업데이트를 위한 패턴 </li>
<li>데코레이터와 유사하게 기능을 추가하는 것 같지만, 데코레이터는 중첩의 형태로 진행되며, 인터페이스가 동일함 / 반면에 프록시는 중첩이 안되며 지연된 생성을 활용한다는 점이 다름 </li>
</ul>
<h2 id="3-facade-pattern">3. Facade Pattern</h2>
<blockquote>
<p>** 3.1. 의도 ** </p>
</blockquote>
<ul>
<li>서브 시스템을 합성하는 다수의 객체들의 인터페이스 집합에 대해 일관된 하나의 인터페이스를 제공할 수 있도록 한다. </li>
<li>서브 시스템을 사용하기 쉽게 하기 위한 <strong><span style= "color: #FF7518;"> 포괄적인 개념의 인터페이스를 정의</span></strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/fb15ce5c-d081-4d8f-8dd2-0c5ac1e1823f/image.png" alt=""></li>
</ul>
<hr>
<p>** 3.2. 예제 ** </p>
<ul>
<li>내부적인 코드를 모두 감싸 TCP server에 대해서 몰라도 쉽고 간편하게 사용할 수 있도록 Facade를 생성<pre><code class="language-cpp">class TCPServer // 반복되는것, 내부동작을 알 필요가 없는 동작은 다음과 같이 싸주는 것이 좋다.
{
  NetworkInit init;
  Socket sock{SOCK_STREAM};
public:
  void Start(const char* ip, short port)
  {
      IPAddress addr(ip, port);
      sock.Bind(&amp;addr);
      sock.Listen();
      sock.Accept();
  }
};
&gt;
int main()
{
  TCPServer server; // 파사드. 이련의 절차에 대한 포괄적인 개념의 인터페이스를 제공 &gt;&gt; 사용자가 사용이 쉬워짐 
  server.Start(&quot;127.0.0.1&quot;, 4000);
}</code></pre>
</li>
</ul>
<h2 id="4-bridge">4. Bridge</h2>
<blockquote>
<p>** 4.1 의도 ** </p>
</blockquote>
<ul>
<li><strong><span style= "color: #FF7518;"> 구현과 추상화 개념을 분리</span></strong>하여 각각 독립적으로 변형할 수 있게 한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/5ee5131e-d7b3-4e5a-9e13-3357e6fdcc0e/image.png" alt=""></li>
<li>클라이언트에서 어떤 추가적인 기능을 원할때 인터페이스가 바뀌면 모든 구현 클래스들이 변경되어야 함.</li>
<li>Abstraction 이라는 가상의 클래스를 통해 간단한 기능은 해당 클래스에서 구현할 수 있고, 구현계층이 변경되더라도 사용자와는 아무 상관이 없다.
<img src="https://velog.velcdn.com/images/taemin-steve/post/be9ac175-0e9a-44d7-86c0-3f2fb0d668dc/image.png" alt=""></li>
</ul>
<hr>
<p>** 4.2. 예제 **</p>
<ul>
<li>업데이트를 편안하게 하고 싶다면 <strong><span style= "color: #FF7518;"> 중간에 계층을 늘려 </span></strong> 상호 독립적으로 업데이트! (단 성능 저하가 발생할 수 있음)<pre><code class="language-cpp">class MP3
{
  IMP3* impl; //P - IMPL point to implementation으로 불리기도 함 .
public:
  MP3(IMP3* p = nullptr) : impl(p)
  {
      if (impl == nullptr)
          impl = new IPod;
  }
&gt;
  void play() { impl-&gt;play(); }
  void stop() { impl-&gt;stop(); }
  &gt;
  void play_one_minute()
  {
      impl-&gt;play();
      // 1분 후에.. 
      impl-&gt;stop();
  }
};</code></pre>
</li>
</ul>
<hr>
<p>** 4.3. PIMPL**</p>
<ul>
<li><strong><span style= "color: #FF7518;">Pointer to Implementation </span></strong> 으로 cpp 에서는 유용하나 다른 언어에서는 적합하지 않을 수 있다. </li>
<li>Point.h가 간접 계층이 되어준다면 PointImpl이 변경되어도 main은 Point.h만을 사용하기 때문에 변경될 것이 없다 (== maind을 전부 재 컴파일 할 필요가 없다.)</li>
<li>Pointer를 선언할때 include 없이 <strong><span style= "color: #FF7518;"> 전방선언으로도 가능</span></strong>하기 때문에 가능한 기법이다. </li>
<li><strong><span style= "color: #FF7518;">컴파일러 방화벽</span></strong>이자 <strong><span style= "color: #FF7518;">완벽한 정보 은닉</span></strong>이 가능해진다.(실제 구현 파트는 DLL로 제공)
<img src="https://velog.velcdn.com/images/taemin-steve/post/720f918f-9afa-4ed0-8c43-a43ef28dd879/image.png" alt=""><pre><code class="language-cpp">//#include &quot;PointImpl.h&quot;
class PointImpl; // 핵심.. 포인터를 쓸때는 전방선언으로도 충분하다.
&gt;
class Point
{
  PointImpl* impl;
public:
  Point(int x, int y);
&gt;
  void print() const;
};</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[재귀적 포함]]></title>
            <link>https://velog.io/@taemin-steve/%EC%9E%AC%EA%B7%80%EC%A0%81-%ED%8F%AC%ED%95%A8</link>
            <guid>https://velog.io/@taemin-steve/%EC%9E%AC%EA%B7%80%EC%A0%81-%ED%8F%AC%ED%95%A8</guid>
            <pubDate>Wed, 09 Oct 2024 08:02:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1-composite-pattern">1. Composite Pattern</h2>
<blockquote>
<p>** 1.1. 의도 **</p>
</blockquote>
<ul>
<li>부분과 전체의 계층을 표현하기 위해 <strong><span style= "color: #FF7518;"> 복합 객체를 트리 구조</span></strong>로 만들어낸다. </li>
<li>Composite 패턴을 클라이언트로 하려면 개별 객체와 복합 객체를 모두 <strong><span style= "color: #FF7518;">동일하게</span></strong> 다룰 수 있도록 한다. </li>
<li>재귀적, 혹은 당양한 타입의 함수 인자를 받기 위해서 공통의 interface로 묶어 Upcasting을 활용. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/635349b5-e573-4934-8ec9-fd97bee557e9/image.png" alt=""></li>
</ul>
<hr>
<blockquote>
<p>*<em>1.2. 예제 *</em></p>
</blockquote>
<ul>
<li>Pop Up Menu를 구현하고 싶은데, Pop up menu(Composite)는 menu(Leaf)도 들어가고 Pop up menu도 들어갈 수 있어야 한다.</li>
<li>자기 자신을 받기 위해서는 단순히 Menu만 받아 저장하는 것이 아니라 Upcasting을 활용하여 BaseMenu(Component)를 받아서 저장하게 한다. -</li>
</ul>
<hr>
<blockquote>
<p>** 1.3. 장점 ** </p>
</blockquote>
<ul>
<li>객체간의 관계만 바꾸어주면 수정과 추가가 쉽다 <img src="https://velog.velcdn.com/images/taemin-steve/post/38847b34-f657-414f-91ac-be14865261f2/image.png" alt=""></li>
<li>위 그림의 색상 변경을 해상도 변경 아래 를 수정하기 위해서 아래와 같이 관계를 재설정 하여 구현 가능 <pre><code class="language-cpp">int main()
{
  PopupMenu* root = new PopupMenu(&quot;ROOT&quot;);
  PopupMenu* pm1 = new PopupMenu(&quot;해상도 변경&quot;);
  PopupMenu* pm2 = new PopupMenu(&quot;색상 변경&quot;);
&gt;
  root-&gt;add_menu(pm1);
//    root-&gt;add_menu(pm2); // 기존 관계 해지
  pm1-&gt;add_menu(pm2); // 새로운 관계 생성 
&gt;
  pm1-&gt;add_menu(new MenuItem(&quot;HD&quot;, 11));
  pm1-&gt;add_menu(new MenuItem(&quot;FHD&quot;, 12));
  pm1-&gt;add_menu(new MenuItem(&quot;UHD&quot;, 13));
&gt;
  pm2-&gt;add_menu(new MenuItem(&quot;RED&quot;,   21));
  pm2-&gt;add_menu(new MenuItem(&quot;GREEN&quot;, 22));
  pm2-&gt;add_menu(new MenuItem(&quot;BLUE&quot;,  23));
  pm2-&gt;add_menu(new MenuItem(&quot;BLACK&quot;, 24));
&gt;
  // 메뉴를 시작하려면 ??
  root-&gt;command();
}</code></pre>
</li>
<li>공통 기능을 구현하는데 있어 두가지 방법을 따를 수 있음. 아래의 방법의 경우 복합객체와 객체의 사용법이 동일해진다는 장점이 존재한다.(단 Leaf 노드에서는 사용할 필요가 없기 때문에 Composite에서 기본적으로 재구현 하지 않으면 오류를 발생시키도록 설정해두는 방법도 존재) 
<img src="https://velog.velcdn.com/images/taemin-steve/post/92bc3d56-43d6-4a31-9f54-2f973b1186ff/image.png" alt=""><blockquote>
<blockquote>
<p>객체 지향이란 결국 객체를 만들고, 관계를 설정하고, 서로간의 메시지를 주고 받는(맴버 함수 호출) 과정이다.</p>
</blockquote>
</blockquote>
</li>
</ul>
<h2 id="2-decorator-pattern">2. Decorator Pattern</h2>
<blockquote>
<p>** 2.1. 의도 **</p>
</blockquote>
<ul>
<li>객체에 <strong><span style= "color: #FF7518;"> 동적으로 서비스를 추가할 수 있게 한다.</span></strong> </li>
<li>객체에 서비스를 <strong><span style= "color: #FF7518;">  중첩적</span></strong>으로 추가할 수 있다. </li>
<li>상속을 사용하여 서비스를 추가하는 것보다 포함을 사용하여 유연한 방법으로 서비스를 추가할 수 있다.</li>
<li>Component에 포함되는 다른 추가적인 ConreteComponet가 Decorator를 <strong><span style= "color: #FF7518;"><br>재사용</span></strong>할 수 있다.
<img src="https://velog.velcdn.com/images/taemin-steve/post/f885a30f-e456-4ba1-b904-b3b5a86a418e/image.png" alt=""></li>
</ul>
<hr>
<blockquote>
<p>** 2.2 예제 **</p>
</blockquote>
<ul>
<li>Image 클래스는 draw() 함수를 보유하며, 이미지 파일을 출력하는 기능을 가지고 있다고 하자. </li>
<li>하지만 이때 Image 클래스에 액자, 혹은 말풍선등을 추가하고 싶다고 가정한다. </li>
<li>상속을 통해 기능을 구현하는 경우 엄밀히 말하면 객체에 기능을 추가하는 것이 아니라 Class에 기능을 추가한 것이기에 사실상 <strong><span style= "color: #FF7518;"> 새로운 기능이 추가된 새로운 객체를 호출</span></strong>해야한다. 뿐만아니라 중복적인 기능의 추가시 코드가 복잡해진다.</li>
<li>상속이 아니라 포함(이미 생성된 객체를 호출해서 활용)을 통해 기능을 추가</li>
<li>또한 중복적으로 값을 추가하기 위해서 객체를 생성하는 클래스와, Decorator 모두 상속해야하는 <strong><span style= "color: #FF7518;"> 공통의 부모 클래스</span></strong>를 추가하하여(IDraw 함수, Composite의 component와 유사한 역할) 해결.
<img src="https://velog.velcdn.com/images/taemin-steve/post/056bc4a2-a2c4-4366-be38-4cc474ddb506/image.png" alt=""></li>
<li>추가적으로 Operation() 함수들은 전달받은 객체의 Operation() 함수를 호출하고, <strong><span style= "color: #FF7518;"> 부가 적인 기능</span></strong>을 만을 추가<pre><code class="language-cpp">class Frame : public Image 
{
public:
  using Image::Image;
&gt;
  void draw() const 
  { 
      std::cout &lt;&lt; &quot;==========================&quot; &lt;&lt; std::endl; //부가기능
      Image::draw();
      std::cout &lt;&lt; &quot;==========================&quot; &lt;&lt; std::endl; 
  }
};
class Balloon : public Image 
{
public:
  using Image::Image;
&gt;
  void draw() const 
  { 
      std::cout &lt;&lt; &quot;== Balloon ==============&quot; &lt;&lt; std::endl; //부가기능
      Image::draw();
      std::cout &lt;&lt; &quot;== Balloon ==============&quot; &lt;&lt; std::endl; 
  }
};</code></pre>
</li>
</ul>
<hr>
<h3 id="span-style-color-ff7518-span--다양한-종류의-객체를-전달받아-사용하고-싶은-경우-공통의-인터페이스를-만들고-upcasting을-활용하여-해결"><span style= "color: #FF7518;"> ※</span>  다양한 종류의 객체를 전달받아 사용하고 싶은 경우, 공통의 인터페이스를 만들고 Upcasting을 활용하여 해결</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[공통성과 가변성의 분리]]></title>
            <link>https://velog.io/@taemin-steve/%EA%B3%B5%ED%86%B5%EC%84%B1%EA%B3%BC-%EA%B0%80%EB%B3%80%EC%84%B1%EC%9D%98-%EB%B6%84%EB%A6%AC</link>
            <guid>https://velog.io/@taemin-steve/%EA%B3%B5%ED%86%B5%EC%84%B1%EA%B3%BC-%EA%B0%80%EB%B3%80%EC%84%B1%EC%9D%98-%EB%B6%84%EB%A6%AC</guid>
            <pubDate>Sun, 06 Oct 2024 15:40:41 GMT</pubDate>
            <description><![CDATA[<h2 id="1-template-method">1. Template method</h2>
<blockquote>
<p>** 1.1. 정의 **</p>
</blockquote>
<ul>
<li>오퍼레이션에는 알고리즘의 <strong><span style= "color: #FF7518;"> 처리 과정만을 정의</span></strong> 하고 각 단계에서 수행할 <strong><span style= "color: #FF7518;">  구체적인 처리는 서브 클래스에서 정의 </span></strong></li>
<li>의도 : 알고리즘의 처리과정은 변경하지 않고 알고리즘 각 단계의 처리를 서브클래스에서 재정의 할 수 있게 한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/ab8d2736-b325-4780-a116-a8a4cc1ba492/image.png" alt=""></li>
<li>탬플릿이란 전체적인 틀을 의미함.<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<p>*<em>1.2. 적용법 *</em></p>
<ul>
<li>변하지 않는 코드 내부의 변경될 수 있는 코드를 찾는다 </li>
<li>변해야 하는 코드를 가상함수로 분리 </li>
<li>변경이 필요한 부분을 재정의 해서 활용. </li>
</ul>
<hr>
<p>클래스 다이어그램 <img src="https://velog.velcdn.com/images/taemin-steve/post/f1b1c7ee-e9b8-448d-854c-808760ab2245/image.png" width="50%" align="center"></p>
<h2 id="2-strategy-pattern">2. Strategy Pattern</h2>
<blockquote>
<p>*<em>2.1. 정의 *</em></p>
</blockquote>
<ul>
<li>다양한 알고리즘들이 존재하면 이들 각각을 <strong><span style= "color: #FF7518;">하나의 클래스로 캡슐화 하여 알고리즘 대체가 가능</span></strong>하도록 구현 (이를 통해 알고리즘을 변경하더라도 클라이언트는 아무런 변경을 할 필요가 없음)
<img src="https://velog.velcdn.com/images/taemin-steve/post/9f20d20d-ce8d-43ae-837f-820620fb49ae/image.png" alt=""></li>
</ul>
<hr>
<p>** 2.2 적용 방법 **</p>
<ul>
<li>인터페이스를 만들고, <strong><span style= "color: #FF7518;"> 약한 결합 </span></strong> 을 통해 생성한 정책 클래스의 객체를 호출하여 활용 <pre><code class="language-cpp">int main()
{
  Edit edit;
  DigitValidator v(5); // 정책 클래스 객체 생성
  edit.set_validator(&amp;v); // 정책 클래스의 객체 호출
&gt;
//    AddressValidator v2(15); // 또다른 정책을 미리 생성해서 사용하는 것도 가능
//    edit.set_validator(&amp;v2);
&gt;
  while (1)
  {
      std::string s = edit.get_text();
      std::cout &lt;&lt; s &lt;&lt; std::endl;
  }
}</code></pre>
</li>
</ul>
<hr>
<p>** 2.3. Strategy  VS Template pattern **</p>
<blockquote>
</blockquote>
<ul>
<li><p>Strategy</p>
<ul>
<li>정책을 사용하는 클래스와 정책이 <strong><span style= "color: #FF7518;"> 서로다른 클래스로 분리 (위임) </span></strong></li>
<li>정책을 필요로 하는 다른 클래스에서도 <strong><span style= "color: #FF7518;"> 동일한 정책 사용 가능 </span></strong></li>
<li><strong><span style= "color: #FF7518;"> 실행시간에 전략 변경 가능 </span></strong></li>
</ul>
</li>
<li><p>Template pattern</p>
<ul>
<li>탬플릿 패턴을 사용하는 경우 정책을 사용하는 클래스가 해당 정책을 소유 </li>
<li>다른 클래스에서 해당 정책을 사용할 수 없음</li>
<li>실행시간에 정책 변경 불가능 (정책을 사용하는 새로운 클래스를 호출해야 함)</li>
<li>다른 클래스에서 사용할 일이 없고, 실행시간중 교체할 이유도 없는 경우(Draw 함수와 같이) 가상함수로 구현하는 경우,  <strong><span style= "color: #FF7518;"> 맴버 데이터 접근도 편리 </span></strong>하다는 이점 또한 존재. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/1b055f51-5243-4ce1-a902-73024b3f3df3/image.png" alt=""></li>
</ul>
</li>
<li><p>변경되는 부분이 공용성이 있는지, <strong><span style= "color: #FF7518;"> 종속적</span></strong>인 것인지, 맴버변수에 접근이 필요한지 등을 종합적으로 고려하여 선택</p>
<blockquote>
</blockquote>
<hr>
<p>클래스 다이어그램 
<img src="https://velog.velcdn.com/images/taemin-steve/post/8a3fe000-56c9-43aa-b344-88a19e7732b2/image.png" alt=""></p>
<h2 id="3-policy-base-design">3. Policy Base Design</h2>
<blockquote>
<p>** 3.1. 정의 **</p>
</blockquote>
<ul>
<li>클래스의 동작을 다양한 정책 클래스로 분리하여 **<span style= "color: #FF7518;"> 템플릿 인자로 전달</span> **  하고, 컴파일 타임에 조합함으로써 유연하고 효율적인 설계를 가능하게 하는 템플릿 메타프로그래밍 기법으로 런타임 오버헤드 없이 구현 가능.(CPP의 STL이 해당 방식을 차용)<blockquote>
<blockquote>
<p>** 템플릿 ** : 모든 데이터 유형과 작동할 수 있는 함수 또는 클래슬 생성하기 위한 틀</p>
</blockquote>
</blockquote>
<pre><code class="language-cpp">// Function template to swap two values
template &lt;typename T&gt;
void swapValues(T&amp; a, T&amp; b) {
T temp = a;
a = b;
b = temp;
}</code></pre>
<blockquote>
<blockquote>
<p>** 템플릿 메타 프로그래밍 ** : 런타임 대신 컴파일 타임에 코드를 생성, 런타임에 직접 적용</p>
</blockquote>
</blockquote>
```  cpp
template <typename T>
T multiply(T a, T b) {
return a * b;
}<blockquote>
<blockquote>
</blockquote>
<p>int result = multiply<int>(3, 4);  // Compiler generates a version where T=int</p>
<blockquote>
</blockquote>
<p>//-------------------------------------
// 컴파일 시간에 생성되는 int version multiply
int multiply(int a, int b) {
return a * b;
}
//---------------------------------------</p>
<hr>
<p>** 3.2. Strategy VS Policy base design**</p>
</blockquote>
</li>
</ul>
</li>
<li><p>Strategy pattern</p>
<ul>
<li>전략 패턴의 경우 인터페이스를 사용하여 전략 객체를 생성하고 객체를 전달 받음</li>
<li>해당 과정에서 가상함수 테이블을 사용하기에 런타임에 오버헤드가 발생할 수 있음 <blockquote>
</blockquote>
</li>
</ul>
</li>
<li><p><strong>Policy base design</strong></p>
<ul>
<li>전략 패턴과 개념은 유사하지만, 객체 대신 템플릿 인자를 활용하여 정책을 전달하기 때문에 <strong><span style= "color: #FF7518;"> 런타임 오버헤드가 없음 </span></strong> </li>
<li>인라인 치환도 가능 </li>
<li>실행시간에 교체 불가능</li>
<li>인터페이스가 없기 때문에 <strong><span style= "color: #FF7518;"> 구현자가 반드시 규칙에 맞추어 모든 기능을 수행할 수 있도록 구현 </span></strong> 해야 함<blockquote>
<hr>
</blockquote>
</li>
</ul>
</li>
<li><ul>
<li>3.3. 예시 코드 **<pre><code class="language-cpp">template&lt;typename T, typename Ax = std::allocator&lt;T&gt; &gt; // 기본 Allocator 제공
class vector
{
 T* ptr;
 Ax ax;
pubilc:
 void resize(std::size_t newsize)
 {
     ptr = ax.allocate(size);
&gt;
     ax.deallocate(ptr, size);
 }
};
&gt;
template&lt;typename T&gt;
class malloc_allocator 
{
public:
//반드시 구현자가 아래의 두 함수를 구현해 주어야 함. 인터페이스가 없으므로 에러가 발생하지 않음. 문서에 맞게 구현자가 구현.
 inline T*   allocate(std::size_t size)  { return static_cast&lt;T*&gt;(malloc(sizeof(T)*size));}
 inline void deallocate(T* ptr, std::size_t size) { free(ptr);}
};
&gt;
int main()
{
 vector&lt;int, malloc_allocator&lt;int&gt; &gt; v;
}</code></pre>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Design Pattern Warming UP]]></title>
            <link>https://velog.io/@taemin-steve/Designe-Pattern-Warming-UP</link>
            <guid>https://velog.io/@taemin-steve/Designe-Pattern-Warming-UP</guid>
            <pubDate>Sat, 05 Oct 2024 02:23:28 GMT</pubDate>
            <description><![CDATA[<h2 id="1-constructor">1. Constructor</h2>
<blockquote>
<p><strong>1.1. 생성자</strong> : 객체가 생성될 때 호출되는 특별한 함수로 주로 객체를 초기화하는 데 사용.</p>
</blockquote>
<hr>
<blockquote>
<p>*<em>1.2. 부모클래스의 생성자 호출  *</em></p>
</blockquote>
<ul>
<li>자식 클래스의 생성자를 호출하는 경우 <strong><span style= "color: #FF7518;"> 부모 클래스의 기본 생성자가 자동으로 호출 </span></strong>되며, 부모 클래스의 생성자가 존재하지 않는 경우 Error가 발생.</li>
<li>부모 클래스의 기본 생성자가 아닌 다른 생성자를 호출하고 싶은 경우 <strong><span style= "color: #FF7518;">명시적</span></strong> 으로 선언해 주어야 함.<pre><code class="language-cpp">class Derived : public Base
{
public:        
//    Derived() { }     // Derived() : Base(){ }
//    Derived(int a) { }// Derived(int a) : Base() { }
 Derived()      : Base(0) { }
 Derived(int a) : Base(a) { }
};</code></pre>
</li>
</ul>
<hr>
<blockquote>
<p>*<em>1.3. Protected 생성자  *</em></p>
</blockquote>
<ul>
<li>부모 클래스의 생성자중 Protected로 선언된 생성자는 직접적으로 <strong><span style= "color: #FF7518;">호출이</span></strong>불가능하나, <strong><span style= "color: #FF7518;">상속</span></strong>하는 것은 가능.</li>
<li>이는 개념(Animal)에 해당하는 부모 클래스를 생성하는 것을 막아 현실 세계를 더욱 사실적으로 모델링 할 수 있음.<pre><code class="language-cpp">class Animal
{
protected: // protected는 상속에 열려 있으나 호출에 막혀 있다.
  Animal() {}
};
class Dog : public Animal
{
public:
  Dog() {}    // Dog() : Animal() {}
};
int main()
{
  Animal a;    // A error protected 생성자를 직접 호출 하는 case
  Dog    d;    // B ok
}
</code></pre>
</li>
</ul>
<h2 id="2-upcasting">2. Upcasting</h2>
<blockquote>
<p>** 2.1. upcating**</p>
</blockquote>
<ul>
<li>자식 클래스(파생 클래스, derived class)의 객체를 부모 클래스(기반 클래스, base class)의 포인터 또는 참조로 변환하는 과정</li>
<li>단 이때 부모 클래스의 포인터로는 부모 클래스의 맴버만 접근할 수 있음 </li>
<li>만약 자식 클래스의 맴버에 접근하고 싶다면 명시적 변환을 활용해야 한다.<pre><code class="language-cpp">static_cast&lt;Rect*&gt;(p)-&gt;x = 0; // ok</code></pre>
<blockquote>
</blockquote>
</li>
</ul>
<hr>
<p><strong>2.2. Upcasting 활용</strong></p>
<ul>
<li>동종을 보관하는 Container로 활용.</li>
<li>모든 자식 클래스에 공통으로 적용되는 함수를 한번에 적용
<del>~</del>cpp
class Shape
{
public:
  int color;
};<blockquote>
</blockquote>
class Rect : public Shape
{
public:
  int x, y, w, h;
};<blockquote>
</blockquote>
void changeBlack(Shape* p) // 공통함수 한번에 적용
{
  p-&gt;color = 0;
}<blockquote>
</blockquote>
/*
void changeBlack(Triangle* p)
{
  p-&gt;color = 0;
}</li>
<li>/
int main()
{
   Rect r;
   changeBlack(&amp;r);<blockquote>
</blockquote>
   Rect* buffer[10];
   Shape* buffer[10]; //동종을 보관하는 Container
}</li>
</ul>
<h2 id="3-dynamic-cast">3. Dynamic Cast</h2>
<blockquote>
<p>** 3.1. Downcasting ** </p>
</blockquote>
<ul>
<li>부모 클래스의 객체를 자식 클래스의 포인터 또는 참조로 변환하는 과정 </li>
<li>명시적인 변환이 필요하다. (Static or Danamic Casting)<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<p>** 3.2. Static Casting 과 Dynamic Casting ** </p>
<ul>
<li>Static Casting <ul>
<li>컴파일 시간 Casting</li>
<li><strong><span style= "color: #FF7518;">  런타임에 오버헤드가 발생하지 않는다.</span></strong> </li>
<li>컴파일 시간에는 Casting하려는 Memory가 무엇인지 확인할 수 없기 떄문에 잘못된 DownCasting인지 확인 불가능</li>
</ul>
</li>
<li>Dyanmaic Casting<ul>
<li>런타임 Casting </li>
<li>런타임 오버헤드 발생 </li>
<li>Casting 하려는 메모리 확인후 진행하여 잘못된 DownCasting이 발생하지 않는다. 단 메모리 확인을 위해 가상함수 테이블을 활용하기 때문에 가상함수가 존재해야만한다. </li>
</ul>
</li>
</ul>
<hr>
<p>** 3.3. Dynamic Casting의 설계적 관점 **</p>
<ul>
<li>Upcasting을 통해 부모 클래스(Animal)에서 정의된 함수가 있다면, 모든 자식 Classd에서 수행 가능해야 좋은 설계라고 할수 있음. </li>
<li>따라서 굳이 Dynamic Casting을 통해 특정 자식객체인지 확인할 이유가 없다.</li>
<li>만약 특정 자식객체만 독특하게 수행해야할 것이 있다면 오버로딩을 통해 새로운 함수를 만들어 내는 것이 설계적으로 바람직함 <pre><code class="language-cpp">//기존의 코드를 수정하지 않고, 추가적인 요구사항을 만족시키기 위해 다음과 같이 오버라이딩을 진행
void foo(Animal* p)
{
  // 모든 동물의 공통의 작업
}
&gt;
void foo(Dog* p)
{
  foo(static_cast&lt;Animal*&gt;(p));
  p-&gt;run();
}</code></pre>
위의 코드와 같이 기존의 코드는 건드리지 않고 (Closed) 추가적인 기능을 수행(Open)할 수 있는 것이 바람직하다. </li>
</ul>
<h2 id="4-abstract">4. Abstract</h2>
<blockquote>
<p>** 4.1. 가상함수 &amp; 순수 가상함수 **</p>
</blockquote>
<ul>
<li>가상함수 : virtual 키워드가 앖에 먼저 선언되며, 자식 클래스에서 Overriding이 가능한 함수 </li>
<li>순수 가상함수 : virtual 키워드로 시작하며, 구현부 대신 <strong><span style= "color: #FF7518;">=0</span></strong> 
으로 구성되어진 함수<ul>
<li>자식 클래스에서 해당 함수를 <strong><span style= "color: #FF7518;">반드시 override 하도록</span></strong>  강제 (구현하지 않는경우 컴파일 되지 않음)</li>
<li>순수 가상함수가 하나라도 포함한 클래스는 추상 클래스가 됨. (추상 클래스는 객체를 생성할 수 없으나, 포인터 생성은 가능)</li>
</ul>
</li>
</ul>
<hr>
<p><strong>4.2. 설계 관점</strong></p>
<ul>
<li>가상함수의 경우 자식 클래스에서 해당 함수를 재정의 하지 않으면 부모 클래스의 함수를 호출 가능. 하지만 이때 부모 클래스의 함수를 호출하는 것이 개념적으로 맞지 않을 수 있음. <pre><code class="language-cpp">class Shape
{
public:
  virtual ~Shape() {}
  virtual void draw() = 0; // 추상적인 개념을 직접 그려낸다는게 어려움.
};
&gt;
class Rect : public Shape 
{
public:
  void draw() override { std::println(&quot;draw Rect&quot;); }
};</code></pre>
</li>
<li>위의 코드와 같이 Shpae 라는 개념이 그려질(draw)될 일이 없으므로 순수 가장함수로 만들고, 자식 클래스에서 override 하여 그리는 방식 활용</li>
</ul>
<h2 id="5-interface">5. Interface</h2>
<blockquote>
<p>** 5.1. 인터페이스 &amp; 추상 클래스 **</p>
</blockquote>
<ul>
<li>인터페이스 : <strong><span style= "color: #FF7518;"> 모두 순수 가상 함수들로 구현</span></strong> 되어 지켜야할 <strong><span style= "color: #FF7518;">규칙</span></strong> 만을 가진 클래스 (구현 한다고 표현)</li>
<li>추상 클래스 : 순수 가상함수를 하나라도 포함하는 클래스 <blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<p>* Struct를 이용해서 인터페이스를 생성하기도 함. (public 키워드 뺄 수 있음) </p>
<blockquote>
</blockquote>
<hr>
<blockquote>
</blockquote>
<p>** 5.2. virtual 키워드 ** </p>
<ul>
<li>virtual 키워드는 런타임 시에 <strong><span style= "color: #FF7518;">실제 객체 타입에 따라 함수를 선택적으로 호출</span></strong> 되도록 보장. (CPP 진영에서는 &quot;가상함수가 아니면 재정의 하지도 말라&quot;라는 격언이 존재)</li>
<li>이런 이유로 interface 혹은 기반 클래스들은 가상 소멸자를 사용해 주는 것이 좋다.(Upcasting을 사용하여 부모 클래스의 포인터로 파생클래스의 객체를 참조하는 경우 부모 클래스의 소멸자가 호출되는데, 이때 자식 클래스의 맴버변수들에 대한 정보 누락으로 ** 메모리 누수**가 발생할 수 있음)<pre><code class="language-cpp">struct ICamera
{    
//public:
  virtual ~ICamera() {} // 가상 소멸자.
&gt;
  virtual void take() = 0;    
};</code></pre>
</li>
<li>동일한 코드가 상황에 따라 다르게 동작하는 것을 <strong><span style= "color: #FF7518;"> 다형성(Polymorphism) </span></strong> 이라고 하며 이는 OCP를 지키는데 큰 도움이 된다.</li>
</ul>
<hr>
<p>** 5.3. 강한결합 &amp; 약한결합 ** </p>
<ul>
<li>강한 결합 : 서로의 클래스 이름을 알고 있는 상태로 교체가 불가능하고 경직적인 디자인 </li>
<li><strong><span style= "color: #FF7518;">약한 결합</span></strong>  : 서로의 클래스명을 알지 못하는 상태로 교체가 가능하고 확장성 있는 유연한 디자인.  </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git 사용법]]></title>
            <link>https://velog.io/@taemin-steve/Git-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@taemin-steve/Git-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Sat, 27 Jan 2024 20:33:12 GMT</pubDate>
            <description><![CDATA[<h2 id="1-기본-개념">1. 기본 개념</h2>
<ul>
<li><p>commit id : 커밋 내용, 저자 정보, 날짜 및 시간, 부모 및 커밋 정보로 생성됨</p>
</li>
<li><p>Head는 현재 버전을, main은 마지막 버전을 나타내며, 각각의 version은 이전(부모) version을 기억하고 있다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/d114412e-0e70-4b4a-b831-06e71d3cf2d5/image.png" alt="">
이때 추가적으로 Head는 branch를 가르킬 수도, commit id/version을 기억할 수도 있다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/f829c907-b036-4213-80ce-cc82f9299c95/image.png" alt=""></p>
</li>
<li><p>detached Head : Head가 직접적으로 version을 가리키고 있는 상태
<img src="https://velog.velcdn.com/images/taemin-steve/post/0767b66c-5ba0-4e38-aef9-ecc03e121056/image.png" alt="">
만약 이 상태에서 지속적으로 commit을 하고, 추후에 main으로 check out하게 되면 이전의 version들은 그 누구도 기억하지 않는 상태가 된다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/7d40a72b-6330-40f4-b8cd-51e6d1fee36a/image.png" alt="">
<img src="https://velog.velcdn.com/images/taemin-steve/post/f8aa392c-dbb2-4c4e-97bc-8cae91882608/image.png" alt="">
<img src="https://velog.velcdn.com/images/taemin-steve/post/00f39cd9-498c-419d-a0cd-275315086c8a/image.png" alt="">
따라서 반드시 main으로 돌아올 때는 check out을 통해서 돌아오지 말고, main을 더블 클릭해서 돌아와야 한다. UI가 조금 헷깔리게 되어있는데 아래의 상태는 detached Head 상태이다 
<img src="https://velog.velcdn.com/images/taemin-steve/post/e344aa34-15a1-42d6-acc6-6132094a2d53/image.png" alt="">
아래와 같은 상태가 되어야 제대로 되고 있는 것이다. 잘 보면 테두리의 색이 다름 
<img src="https://velog.velcdn.com/images/taemin-steve/post/38e52478-1efe-47b9-a43d-f249981fed62/image.png" alt="">
추가적으로 문제가 발생하더라도, commit id만 기억해두면 해당 id로 check out 하여 복구 가능하고, detached head 상태에서도 branch를 만들고 merge해주면 문제를 해결할 수 있다. </p>
</li>
<li><p>reset : Head가 가르키는 branch를 변경해준다 
<img src="https://velog.velcdn.com/images/taemin-steve/post/8fd1c382-2b38-4a70-9699-8729cc7ec419/image.png" alt="">
위의 그림과 같이 exp branch에 d를 추가하고 싶었다면 exp로 Head를 옮기고, exp를 d version으로 reset한뒤, 다시 main breanch로 check out, c version으로 reset 해주면 됨.</p>
</li>
<li><p>rebase : Head가 가리키고 있는 branch의 base를 선택한 branch로 재설정(rebase) 시켜준다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/3b3ea10f-ae17-44e9-9a38-16d96b159141/image.png" alt="">
기본적으로 rebase, 새로운 base가 되는 branch가 먼저 기록이 남게 되고, 만약 충돌이 있다면 </p>
</li>
</ul>
<p>-cherry pick : 변경사항만을 가져오고 싶은 경우에 사용. 특정 변화만을 가져와서 사용할 수 있음 
<img src="https://velog.velcdn.com/images/taemin-steve/post/30984243-e22b-4a6a-ac94-318d6b17cc87/image.png" alt=""></p>
<ul>
<li>origine/main : remote tracking branch(rtb), 서버에 push되어 있는 버전을 확인할 수 있음 
<img src="https://velog.velcdn.com/images/taemin-steve/post/881bd0c1-63ea-4a2d-a220-740260bfc76a/image.png" alt="">
아래와 같은 경우는 main과 origine/main이 일치되어 있는 상황을 의미한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/2bc86040-02e3-42f7-82c5-a8ea7c55ded8/image.png" alt=""></li>
<li>push : 로컬 저장소의 내용을 원격 저장소에 전달하는 것 </li>
<li>pull : fetch(원격 저장소의 내용을 로컬로 가져오는 것) + merge </li>
<li>reject : 충돌이 되지 않더라도, 로컬 저장소가 원격 저장소의 내용을 가지고 있지 않다면 발생한다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Commit Convention]]></title>
            <link>https://velog.io/@taemin-steve/Commit-Convention</link>
            <guid>https://velog.io/@taemin-steve/Commit-Convention</guid>
            <pubDate>Thu, 04 Jan 2024 13:25:39 GMT</pubDate>
            <description><![CDATA[<h2 id="01-udacity-commit-convention">01. Udacity Commit Convention</h2>
<blockquote>
<ul>
<li><strong>Commit Convention 개요</strong></li>
</ul>
</blockquote>
<ul>
<li>Udacity에서 제안하는 Commit Convention은 코드의 이력을 명확하고 일관되게 관리하기 위한 규칙입니다.</li>
<li>이 규칙에 따르면, Commit 메시지는 Type, Subject (필수), Body (선택적), Footer (선택적)로 구성됩니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong><span style="color: #FF7518;">Commit Type</span></strong></li>
</ul>
</blockquote>
<ul>
<li><strong>feat</strong> =: 새로운 기능 추가
<code>feat: Add login functionality</code></li>
<li><strong>fix</strong>: 버그 수정
<code>fix: Correct minor typos in code</code><ul>
<li><strong>docs</strong>: 문서 변경 사항
<code>docs: Update README with project setup instructions</code></li>
<li><strong>style</strong>: 코드 스타일 관련 변경 코드 변경 없이 포맷팅, 세미콜론 추가 등의 스타일 관련 수정을 포함.
<code>style: Format code according to PEP8 standards</code></li>
<li><strong>refactor</strong>: 코드 리팩토링
<code>refactor: Restructure existing class hierarchy</code></li>
<li><strong>test</strong>: 테스트 추가 또는 리팩토링
<code>test: Add unit tests for User class</code></li>
<li><strong>chore</strong>: 빌드 태스크, 패키지 매니저 설정 등의 변경. 실제 제품 코드 변경 없이, 프로젝트의 유지관리 작업을 포함
<code>chore: Update package.json dependencies</code></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>Commit Message 예시</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/ae13d851-87e9-4c33-895d-0419e5bf0df4/image.png" alt=""><ul>
<li><strong>Header</strong>: <ul>
<li>Commit Log의 제목으로, 50자 이내, 대문자로 시작하고 마침표 없이 명령문 형태로 작성. </li>
<li>태그와 작업의 대략적 내용을 포함</li>
</ul>
</li>
<li><strong>Body</strong><ul>
<li>작업에 대한 상세 기록으로, Header와는 한 칸 공백으로 구분하며, 72자를 넘기지 않도록 함.</li>
<li>본문에는 변경의 의도와 이유를 상세히 설명. 여러 단락의 경우, 빈 줄로 구분. 필요에 따라 하이픈(-)을 사용해 불릿 포인트를 추가할 수 있음</li>
</ul>
</li>
<li><strong>Footer</strong><ul>
<li>관련 Issue의 태그를 포함합니다. &#39;#&#39;과 Issue 번호로 작성합니다.(이슈 트래커 참조)</li>
<li><span style="color: #FF7518;">해당 commit이 merge 되면 자동으로 issue가 종료됨</span></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="02-pre-commit">02. Pre-commit</h2>
<blockquote>
<ul>
<li><strong>Pre-commit 툴</strong></li>
</ul>
</blockquote>
<ul>
<li>&#39;git commit&#39; 수행 시 정해진 스크립트들을 자동으로 실행하는 툴입니다.</li>
<li>예: 코드 포맷팅(black, flake8), 유닛 테스트(pytest) 등을 실행합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Pre-commit 설치</strong></li>
</ul>
</blockquote>
<ul>
<li>가장 쉬운 방법은 pip를 사용한 설치입니다.</li>
<li><code>pip install pre-commit</code> 명령어로 설치합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Pre-commit Hook 설정</strong></li>
</ul>
</blockquote>
<ul>
<li>&#39;.pre-commit-config.yaml’ 파일 생성이 필요합니다.</li>
<li>기본 hook에는 공백 제거, 파일 검사 등이 포함됩니다.</li>
<li>추가로 black 같은 툴을 통해 코드를 PEP8에 맞게 정리할 수 있습니다.</li>
<li><code>pre-commit install</code>로 hook을 설치합니다.</li>
<li><code>pre-commit autoupdate</code>로 hook을 업데이트합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Pre-commit 적용</strong></li>
</ul>
</blockquote>
<ul>
<li>파일을 commit하면 등록된 hook이 자동으로 실행되며, 필요에 따라 수정 후 다시 commit합니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git Branch 전략]]></title>
            <link>https://velog.io/@taemin-steve/Git-flow</link>
            <guid>https://velog.io/@taemin-steve/Git-flow</guid>
            <pubDate>Thu, 04 Jan 2024 12:35:53 GMT</pubDate>
            <description><![CDATA[<h2 id="github-가이드-branch">Github 가이드: Branch</h2>
<blockquote>
<ul>
<li><strong>Git Flow와 Github Flow</strong></li>
</ul>
</blockquote>
<ul>
<li>Git을 사용하며 branch를 활용하는 전략입니다.</li>
<li>Local 중심의 Git flow와 Remote 중심의 Github flow가 대표적입니다.</li>
<li>Local Remote 중심은 최신 commit이 위치하는 곳을 의미합니다.</li>
<li>Git flow는 Local에 최근 작업한 commit들이, Github flow는 Local과 Remote에 위치합니다.</li>
</ul>
<h2 id="01-git-flow">01 Git Flow</h2>
<blockquote>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/cfed906f-17db-48c3-9b54-c0b46067b2b6/image.png" alt=""></p>
<ul>
<li><strong>Gitflow: Local 중심 Branch 전략</strong></li>
</ul>
</blockquote>
<ul>
<li>주요 branch로는 main(master), develop, release, feature, hotfix 등이 있습니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>main(master)</strong></li>
</ul>
</blockquote>
<ul>
<li>배포의 기준이 되며 Release Tag를 기록하는 브랜치입니다.</li>
<li>배포용이므로 main에 직접 commit하거나 비배포용 branch에서 merge 금지.</li>
<li>hotfix 브랜치는 main에 직접 merge 가능.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>develop</strong></li>
</ul>
</blockquote>
<ul>
<li><span style="color: #FF7518;">주로 개발이 이루어지는 브랜치.</span></li>
<li>동시 작업 시 conflict 발생 가능, 따라서 feature 브랜치에서 작업 후 develop에 merge 권장.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>feature</strong></li>
</ul>
</blockquote>
<ul>
<li><span style="color: #FF7518;">개발 작업의 핵심, develop에서 분기.</span></li>
<li>Issue에 등록된 기능, bugfix, refactoring 등을 수행.</li>
<li>작업 완료 시 develop에 merge.</li>
<li>예: feat, refactor, fix, docs 등의 prefix 사용.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>release</strong></li>
</ul>
</blockquote>
<ul>
<li>배포 준비를 위한 브랜치.</li>
<li>develop에서 분기, bugfix 및 추가 refactoring 진행.</li>
<li>준비 완료 시 main에 merge.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>hotfix</strong></li>
</ul>
</blockquote>
<ul>
<li>배포된 버전(main)에서 문제 발생 시 사용.</li>
<li>main에서 분기, 문제 해결 후 main 및 develop에 merge.</li>
</ul>
<h2 id="02-github-flow">02 Github Flow</h2>
<blockquote>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/3124805d-9c80-48a6-a296-d98c94333eaa/image.png" alt=""></p>
<ul>
<li><strong>Remote 중심 Branch 전략</strong></li>
</ul>
</blockquote>
<ul>
<li>Git Flow와 달리, 주로 main 브랜치와 feature 브랜치로 구성.</li>
<li>main은 배포의 중심, feature는 기능 개발의 중심.</li>
<li>Remote에 작업 내용을 수시로 push, 항상 최신 상태 유지.</li>
<li>배포 준비용 브랜치 없이, main에 merge 시 엄격한 관리 필요.</li>
<li><span style="color: #FF7518;">Github Flow는 빠른 반영과 심플한 구조가 특징.</span></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Object Detection]]></title>
            <link>https://velog.io/@taemin-steve/Object-Detection</link>
            <guid>https://velog.io/@taemin-steve/Object-Detection</guid>
            <pubDate>Wed, 03 Jan 2024 03:06:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>참고 블로그 : <a href="https://herbwood.tistory.com/">https://herbwood.tistory.com/</a></p>
</blockquote>
<h2 id="01-object-detection-metrics--library">01. Object Detection metrics &amp; Library</h2>
<blockquote>
<p><strong>1.1 Object Detection 평가 지표</strong></p>
<ul>
<li><strong>mAP (mean Average Precision)</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/fab5eac7-3f50-4615-bd6c-77deb5507b1b/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>mAP는 클래스별 평균 정밀도(Average Precision)를 평균낸 것으로, 객체 탐지 알고리즘의 성능을 평가하는 데 중요한 지표</li>
<li>mAP를 이해하려면 정밀도(Precision), 재현율(Recall), AP, IOU 등의 개념을 알아야 함.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Precision &amp; Recall</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/2854978a-1402-4cf4-8df9-23dbfc21a535/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>정밀도(Precision)는 Positive로 예측한 대상 중 실제로 Positive인 비율.</li>
<li>재현율(Recall)은 실제 Positive인 대상 중 올바르게 예측된 비율.</li>
<li>TP(True Positive), FP(False Positive), TN(True Negative) 등의 개념을 통해 계산.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>IOU</strong> 
<img src="https://velog.velcdn.com/images/taemin-steve/post/0dd13dea-6be8-42bb-9146-f925c3480a70/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>교차집합 / 합집합</li>
<li>값이 1에 가까울수록 두 집합이 더 유사하다는 것을 의미하며, 0에 가까울수록 두 집합이 더 차이가 있다는 것을 의미<blockquote>
<ul>
<li><strong>mAP 계산</strong></li>
</ul>
</blockquote>
</li>
<li>정밀도와 재현율 곡선(Precision-Recall curve)을 사용해 계산되며, 여기서 얻어진 정밀도의 평균이 AP.</li>
<li>mAP는 다양한 객체에 대한 AP의 평균값으로, 객체 탐지 성능의 전반적인 척도를 제공.</li>
</ul>
<blockquote>
<p>** 1.2 Object Detection 라이브러리**</p>
<ul>
<li><strong>MMDetection</strong></li>
</ul>
</blockquote>
<ul>
<li>PyTorch 기반의 객체 탐지 오픈소스 라이브러리</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Detectron2</strong></li>
</ul>
</blockquote>
<ul>
<li>페이스북 AI 리서치에서 개발한 PyTorch 기반의 객체 탐지 및 세그멘테이션 라이브러리.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>YOLOv5</strong></li>
</ul>
</blockquote>
<ul>
<li>COCO 데이터셋으로 사전 학습된 모델로, 여러 연구와 개발을 거쳐 발전한 객체 탐지 모델.</li>
<li>다양한 플랫폼에서 오픈 소스로 제공.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>EfficientDet</strong></li>
</ul>
</blockquote>
<ul>
<li><p>Google Research &amp; Brain에서 연구한 모델로, EfficientNet을 응용해 만든 객체 탐지 모델.</p>
</li>
<li><p>TensorFlow와 PyTorch 기반 라이브러리가 제공.</p>
<h2 id="02-2-stage-detectors">02. 2 Stage Detectors</h2>
<blockquote>
<p><strong><a href="https://arxiv.org/abs/1311.2524">2.1 R-CNN</a></strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/65799644-22fd-44e6-bc73-edf03334c269/image.png" alt=""></p>
<ul>
<li><strong>파이프라인</strong></li>
</ul>
</blockquote>
</li>
<li><p>주요 과정은 입력 이미지 처리 </p>
</li>
<li><p>Region Proposal 추출</p>
</li>
<li><p>CNN을 통한 feature 추출</p>
</li>
<li><p>SVM 분류, Bounding Box Regression</p>
</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>학습 방법</strong></li>
</ul>
</blockquote>
<ul>
<li>Pretrained AlexNet을 사용하여 4096차원의 feature vector를 추출.</li>
<li>각 Region에 대해 SVM을 사용하여 클래스를 분류하고, Bounding Box Regressor로 정확한 위치를 예측합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>단점</strong></li>
</ul>
</blockquote>
<ul>
<li>각각의 Region을 CNN에 통과시켜야 해서 계산 비용이 큼.</li>
<li>Warping을 통해 이미지를 변형시키는 과정에서 성능 저하가 발생 가능.</li>
<li>CNN, SVM, Bounding Box Regressor를 각각 별도로 학습해야함.</li>
<li>End-to-End 학습이 아니기 때문에 최적화가 어려움.</li>
</ul>
<blockquote>
<p><a href="https://arxiv.org/abs/1406.4729"><strong>2.2 SPPNet</strong></a>
<img src="https://velog.velcdn.com/images/taemin-steve/post/09c5653f-ce70-497a-b7f8-96404cd9a7b8/image.png" alt=""></p>
<ul>
<li><strong>파이프라인</strong></li>
</ul>
</blockquote>
<ul>
<li>R-CNN과 달리 CNN을 먼저 통과</li>
<li>Spatial Pyramid Pooling을 사용하여 다양한 크기의 feature map에서 고정된 크기의 feature를 추출.<blockquote>
<blockquote>
<p><strong><span style="color: #FF7518;">Spatial Pyramid Pooling</span></strong> : 이미지의 다양한 크기의 영역에 대해 고정된 크기의 특징 벡터를 생성(spatial bins의 개수를 정하고 pooling을 진행하기에 이미지의 크기에 상관없이 고정길이 feature 추출 가능) <img src="https://velog.velcdn.com/images/taemin-steve/post/95b5d648-c3c9-4db1-8fb3-2bcae2bd6bae/image.png" alt=""></p>
</blockquote>
</blockquote>
</li>
<li>Fully connected layer를 통과</li>
<li>SVM, Bounding Box Regressor 학습</li>
</ul>
<blockquote>
<p><a href="https://arxiv.org/abs/1504.08083"><strong>2.3 Fast R-CNN</strong></a>
<img src="https://velog.velcdn.com/images/taemin-steve/post/b484ed93-8897-42fd-a1bb-d2c4092b15b3/image.png" alt=""></p>
<ul>
<li><strong>파이프라인</strong></li>
</ul>
</blockquote>
<ul>
<li>한 번의 CNN 처리를 통해 feature를 추출하고</li>
<li>RoI Pooling을 사용하여 모든 Region에 대해 고정된 크기의 feature를 추출.<blockquote>
<blockquote>
<p><strong><span style="color: #FF7518;">ROI Pooling</span></strong> : Receptive field가 RoI에 맞게끔 계산하여 영역을 정하고 해당 부분에 대해서 pooling을 진행. 아래 그림에서 정중앙이 아닌 이유는 영역의 크기가 홀수 여서 버림을 진행하였기 때문!
<img src="https://velog.velcdn.com/images/taemin-steve/post/3ceda8f5-539d-404a-90c2-ee552bc6d6fe/image.png" alt=""></p>
</blockquote>
</blockquote>
</li>
<li>이하 동일</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>학습 방법</strong></li>
</ul>
</blockquote>
<ul>
<li>Multi-task loss(분류 및 Bounding Box Regression)를 사용.</li>
<li>VGG16과 같은 강력한 CNN 구조를 사용하여 성능을 향tkd.</li>
</ul>
<blockquote>
<p><a href="https://arxiv.org/abs/1506.01497"><strong>2.4 Faster R-CNN</strong></a>
<img src="https://velog.velcdn.com/images/taemin-steve/post/9071b5c1-6e7b-43f1-82f8-f2b18feb905a/image.png" alt=""></p>
<ul>
<li><strong>파이프라인</strong></li>
</ul>
</blockquote>
<ul>
<li>Feature extraction by pre-trained VGG16</li>
<li>Generate Anchors by Anchor generation layer : 각각의 Grid Cell(원본이미지를 sub sampling ratio를 기준으로 기준으로 나눈 특정 영역)을 중심으로 기준(Anchor)를 생성하여 사전 정의된 9개의 anchor box 생성.<img src="https://velog.velcdn.com/images/taemin-steve/post/11d5e125-4f9c-4014-8055-d6446da5f8cf/image.png" alt=""></li>
<li>Class scores and Bounding box regressor by RPN<blockquote>
<blockquote>
<p><strong><span style="color: #FF7518;">RPN</span></strong> : 미지 내에서 객체 후보 영역을 빠르게 제안하는 역할<img src="https://velog.velcdn.com/images/taemin-steve/post/388793dd-a163-49f7-b516-01f240841389/image.png" alt=""></p>
</blockquote>
</blockquote>
</li>
<li>Region proposal by Proposal layer : anchor boxes와 RPN에서 반환된 class scores, bounding box regrerssor를 사용하여 anchor box가 객체의 위치를 더 잘 detect하도록 조정</li>
<li>ROI pooling</li>
<li>Classification<blockquote>
<blockquote>
<p><strong>NMS(Non-Maximum Suppression)</strong>: confidence score가 낮은 박스 OR highest IoU score인 박스를 비교해가며 하나씩 삭제해 나감</p>
</blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>학습 방법</strong></li>
</ul>
</blockquote>
<ul>
<li>Imagenet pretrained backbone과 RPN을 번갈아 가며 학습하는 4단계 학습 방법을 사용.</li>
<li>Fast R-CNN과 동일한 loss 함수를 사용하며, RPN 단계에서의 classification과 regressor 학습을 위해 anchor box를 사용.</li>
</ul>
<h2 id="03-object-detection-library">03. Object Detection Library</h2>
<blockquote>
<p><strong>3.1 MMDetection</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/20659c4c-262f-4a10-960d-8625cc6bd395/image.png" alt=""></p>
<ul>
<li><strong>기본 구조</strong></li>
</ul>
</blockquote>
<ul>
<li>Pytorch 기반의 Object Detection 오픈소스 라이브러리입니다.</li>
<li>MMDetection 라이브러리의 주요 특징은 전체 프레임워크를 모듈 단위로 분리해 관리할 수 있으며, 다양한 프레임워크를 지원하고 속도가 빠른 점입니다.</span></li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Pipeline 구조</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/9f12a36b-8e11-421a-a020-371795f15ec3/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>Backbone, Neck, Dense Prediction Prediction 등 여러 단계를 거칩니다.</li>
<li>2 Stage 모델은 크게 Backbone, Neck, DenseHead, RoIHead 모듈로 나눌 수 있으며, 각 모듈 단위로 커스터마이징이 가능합니다.</li>
<li>이러한 시스템은 config 파일을 통해 제어됩니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Config File</strong></li>
</ul>
</blockquote>
<ul>
<li>Config 파일은 데이터셋부터 모델, scheduler, optimizer를 정의할 수 있으며, 다양한 object detection 모델들의 config 파일들이 정의되어 있습니다.</li>
</ul>
<hr>
<ul>
<li><strong><span style="color: #FF7518;">기본 구성요소</span></strong><ul>
<li>dataset : Train, Validation, Test</li>
<li>model : type, backbone, neck, rpn_head, roi_head, bbox_head, train_cfg</li>
<li>schedule</li>
<li>default_runtime</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>3.2 Detectron2</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/d4f60453-ae1d-41da-bd50-aa6d6f9729fb/image.png" alt=""></p>
<ul>
<li><strong>기본 구조</strong></li>
</ul>
</blockquote>
<ul>
<li>Facebook AI Research의 Pytorch 기반 라이브러리입니다.</li>
<li>Object Detection 외에도 Segmentation, Pose prediction 등의 알고리즘을 지원합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Pipeline 구조</strong></li>
</ul>
</blockquote>
<ul>
<li>Setup Config, Setup Trainer, Start Training의 단계를 포함합니다.</li>
<li>Config 파일 수정, 데이터셋 등록, Augmentation mapper 정의, Trainer 정의 등의 단계로 구성됩니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Config File</strong></li>
</ul>
</blockquote>
<ul>
<li><p>MMDetection과 유사하게 config 파일을 수정하여 파이프라인을 구축하고 학습을 진행합니다.</p>
</li>
<li><p>틀이 갖춰진 기본 config를 상속 받아 필요한 부분만 수정하여 사용합니다.</p>
<h2 id="04-neck-구조">04. Neck 구조</h2>
</li>
</ul>
<blockquote>
<p><strong>4.1 Neck</strong></p>
<ul>
<li>구조
<img src="https://velog.velcdn.com/images/taemin-steve/post/c2ff86e0-d116-409c-95f9-5421b3ec0650/image.png" alt=""></li>
<li><strong>필요성</strong></li>
</ul>
</blockquote>
<ul>
<li>입력, Backbone, Neck, RPN, Prediction의 유의미한 연결.</li>
<li>다양한 크기의 객체를 더 잘 탐지하기 위해 필요.</li>
<li><span style="color: #FF7518;">하위 레벨의 feature가 세맨틱적으로 약할 때, 상위 레벨의 강한 세맨틱 feature와의 교환을 수행</span>.</li>
</ul>
<blockquote>
<p><strong>4.2 Feature Pyramid Network (FPN)</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/8aa4382b-e227-42c2-9754-098d811bb11a/image.png" alt=""></p>
</blockquote>
<ul>
<li>high level에서 low level로 세맨틱 정보를 전달하는 방식.</li>
<li>Bottom-up, <span style="color: #FF7518;"><strong>Top-down</strong></span>, <span style="color: #FF7518;"><strong>Lateral connections</strong></span> 등을 통해 구성 
<img src="https://velog.velcdn.com/images/taemin-steve/post/23454809-93a8-45ec-90b5-46a60ac883e8/image.png" alt=""></li>
<li>Upsampling시 Nearest Neighbor Upsampling 방식을 사용.</li>
<li>Backbone으로 ResNet을 사용하며, Top N Boxes를 선택하는 과정을 포함.</li>
<li>ROI Pooling을 진행하기 위해서, ROI의 크기에 따라 적절한 feature map(p5~p2)을 <strong>선정</strong>하여 진행하였음.
<img src="https://velog.velcdn.com/images/taemin-steve/post/2dbc835c-1784-4f10-9bcf-84f1ac2afc0b/image.png" alt=""></li>
</ul>
<blockquote>
<p><strong>4.3 Path Aggregation Network (PANet)</strong></p>
<ul>
<li><strong>Bottom-up Path Augmentation</strong></li>
</ul>
</blockquote>
<ul>
<li>Top-down을 진행할 때 과연 Row level feature가 high level featuer에 전달이 되지 않을 수 있다. </li>
<li>Bottom-up Path Augmentation을 사용하여 하위 level feature가 보다 상위 level에 잘 전달 하게 구조 개선
<img src="https://velog.velcdn.com/images/taemin-steve/post/5f2641a1-29f8-4758-b13e-5b040e6efc67/image.png" alt=""><ul>
<li>** Adaptive Feature Pooling **</li>
<li>ROI 풀링 시 경계 값에서 feture map을 선택하는데 있어 불연속적 </li>
<li>Adaptive Feature Pooling을 통해서 모든 feature map을 고려
<img src="https://velog.velcdn.com/images/taemin-steve/post/3831124c-d7f4-474d-8f70-3b7caa2af3d9/image.png" alt=""></li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>4.4 DetectoRS</strong></p>
<ul>
<li><strong>DetectoRS 동기</strong></li>
</ul>
</blockquote>
<ul>
<li>(RPN), Cascade R-CNN 등을 고려하여 반복적인 계산을 통해 성능 개선을 이룰 수 있을 거라 판단.<ul>
<li><strong><span style="color: #FF7518;">Recursive Feature Pyramid (RFP)</span></strong></li>
</ul>
</li>
<li>Neck의 정보를 활용하여 Backborn Network를 재학습
<img src="https://velog.velcdn.com/images/taemin-steve/post/dc3d3284-3ed0-4dca-a3d1-b8af02e994b0/image.png" alt=""></li>
<li><strong>Atrous Spatial Pyramid Pooling(ASPP)</strong> : 원본 feature를 여러 필터로 탐색하여, 보다 다양한 scale에서 유용한 정보를 뽑는 기법
<img src="https://velog.velcdn.com/images/taemin-steve/post/d1848001-b60a-467a-8f9b-a96ec36ec4d7/image.png" alt=""></li>
<li><strong>Atros Convolution</strong> 
<img src="https://velog.velcdn.com/images/taemin-steve/post/c75237d1-107d-492b-b315-b3be90ce3a0e/image.png" alt=""></li>
</ul>
<blockquote>
<p><strong>4.5 Bi-directional Feature Pyramid (BiFPN)</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/57b19793-87d3-4c0a-a2fa-04635a18456d/image.png" alt=""></p>
</blockquote>
<ul>
<li>하나의 feature의 정보만 받게되는 노드 삭제 
<img src="https://velog.velcdn.com/images/taemin-steve/post/5c3402b9-1ed9-4800-9a85-b8fa458a652e/image.png" alt=""></li>
<li>반복적으로 진행</li>
<li>FPN과 달리, 각 feature에 가중치를 부여한 후 summation하는 방식
<img src="https://velog.velcdn.com/images/taemin-steve/post/d703fd53-d1b3-4cf5-abfd-67fb82b86078/image.png" alt=""></li>
</ul>
<blockquote>
<p><strong>4.6 NASFPN</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/b46fc37f-3706-41b4-8a09-3a7f95f9fab6/image.png" alt=""></p>
</blockquote>
<ul>
<li>FPN 아키텍처를 NAS(Neural architecture search)를 통해서 찾아보려는 시도 </li>
<li>Architecture, Search, Stacking 단계를 포함.</li>
<li>COCO dataset ResNet 기준으로 찾은 architecture가 <span style="color: #FF7518;"><strong>범용적이지 못하며</strong>, <strong>많은 파라미터와 높은 search cost</strong></span>가 필요.</li>
</ul>
<blockquote>
<p><strong>4.7 AugFPN</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/2548fce2-75a4-445b-9938-d64a4463ae2f/image.png" alt=""></p>
<ul>
<li>FPN의 문제점, 특히 서로 다른 레벨의 feature 간의 semantic 차이, Highest feature map의 정보 손실, RoI 생성 방법 등을 개선</li>
</ul>
</blockquote>
<ul>
<li><strong><span style="color: #FF7518;">Residual Feature Augmentation</span></strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/0b41b9b8-f042-41e1-97bc-b99acce97906/image.png" alt=""><ul>
<li>최고층의 feature map에서 정보의 손실이 발생하는 것을 막기 위해 Residual Feature를 증강해서 새로운 feature map 생성</li>
<li>생성을 위해 Adaptive Spatial Fusion을 진행. 해당 과정에서 <strong>하위 feature map의 중요도를 학습</strong>하여 Weight Aggreation 진행</li>
</ul>
</li>
<li><strong><span style="color: #FF7518;">Soft RoI Selection</span></strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/610f48cf-a35d-4e55-b8b2-4002bade00ba/image.png" alt=""><ul>
<li>PANet의 max pooling시의 정보 손실을 막기 위해 시도 </li>
<li>모든 scale의 feature에서 RoI projection 진행 후 RoI pooling</li>
<li>Channel-wise 가중치 계산 후 가중합을 사용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[서비스 개발 기초]]></title>
            <link>https://velog.io/@taemin-steve/%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@taemin-steve/%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Tue, 26 Dec 2023 10:44:15 GMT</pubDate>
            <description><![CDATA[<h2 id="1-파이썬-버전-관리">1. 파이썬 버전 관리</h2>
<blockquote>
<p><strong>버전과 버저닝</strong></p>
</blockquote>
<ul>
<li><strong>버전(Version)</strong>: <span style="color: #FF7518;">소프트웨어 제품의 특정 릴리스에 대한 고유한 식별자입니다.</span></li>
<li><strong>버저닝(Versioning)</strong>: 소프트웨어에 고유한 버전 이름과 번호를 할당하는 과정입니다.</li>
</ul>
<blockquote>
</blockquote>
<p><strong>파이썬 3.11 설치하기</strong></p>
<ul>
<li>다양한 방법으로 파이썬을 설치할 수 있습니다:<ul>
<li>공식 홈페이지에서 다운로드</li>
<li>Conda를 사용하여 설치</li>
<li>Docker 이미지를 사용하여 설치</li>
<li>패키지 관리자(brew, apt, winget)를 사용하여 설치</li>
<li><strong>Pyenv</strong>를 사용하여 설치</li>
</ul>
</li>
</ul>
<hr>
<p><strong>Pyenv</strong></p>
<ul>
<li><strong>Pyenv</strong>: 파이썬의 다양한 버전을 CLI로 쉽게 설치하고 관리할 수 있는 도구입니다.</li>
</ul>
<blockquote>
<h3 id="3-파이썬-프로젝트-버전-관리">3. 파이썬 프로젝트 버전 관리</h3>
</blockquote>
<h4 id="31-가상-환경">3.1 가상 환경</h4>
<ul>
<li><strong>가상 환경</strong>: 프로젝트 별로 독립적인 파이썬 환경을 생성하여 패키지 충돌 문제를 해결합니다.</li>
</ul>
<hr>
<h4 id="32-패키지-매니저">3.2 패키지 매니저</h4>
<ul>
<li>파이썬의 주요 패키지 매니저:<ul>
<li><strong>pip</strong>: 가장 많이 사용되는 파이썬 내장 패키지 매니저입니다.</li>
<li>poetry</li>
<li>conda (주로 Anaconda의 패키지 매니저)</li>
</ul>
</li>
</ul>
<h2 id="2-리눅스linux">2. 리눅스(Linux)</h2>
<blockquote>
<p><strong>2.1 리눅스</strong></p>
</blockquote>
<ul>
<li><strong>Linux의 이해</strong><ul>
<li>개발하기 전에는 주로 Mac OS나 Windows OS에 익숙하지만, 프로그래밍에 본격적으로 입문하면 Linux를 많이 다루게 됨.</li>
<li>특히 서버와 관련된 직군에서 Linux 사용이 많음.</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Linux를 알아야 하는 이유</strong></li>
</ul>
</blockquote>
<ul>
<li>서버에서 자주 사용되는 OS로, Mac이나 Windows도 서버로 사용 가능하지만 유료임.</li>
<li>Linux는 Free이며 오픈소스로, 다양한 버전이 존재하여 사용자가 직접 버전을 만들 수도 있음.</li>
<li>Linux는 안정성과 신뢰성이 높으며, Unix 기반으로 Stability와 Reliability를 제공함.</li>
<li><span style="color: #FF7518;">쉘 커맨드와 쉘 스크립트 사용이 중요</span>.</li>
</ul>
<blockquote>
<p><strong>2.2 Shell Command</strong></p>
<ul>
<li><strong>쉘의 종류</strong></li>
</ul>
</blockquote>
<ul>
<li><strong>sh</strong>: 최초의 쉘.</li>
<li><strong>bash</strong>: Linux 표준 쉘.</li>
<li><strong>zsh</strong>: Mac Catalina OS의 기본 쉘.<blockquote>
<ul>
<li><strong>쉘 사용 사례</strong></li>
</ul>
</blockquote>
</li>
<li>서버 접속, crontab 같은 Linux 내장 기능 활용, 데이터 전처리, Docker 사용, 서버 관리 등에 쉘 커맨드 사용.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>기본 쉘 커맨드</strong></li>
</ul>
</blockquote>
<ul>
<li><code>man</code>: 쉘 커맨드의 매뉴얼 문서를 보기 위함.</li>
<li><code>mkdir</code>: 폴더 생성.</li>
<li><code>ls</code>: 현재 폴더의 파일 목록을 확인.</li>
<li><code>pwd</code>: 현재 폴더의 절대 경로를 보여줌.</li>
<li><code>cd</code>: 폴더 이동.</li>
<li><code>echo</code>: 터미널에 텍스트 출력.</li>
<li><code>cp</code>: 파일 또는 폴더 복사.</li>
<li><code>mv</code>: 파일 또는 폴더 이동 또는 이름 변경.</li>
<li><code>cat</code>: 파일 내용 출력 및 파일 합치기.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Redirection &amp; Pipe</strong></li>
</ul>
</blockquote>
<ul>
<li>Redirection을 통해 프로그램의 출력을 다른 파일이나 스트림으로 전달할 수 있음.</li>
<li>Pipe를 사용하여 한 프로그램의 출력을 다른 프로그램의 입력으로 사용 가능.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>서버에서 자주 사용하는 쉘 커맨드</strong></li>
</ul>
</blockquote>
<ul>
<li><code>ps</code>: 현재 실행 중인 프로세스를 보여줌.</li>
<li><code>curl</code>: 커맨드 라인 기반 데이터 전송, 웹 서버의 요청 테스트에 사용.<ul>
<li><code>scp</code>: SSH을 이용해 파일을 네트워크를 통해 전송.</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>2.3 쉘 스크립트</strong></p>
<ul>
<li><strong>쉘 스크립트의 이해</strong></li>
</ul>
</blockquote>
<ul>
<li>쉘 커맨드의 조합으로 구성되며, Python과 유사한 if, while, case 문을 포함할 수 있음.</li>
<li>실제 작성 예시 및 학습 방법 제공.</li>
</ul>
<h2 id="3-docker">3. Docker</h2>
<blockquote>
<p><strong>3.1 Docker 소개</strong></p>
<ul>
<li><strong>가상화란?</strong></li>
</ul>
</blockquote>
<ul>
<li>하나의 물리적 서버에 여러 개의 가상 서버를 생성하는 기술로 가상 서버는 물리적 서버의 하드웨어 자원을 공유하지만, 독립적인 운영 체제와 응용 프로그램을 실행할 수 있음 </li>
<li>가상화를 통한 일관된 개발 환경 제공의 필요성.</li>
</ul>
<hr>
<ul>
<li><strong>Container란?</strong><ul>
<li>가상화의 한 형태로, 애플리케이션과 그 애플리케이션을 실행하는 데 필요한 모든 종속 항목을 하나의 패키지로 묶은 것</li>
<li>컨테이너는 가상 머신과 달리 <span style="color: #FF7518;">운영 체제의 커널을 공유</span>하기 때문에 가볍고 효율적</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Docker 소개</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/c0102c62-3bfa-4b1a-b109-7b17c991661d/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>컨테이너 기반의 개발과 운영을 빠르게 확장.</li>
<li>가상화 기술을 쉽게 사용할 수 있는 도구.</li>
<li>Docker Image : 컨테이너를 실행할 때 사용할 수 있는 &#39;템플릿&#39;</li>
<li>Docker Container : Docker Image를 활용해 실행된 인스턴스 </li>
</ul>
<blockquote>
<p><strong>3.2 Docker 사용법</strong></p>
<ul>
<li><strong>Docker 실행 명령어</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/53ff80a2-0505-43e8-a82a-08ed18db9afb/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li><code>docker run --name [컨테이너 이름]</code>: 컨테이너에 이름 지정. 이름을 지정하지 않으면 Docker가 랜덤으로 이름을 생성</li>
<li><code>-e [환경변수=값]</code>: 컨테이너에 환경변수 설정. MySQL 컨테이너의 경우, root 계정 비밀번호 설정을 위해 <code>-e MYSQL_ROOT_PASSWORD=1234</code> 사용</li>
<li><code>-d</code>: 컨테이너를 백그라운드 모드로 실행. 이 옵션을 사용하지 않으면 컨테이너가 현재 셸 위에서 실행되며, 셸을 종료하면 컨테이너도 종료됨 .</li>
<li><code>-p [로컬 호스트 포트]:[컨테이너 포트]</code>: 로컬 호스트의 포트와 컨테이너 포트를 연결. 예: <code>-p 3306:3306</code>을 사용하여 로컬 포트 3306을 컨테이너 포트 3306에 연결</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Docker 기본 명령어</strong></li>
</ul>
</blockquote>
<ul>
<li><code>docker pull “이미지 이름:태그&quot;</code>: 필요한 이미지 다운로드.</li>
<li><code>docker images</code>: 다운받은 이미지 목록 확인.</li>
<li><code>docker run “이미지 이름:태그&quot;</code>: 이미지를 기반으로 컨테이너 생성.</li>
<li><code>docker ps</code>: 실행 중인 컨테이너 목록 확인. <span style="color: #FF7518;">-a 명령어를 활용하여 작동을 멈춘 컨테이너도 확인 가능 </span></li>
<li><code>docker exec -it “컨테이너 이름(ID)”/bin/bash</code>: 컨테이너에 진입.</li>
<li><code>docker stop “컨테이너 이름(ID)”</code>: 실행 중인 컨테이너 중지.</li>
<li><code>docker rm “컨테이너 이름(ID)”</code>: 중지된 컨테이너 삭제. <span style="color: #FF7518;">-f 옵션을 통해서 실행중인 것도 삭제 가능</span><ul>
<li><code>-v [호스트 폴더]:[컨테이너 폴더]</code>: 호스트와 컨테이너 간의 폴더 공유. <code>ex) dockerrun-it-p8888:8888-v/some/host/folder/for/work:/home/jovyan/workspace
jupyter/minimal-notebook</code><blockquote>
<ul>
<li><strong>Docker Image 작성</strong></li>
</ul>
</blockquote>
</li>
</ul>
</li>
<li>Dockerfile은 Docker Image를 빌드하기 위한 정보를 담고 있음.
<img src="https://velog.velcdn.com/images/taemin-steve/post/6c3cef1b-a249-4878-be1c-cb1381d7e7b0/image.png" alt=""></li>
<li>FROM: 이미지 빌드에 사용할 베이스 이미지를 지정.</li>
<li>COPY: 로컬 디렉토리(파일)을 컨테이너 내 디렉토리(파일)로 복사.</li>
<li>WORKDIR: Dockerfile의 명령어들을 실행할 컨테이너 경로 지정.</li>
<li>ENV: 컨테이너 내 환경변수 설정.</li>
<li>RUN: 컨테이너 내에서 리눅스 명령어 실행.</li>
<li>CMD: 컨테이너 실행 시 바로 실행할 명령어.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Docker Image 빌드</strong></li>
</ul>
</blockquote>
<ul>
<li><code>docker build -t &lt;이미지 이름:태그&gt; &lt;Dockerfile 위치&gt;</code>: Docker Image 빌드. ex): docker build -t 02-docker:latest .</li>
<li><code>-t</code> 옵션으로 이미지 이름과 태그 지정.</li>
<li>태그를 지정하지 않으면 기본적으로 <code>latest</code>가 사용됨.</li>
<li>빌드가 완료되면 <code>docker images</code> 명령어로 이미지 확인 가능.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Docker Image Push</strong></li>
</ul>
</blockquote>
<ul>
<li>이미지를 온라인 저장소에 업로드.</li>
<li><strong>로그인</strong>: <code>docker login</code> 명령어로 Docker 계정에 CLI에서 로그인.</li>
<li><strong>태그 설정</strong>: <code>docker tag &lt;기존 이미지:태그&gt; &lt;새 이미지 이름:태그&gt;</code>.<ul>
<li>Dockerhub에 올릴 경우, 이미지 이름은 <code>계정 ID/이미지 이름</code> 형태여야 함&#8203;<code>【oaicite:1】</code>&#8203;.
<img src="https://velog.velcdn.com/images/taemin-steve/post/b4342a6b-0e17-42a2-bbb6-1c0dbef27460/image.png" alt=""></li>
</ul>
</li>
<li><strong>Push</strong>: <code>docker push &lt;이미지 이름:태그&gt;</code> 명령어로 이미지 업로드.</li>
</ul>
<hr>
<ul>
<li>원격 사용법
<a href="https://donghwa-kim.github.io/vscode_ssh.html">https://donghwa-kim.github.io/vscode_ssh.html</a></li>
</ul>
<h2 id="4-디버깅">4. 디버깅</h2>
<blockquote>
<p><strong>4.1 디버깅 Process</strong></p>
<ul>
<li><strong>문제 인식</strong></li>
</ul>
</blockquote>
<ul>
<li>문제 상황 확인: 어떤 상황인지, 재현 가능성</li>
<li>오류 분류: 코드 오류, 인프라 오류, 알 수 없는 오류 등</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>해결책 찾기</strong></li>
</ul>
</blockquote>
<ul>
<li>과거 경험, 구글, Stackoverflow, 오픈카톡방, 공식 문서, Github Issue, ChatGPT 등을 통한 정보 수집</li>
<li>오답노트 및 오픈소스 코드 확인</li>
</ul>
<blockquote>
<p><strong>4.2 서버 관리</strong></p>
<ul>
<li><strong>서버의 역할과 관리</strong></li>
</ul>
</blockquote>
<ul>
<li>서버는 클라우드뿐만 아니라 집에 있는 컴퓨터로도 활용 가능</li>
<li>서버 관리의 목적: 안정적 운영 및 장애 방지</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>서버 관리를 위한 기초 지식</strong></li>
</ul>
</blockquote>
<ul>
<li>Shell Command, 파일 시스템, 네트워크, 패키지 관리, 성능 모니터링, Docker 컨테이너 등</li>
<li>Linux 파일 시스템 구성과 디스크 관리 방법</li>
</ul>
<blockquote>
<p><strong>4.3 네트워크 관리</strong></p>
<ul>
<li><strong>네트워크 관리와 진단</strong></li>
</ul>
</blockquote>
<ul>
<li>IP, DNS, 포트 관리 및 방화벽 설정</li>
<li>네트워크 진단 명령어: ping, nslookup, netstat 사용법</li>
</ul>
<h2 id="5-mlops">5. MLOps</h2>
<blockquote>
<p><strong>5.1 MLOps 개론</strong></p>
<ul>
<li><strong>모델 개발 프로세스 (Research &amp; Production)</strong></li>
</ul>
</blockquote>
<ul>
<li>MLOps : ML(MachineLearning)+Ops(Operations)</li>
<li>Research 프로세스: 문제 정의, EDA, Feature Engineering, Train, Predict.</li>
<li>Production 프로세스: 위 단계에 Deploy 단계 추가.</li>
</ul>
<blockquote>
<p><strong>5.2 MLOps Component</strong></p>
<ul>
<li><strong>Infra (Server GPU)</strong> : 서버 GPU 및 기타 인프라에 대한 중요성. (GCP, AWS)</li>
<li><strong>Serving</strong> : 모델의 배포 및 서빙 방식에 대한 설명.
<img src="https://velog.velcdn.com/images/taemin-steve/post/57e71066-9984-4582-a27d-bcd70e55a983/image.png" alt=""></li>
<li><strong>Experiment &amp; Model Management</strong> : 실험 관리와 모델 관리의 중요성.
<img src="https://velog.velcdn.com/images/taemin-steve/post/7d96b500-911d-45f0-9254-c25b74e8ab27/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li><a href="https://mlflow.org/">MLflow</a> : 모델의 개발, 배포 및 추적을 위한 오픈 소스 플랫폼. <code>mlflow.sklearn.autolog()</code> 와 같이 <span style="color: #FF7518;">한줄로 logging을 시도할 수 있음 </span><blockquote>
<ul>
<li><strong>Feature Store</strong> : 데이터 특징 저장 및 관리 방법.
<img src="https://velog.velcdn.com/images/taemin-steve/post/d7737359-85f0-4eda-99a3-03fa35f1bc57/image.png" alt=""></li>
<li><strong>Data Validation</strong> : 데이터 유효성 검증의 중요성.</li>
</ul>
</blockquote>
</li>
<li>데이터 드리프트 : 입력 데이터의 통계적 특성이 예상치 못하게 변화하여 모델 성능이 저하되는 현상</li>
<li>모델 드리프트 : 시간에 따라 입력과 출력 변수 간의 기본 관계가 변경되어 모델 성능이 저하되는 현상</li>
<li>개념 드리프트 : 모델이 예측하려는 대상 변수의 통계적 특성이 변경되는 현상<blockquote>
<ul>
<li><strong>Continuous Training</strong> : 모델의 지속적인 훈련 및 업데이트 필요성.
<img src="https://velog.velcdn.com/images/taemin-steve/post/bb1ed127-6c3e-40c5-a49f-d0149c4d1078/image.png" alt=""></li>
<li><strong>Monitoring</strong> : 모델 성능 및 상태 모니터링의 중요성.</li>
<li><strong>AutoML</strong> : 자동화된 머신러닝 프로세스의 장점.</li>
</ul>
</blockquote>
</li>
<li><a href="https://nni.readthedocs.io/en/latest/index.html">NNI</a> : 양한 머신 러닝 프레임워크와 호환되며, <span style="color: #FF7518;">다양한 하이퍼파라미터 탐색 </span> 방법을 제공</li>
</ul>
<blockquote>
<p><strong>5.3 Futher reading</strong></p>
</blockquote>
<ul>
<li><a href="https://github.com/EthicalML/awesome-production-machine-learning?tab=readme-ov-file">awesome-production-machine-learning</a></li>
<li><a href="https://github.com/visenger/awesome-mlops">awesome-mlops</a></li>
<li><a href="https://cloud.google.com/resources/mlops-whitepaper">Practitioners Guide to Machine Learning Operations (MLOps)</a></li>
</ul>
<h2 id="6model-serving">6.Model Serving</h2>
<blockquote>
<p>** 6.1 Model Serving 개요**</p>
<ul>
<li><strong>Model Serving의 정의</strong></li>
</ul>
</blockquote>
<ul>
<li>실제 환경(앱, 웹 등)에서 머신러닝 모델을 사용할 수 있도록 배포하는 과정입니다.</li>
<li>서비스화된 모델을 회사 서비스의 일부로 활용할 수 있습니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Model Serving의 주요 방식</strong></li>
</ul>
</blockquote>
<ul>
<li>Model Serving은 크게 Online Serving 과 Batch Serving 두 가지 방식으로 나뉩니다.</li>
<li>각각의 방식은 모델을 배포하고 활용하는 방법에 따라 다릅니다.</li>
</ul>
<blockquote>
<p>** 6.2 Online Serving**</p>
<ul>
<li><strong>Web Server 기초</strong></li>
</ul>
</blockquote>
<ul>
<li>Web Server는 HTTP를 통해 요청받은 내용을 전달하는 역할을 합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Online Serving의 특징</strong></li>
</ul>
</blockquote>
<ul>
<li><span style="color: #FF7518;">실시간으로 요청에 대해 예측하고 결과를 반환</span>합니다.</li>
<li>클라이언트(애플리케이션)에서 머신러닝 모델 서버에 HTTP 요청을 하고, 서버는 예측 후 결과를 반환합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Online Serving의 구현</strong></li>
</ul>
</blockquote>
<ul>
<li>직접 API 웹 서버 개발, 클라우드 서비스 활용, Serving 라이브러리 활용 등 여러 방법이 있습니다.</li>
</ul>
<blockquote>
<p><strong>6.3 Batch Serving</strong></p>
<ul>
<li><strong>Batch Serving 기초</strong></li>
</ul>
</blockquote>
<ul>
<li>Batch Serving은 <span style="color: #FF7518;">데이터를 주기적으로 한꺼번에 처리</span>합니다.</li>
<li>예: 매일 특정 시간에 데이터를 처리하거나, 일정 주기로 예측을 수행합니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Batch Serving의 예시</strong></li>
</ul>
</blockquote>
<ul>
<li>추천 시스템, 수요 예측 등 실시간 처리가 필요하지 않은 대부분의 경우에 활용됩니다.</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Batch Serving의 장단점</strong></li>
</ul>
</blockquote>
<ul>
<li>구현이 간단하고 많은 데이터를 한번에 처리할 수 있는 장점이 있습니다.</li>
<li>실시간으로 활용할 수 없다는 단점이 있습니다.</li>
</ul>
<blockquote>
<p><strong>6.4 Online Serving과 Batch Serving 비교</strong></p>
<ul>
<li><strong>선택 기준</strong></li>
</ul>
</blockquote>
<ul>
<li>데이터 처리 방식과 결과 활용 방식에 따라 선택합니다.</li>
<li>예: 데이터를 하나씩 실시간 처리해야 하면 Online, 한꺼번에 처리해도 되면 Batch 방식을 선택합니다.</li>
</ul>
<h2 id="7-ml-project-flow">7. ML Project Flow</h2>
<blockquote>
<p><strong>7.1 머신러닝 프로젝트 Flow</strong></p>
<ul>
<li><strong>문제 정의의 중요성</strong> : 문제 해결을 위해 명확한 문제 정의가 필수임을 강조.</li>
<li><strong>현상 파악</strong> : 현재 발생하고 있는 사건과 그로 인한 어려움을 파악하는 과정.</li>
</ul>
</blockquote>
<ul>
<li><strong>구체적인 문제 정의</strong> : 문제를 보다 명확하고 구체적으로 정의하고, 이를 해결하기 위한 방법 모색.</li>
<li><strong>프로젝트 설계</strong> : 문제 정의에 기반한 프로젝트의 전체적인 설계.<blockquote>
<ul>
<li><strong>지표 결정</strong> : 프로젝트의 성공을 측정하기 위한 지표를 결정.</li>
<li><strong>Action(모델 개발 후 배포 &amp; 모니터링)</strong> : 개발한 모델을 배포하고 그 성능을 모니터링하는 단계</li>
</ul>
</blockquote>
</li>
</ul>
<blockquote>
<p><strong>7.2 비즈니스 모델</strong></p>
<ul>
<li><strong>비즈니스 모델 파악하기</strong></li>
</ul>
</blockquote>
<ul>
<li>프로젝트의 비즈니스 측면을 이해하고, 비즈니스 모델을 분석하는 과정</li>
</ul>
<blockquote>
<p><strong>7.3 예시</strong> </p>
<ul>
<li><strong>문제 정의에서 출발</strong> : 문제 정의, 데이터 수집, 모델 개발, 배포 및 수익 획득의 순서로 진행.</li>
<li><strong>실제 프로젝트 과정</strong> : 문제 정의, Metric 선택, 데이터 수집, 모델 개발, 예측 결과 분석, 모델 재학습, 데이터 추가 수집, 모델 최적화 및 재학습 과정을 거침</li>
<li><strong>목표 설정</strong> : 프로젝트의 일반적인 목적과 그 달성을 위한 구체적인 단계 목표 설정.</li>
<li><strong>목표 예시</strong> : 랭킹 시스템에서 고객 참여 최대화 목표 설정 및 세부 목표 규정</li>
<li><span style="color: #FF7518;">비즈니스 목표 영향 파악</span> : 모델 성능 지표와 별개로 비즈니스 목표에 미치는 영향을 고려해야 함</li>
<li><strong>제약 조건</strong> : 프로젝트의 시간, 예산, 영향 받는 사람들 등을 고려.</li>
<li><strong>기술적 제약 및 개인정보 보호</strong> : 기존 인프라의 제약, 데이터 저장 및 보호 요구사항 등을 고려</li>
</ul>
</blockquote>
<h2 id="8-웹-서비스">8. 웹 서비스</h2>
<blockquote>
<p><strong>8.1 웹 서비스 형태 - Streamlit</strong></p>
<ul>
<li><strong>웹 서비스를 만드는 과정</strong></li>
</ul>
</blockquote>
<ul>
<li>Voila에서의 학습 내용과 Streamlit의 장점 소개</li>
<li>Voila의 장점: 노트북에서 쉽게 프로토타입을 만들 수 있음, 하지만 대시보드 레이아웃 설정이 어려움</li>
<li>Streamlit의 등장 배경: 프로토타이핑을 위한 자바스크립트, React, Vue 사용의 비효율성과 HTML/자바스크립트 + Flask/Fast API 대신 기존 코드를 소량 수정하여 웹 서비스 제작 목표</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit의 대안</strong></li>
</ul>
</blockquote>
<ul>
<li>R의 Shiny, Flask Fast API (백엔드 직접 구성 + 프론트엔드 작업), Dash (Python 대시보드 라이브러리), Voila (Jupyter Notebook 시각화)</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit 소개</strong></li>
</ul>
</blockquote>
<ul>
<li>장점: 파이썬 스크립트 코드를 소량 수정하여 웹 서비스 구현, 백엔드 개발 및 HTTP 요청 불필요</li>
<li>다양한 컴포넌트 제공, Streamlit Cloud를 통한 쉬운 배포, 화면 녹화 기능</li>
<li>예시 및 Streamlit Gallery 소개</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit 설치 및 실행</strong></li>
</ul>
</blockquote>
<ul>
<li>설치 방법: <code>pip3 install streamlit</code></li>
<li>실행 방법: CLI를 통해 <code>streamlit run streamlit-basic.py</code> 실행, localhost:8501로 접근</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit 기능</strong></li>
</ul>
</blockquote>
<ul>
<li>Text 작성, Button, Check Box, Pandas Dataframe, Markdown, Metric, JSON, Line Chart, Map Chart, Radio Button, Select Box, Multi Select Box, Slider, Input Box, Caption Code, Latex, Layout (Sidebar, Columns, Expander), Spinner, Balloons, Status Box, Form, File Uploader 등 다양한 기능</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit의 데이터 플로우</strong></li>
</ul>
</blockquote>
<ul>
<li>화면 업데이트 시 전체 코드 재실행</li>
<li>사용자 위젯 상호작용 시 코드 수정</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit Session State</strong></li>
</ul>
</blockquote>
<ul>
<li>데이터 플로우로 인한 코드 재실행 문제 해결을 위한 Global Variable 비슷한 기능</li>
<li>Streamlit 0.84 버전에 session_state 개발</li>
<li>Counter 예제로 session_state 사용 방법 설명</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>Streamlit Cache - @st.cache</strong></li>
</ul>
</blockquote>
<ul>
<li>매번 코드 재실행으로 인한 데이터 재읽기 문제를 해결하기 위한 캐싱 기능</li>
<li>데이터 읽는 함수에 데코레이터 적용 방법</li>
</ul>
<hr>
<blockquote>
<ul>
<li><strong>특별 임무</strong></li>
</ul>
</blockquote>
<ul>
<li>Jupyter Notebook으로 만든 마스크 분류 모델을 Streamlit으로 구현</li>
<li>공식 문서 읽고 정리</li>
<li>Callback 함수를 사용하여 session_state 값을 유지하는 코드 작성</li>
<li>CV/NLP에서 진행한 프로젝트를 Streamlit으로 구현</li>
</ul>
<h2 id="추가-라이브러리">추가 라이브러리</h2>
<blockquote>
</blockquote>
<ul>
<li>poetry</li>
<li>MLflow</li>
<li>NNI</li>
<li>wandb</li>
<li>streamlit</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Deep Learning Basic]]></title>
            <link>https://velog.io/@taemin-steve/Deep-Learning-Basic</link>
            <guid>https://velog.io/@taemin-steve/Deep-Learning-Basic</guid>
            <pubDate>Mon, 20 Nov 2023 06:59:03 GMT</pubDate>
            <description><![CDATA[<h2 id="1-neural-networks--multi-layer-perceptron">1. Neural Networks &amp; Multi-Layer Perceptron</h2>
<blockquote>
<p><strong>1.1 Neural networks</strong></p>
</blockquote>
<ul>
<li>정의 : 비선형 변환을 통해 우리가 원하는 함수로 근사시키는 모델</li>
</ul>
<blockquote>
</blockquote>
<p><strong>1.2 MLP</strong></p>
<ul>
<li>다층 신경망으로, Neural Networks가 적층되어 있는 구조 </li>
<li>각각의 Layer를 다른 차원으로 변환시켜주는 행렬로 생각해주는 것이 좋음</li>
<li>이때 Activation Function을 활용하여 비선형성을 주지 못한다면 합성곱으로 인해 그저 하나의 층이 있는 것과 동일하다.</li>
</ul>
<h2 id="2-optimization">2. Optimization</h2>
<blockquote>
<p><strong>2.1 Important Concepts in Optimization</strong></p>
</blockquote>
<ul>
<li><strong>Generalization</strong> : 보지 않은 데이터에 대해서 모델이 어떻게 반응할 것인가<ul>
<li>Underfitting : 과소적합 </li>
<li>Overfitting : 과적합 
<img src="https://velog.velcdn.com/images/taemin-steve/post/f6d6f8c4-98f2-4ca2-94e9-4f410cc3ee29/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>Cross-validation</strong> : Validation Set을 K개로 나누어 K-1 개로 학습을 진행하고, 나머지 하나에 대해서 검증을 진행하는 방식.<br><img src="https://velog.velcdn.com/images/taemin-steve/post/1aba5b23-7a7c-445e-85bd-79d62db90df8/image.png" alt=""></li>
</ul>
<hr>
<ul>
<li><strong>Bias and Variance Tradeoff</strong> : 모델의 복잡도가 증가하면 Bias는 감소 할수 있을지 몰라라도 반대로 Variance가 커진다. 아래의 그림과 같이 Bias와 Variance는  Trade Off 관계로 두개를 모두 만족하는 모델을 찾기란 어렵다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/d58ba7fe-b6d1-45f6-9546-627cc930f41f/image.png" alt=""></li>
</ul>
<hr>
<ul>
<li><strong>Bootstrapping</strong> : 표본 데이터로부터 추가적인 표본을 생성하여 여러 모델을 학습하고, 모델들의 결과를 종합해 결론을 내는 방식<ul>
<li>Bagging(Bootstrapping aggregating) : bootstrapping을 통해 생성된 여러 모델들의 voting 혹은 평균값을 활용하여 결과를 도출 </li>
<li>Boosting : 순차적으로 강화되는 방식으로 모델을 훈련시킴. 이전 모델이 잘못 예측한 샘플에 가중치를 높여서 다음 모델을 훈련시키는 방식.
<img src="https://velog.velcdn.com/images/taemin-steve/post/d5b610b5-84d5-4f42-ab8d-b20fff00a69e/image.png" alt=""></li>
</ul>
</li>
</ul>
<blockquote>
<p>*<em>2.2 Gradient Descent Method *</em></p>
</blockquote>
<ul>
<li><strong>Batch-size</strong><ul>
<li>Batch gradient descent : 전체 데이터를 사용하여 gradient를 계산, 시간이 오래걸린다는 단점이 있음</li>
<li>Mini-batch gradient descent : Mini-batch 단위에 들어있는 데이터를 활용하여 데이터를 계산</li>
<li>Stochastic gradient descent : 무작위로 선택된 하나의 데이터 포인트에 대한 그래디언트을 활용해 gradient 계산, 로컬 미니마로 부터 벗어날 가능성이 있음.</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>Batch-size Matter</strong>
<span style="color: #FF7518;"><strong>Batch Size가 작을수록 Flat Minimum로 수렴하기 때문에 보다 일반화 성능이 올라감</strong></span>. Flat Minimum의 경우 함수의 굴곡이 작아, 비교적 적은 차이를 만들어낼 수 있기 때문.
<img src="https://velog.velcdn.com/images/taemin-steve/post/f5e94e68-1634-4ad5-80c5-f9c5e65e12d7/image.png" alt=""></li>
</ul>
<hr>
<ul>
<li>*<em>Gradient Descent Methods *</em>
<img src="https://velog.velcdn.com/images/taemin-steve/post/2efc1932-8764-4fac-9e95-0ed3b2d9c597/image.png" alt=""><ul>
<li>Stochastic gradient descent
여기서 $J()$는 손실함수 <blockquote>
<blockquote>
<p>$\theta_{t+1} = \theta_t - \eta \nabla J(\theta_t; x^{(i)}, y^{(i)})$</p>
</blockquote>
</blockquote>
</li>
<li>Momentum :이전의 gradient 변화를 고려하여 관성을 부여하는 방식. 기울기가 0인 지점에서 momentum이 존재하여 local minima에서 벗어날 수 있음. $v_t$는 모멘텀<blockquote>
<blockquote>
<p>$v_t = \beta v_{t-1} + (1 - \beta) \nabla J(\theta_t)$
$\theta_{t+1} = \theta_t - \eta v_t
$</p>
</blockquote>
</blockquote>
</li>
<li>Nesterov Accelerated Gradient (NAG): 모멘텀을 사용하지만, 현재 위치가 아니라, 모멘텀 방향으로 더 진행한 상태의 gradient를 업데이트 하는 방식 <blockquote>
<blockquote>
<p>$v_t = \beta v_{t-1} + (1 - \beta) \nabla J(\theta_t - \eta \beta v_{t-1})$
$\theta_{t+1} = \theta_t - \eta v_t$</p>
</blockquote>
</blockquote>
</li>
<li>Adagrad : 매개변수 마다 학습률을 조절하여 업데이트 하는 방식. 변화값이 클 수록 학습속도가 감소함. 학습이 지속되면서 결국 학습이 잘 일어나지 않는 문제가 존재. $s_t$ : 각 매개 변수의 gradient의 누적 값<blockquote>
<blockquote>
<p>$g_t = \nabla J(\theta_t)$
$s_t = s_{t-1} + g_t^2$
$\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{s_t + \epsilon}} g_t$</p>
</blockquote>
</blockquote>
</li>
<li>Adadelta : Accumulation window를 활용하여 학습률이 지속적으로 감소하는 것을 방지 <blockquote>
<blockquote>
<p>$g_t = \nabla J(\theta_t)$
$s_t = \rho s_{t-1} + (1 - \rho) g_t^2$
$\theta_{t+1} = \theta_t - \frac{\sqrt{\Delta 
\theta_{t-1} + \epsilon}}{\sqrt{s_t + \epsilon}} g_t
$</p>
</blockquote>
</blockquote>
</li>
<li>RMSprop: 경험적으로 이렇게 하니깐 잘되더라~<blockquote>
<blockquote>
<p>$g_t = \nabla J(\theta_t)$
$s_t = \rho s_{t-1} + (1 - \rho) g_t^2$
$\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{s_t + \epsilon}} g_t$</p>
</blockquote>
</blockquote>
</li>
<li><span style="color: #FF7518; padding: 2px;"><strong>Adam</strong></span> : 모멘텀과 RMSprop을 결합하여 사용하는 최적화 알고리즘.(대체로 Adam이 성능이 잘나온다)
$v_t$ : EMA of gradient squares<blockquote>
<blockquote>
<p>$m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t$
$v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2$
$\hat{m}<em>t = \frac{m_t}{1 - \beta_1^t}$
$\hat{v}_t = \frac{v_t}{1 - \beta_2^t}$
$\theta</em>{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t$</p>
</blockquote>
</blockquote>
</li>
<li><span style="color: #FF7518; padding: 2px;"><strong>AdamW</strong></span> : 
AdamW는 Adam 옵티마이저의 변형으로, 가중치 감쇠(weight decay)를 적용하여 모델의 복잡성을 제어하고, 오버피팅(overfitting)을 완화. </li>
</ul>
</li>
</ul>
<h2 id="3-regularization">3. Regularization</h2>
<blockquote>
<p><strong>Regularization</strong></p>
</blockquote>
<ul>
<li><strong>Early Stopping</strong> : 학습중에 과적합이 되는 것을 방지하기 위해, Validation error가 더이상 증가하지 않는 시점에서 학습을 중지하는 기법. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/c95102df-4072-4d36-9bd5-ae8981503d99/image.png" alt=""></li>
</ul>
<hr>
<ul>
<li><strong>Parameter Norm Penalty</strong> : 모델의 파라미터가 너무 커지지 않도록 손실함수에 정규화 항을 추가하는 기법. 파라미터가 작은 값을 가지면 함수공간에서 더욱 부드러운 함수가 생성되어 보다 일반화 성능이 높을 것이라고 예상.<blockquote>
<blockquote>
<p>$\text{total cost} = \text{loss(D;W)} + \lambda \sum_{i} |W_i|^2$</p>
</blockquote>
</blockquote>
</li>
</ul>
<hr>
<ul>
<li><strong>Data Augmentation</strong> : 습 데이터를 다양한 방법으로 변형하여 모델의 일반화 성능을 향상시키는 기법.</li>
</ul>
<hr>
<ul>
<li><strong>Noise Robustness</strong> : 모델이 입력 데이터에 포함된 노이즈에 강건하게 대응할 수 있도록 학습하는 기법. input 뿐만 아니라 학습 중간에 모델의 가중치에도 노이즈를 적용할 수 있음. </li>
</ul>
<hr>
<ul>
<li><span style="color: #FF7518;"><strong>Label Smoothing</strong></span> : 모델이 과적합되거나 너무 확신하지 않도록 하기 위해 정답 라벨에 소프트 업데이트를 적용하는 기법<ul>
<li>Mix up : 서로다른 레이블의 input 데이터를 섞고, label 또한 값을 섞어주는 방식 </li>
<li>Cut mix : 서로다른 레이블의 input 데이터를 자르고 붙이고, label 또한 적정 비율로 섞어주는 방식 
<img src="https://velog.velcdn.com/images/taemin-steve/post/48f1512d-53df-4bf0-8f47-33be2c510013/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>Dropout</strong> : 학습 중에 무작위로 선택된 뉴런을 비활성화하여 모델의 과적합을 방지하는 기법</li>
</ul>
<hr>
<ul>
<li><strong>Batch Normalization</strong> : 학습 중에 각 미니배치의 입력을 정규화하여 학습을 안정화시키고 속도를 향상시키는 기법
<img src="https://velog.velcdn.com/images/taemin-steve/post/a4df9975-d2f8-42db-bf23-8609ccd13356/image.png" alt=""></li>
</ul>
<h2 id="4-convolutional-neural-networks">4. Convolutional Neural Networks</h2>
<blockquote>
<p><strong>4.1 Convolutional Neural Networks</strong></p>
</blockquote>
<ul>
<li>Conv : 데이터와 필터(또는 커널) 간의 연산으로, 입력 데이터에서 유용한 정보를 추출. 필터는 작은 가중치 행렬로, 입력 데이터를 도장처럼 스캔하면서 특징을 감지.</li>
</ul>
<hr>
<ul>
<li>모델의 parameter 계산 : Kernel W x Kernel W x input channel x output channel (input channel의 개수 만큼 동일한 크기의 kernel이 확장된다고 생각해야함. 동일한 kernel을 재사용하는 것이 아니다.)</li>
</ul>
<blockquote>
<p><strong>4.2 Modern CNN</strong></p>
</blockquote>
<ul>
<li><strong>AlexNet</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/fe961e4b-45f7-46b3-8f14-a6c7912850e7/image.png" alt=""><ul>
<li><span style="color: #FF7518;"><strong>ReLU activation</strong></span> : ReLU(Rectified Linear Unit) 활성화 함수가 사용. 빠르게 수렴하며, 그레디언트 소실 문제를 줄여 학습이 효과적(양수 영역에서는 y = x 형태의 선형함수의 형질을 유지하고 있기에 미분도 용이)</li>
<li>Data Augmentation </li>
<li>Dropout</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>VGGNet</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/a72eaad4-9774-4ea3-9e66-ebe9b81bee18/image.png" alt=""><ul>
<li><span style="color: #FF7518;"><strong>3x3 크기의 kernel 사용</strong></span> : 동일한 Receptive field를 가지게 하는 kernel 간의 비교에서, 작은 크기의 kernel을 활용하는 것이 parameter 측면에서 이득이 존재.(parameter 수의 감소로 학습이 용이 )
<img src="https://velog.velcdn.com/images/taemin-steve/post/cedac3fc-6745-482d-8c3e-45ace16ae51d/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>GoogLeNet</strong>
<img src="https://paperswithcode.com/media/methods/Screen_Shot_2020-06-22_at_3.22.39_PM.png" alt=""><ul>
<li>NiN 구조 : Network 안에 Network가 있는 구조를 활용하였음</li>
<li>Inception block : <span style="color: #FF7518;"><strong>1x1 Conv Layer를 활용하여 Parameter 수를 감소</strong></span>시키고, 다양한 크기의 Conv Layer를 거친 정보를 취합.
<img src="https://velog.velcdn.com/images/taemin-steve/post/2b954ad4-3ed9-428e-91b9-82bc40e9d57a/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>*<em>ResNet *</em><ul>
<li>Residual Block : <span style="color: #FF7518;"><strong>Skip Connection</strong></span>을 이용하여 Gradient vanishing을 완화하고, 이로인해 더 깊은 Layer에 대해서 학습이 가능하게 한다. (BN은 conv 뒤에 오기도 하고, ReLU 뒤에 오기도 한다) 
<img src="https://d2l.ai/_images/resnet-block.svg" alt=""></li>
<li>Bottlenck architecture: 1x1 layer를 활용하여  차원 축소의 효과를 발생시키고, parameter수를 감소시킨다. 
<img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGcSbV%2FbtqTkgJVRN1%2Fvkap6By64KbxsCLdpTpyhk%2Fimg.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>DenseNet</strong>
<img src="https://velog.velcdn.com/images/taemin-steve/post/b1a23bc8-bba1-483e-b634-06b30e0ee753/image.png" alt=""><ul>
<li>DensBlock : Resnet과 다르게 <span style="color: #FF7518;"><strong>모든 선행 layer의 output을 concatenate</strong></span> 하여 다음 layer로 전달.(이때 concatenate 하기 때문에 output의 channel이 기하적으로 증가한다. 또한 DensBlock 내의 layer에서는 output의 크기가 모두 동일하기 때문에 concatenate 가능하다.)</li>
<li>Transition Block : Dense Block 사이을 이어주는 block으로 1x1 Conv, 2x2 AvgPooling 진행</li>
</ul>
</li>
</ul>
<h2 id="5-computer-vision-applications">5. Computer Vision Applications</h2>
<blockquote>
<p>*<em>5.1 Semantic Segmentation *</em></p>
</blockquote>
<ul>
<li>Semantic Segmentation : 미지를 픽셀 단위로 분할하여 각 픽셀을 해당하는 객체 또는 클래스로 할당하는 작업</li>
</ul>
<hr>
<ul>
<li>Fully Convolutional Network (FCN)<ul>
<li>기존의 네트워크는 Dense Lyaer를 거치면서 대부분의 공간정보를 손실한다. 이를 해결하기 위해 모든 layer를 Conv layer로 사용한다. </li>
<li>이와 같이 진행하는 경우 input 이미지의 size와 상관없이 동작하며 heatmap 형식으로 결과를 도출 할 수 있음 </li>
<li>Upsampling : 앞에서 추출한 feature를 바탕으로 Upsampling을 하여 기존의 이미지 크기로 복원. 이때 Deconvolution을 활용 
<img src="https://velog.velcdn.com/images/taemin-steve/post/3d2f78e7-1f03-403b-a8e5-428cf8cf057f/image.png" alt=""></li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>5.2 Detection</strong></p>
</blockquote>
<ul>
<li>R-CNN
<img src="https://velog.velcdn.com/images/taemin-steve/post/dd5c9fdd-b795-4d2f-bdd8-fec24d7027e0/image.png" alt=""><ul>
<li>image input</li>
<li>Region proposals : Selective search를 활용하여 2000개의 객체 위치 제안</li>
<li>feature 계산 : 각 Region Proposal에 대한 특징값을 계산(CNN 활용)</li>
<li>객체 분류 : SVM(Support Vector Machine)을 활용하여 객체의 클래스 분류 <blockquote>
<blockquote>
<p>🔍 Selective search : 각각의 segment로 임의 분할하고, 각각의 segment간의 유사도를 측정하여 유사한 특징을 가지는 객체끼리 같은 객체로 분류</p>
</blockquote>
</blockquote>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>SPP-Net
<img src="https://velog.velcdn.com/images/taemin-steve/post/6cdc2922-a3c4-47f5-b6cd-8f957bfb8ac6/image.png" alt=""><ul>
<li>Convolutional Feature Extraction: R-CNN과 다르게 Conv layer를 우선적으로 수행</li>
<li>Spatial Pyramid Pooling : 이미지의 다양한 크기의 영역에 대해 고정된 크기의 특징 벡터를 생성(spatial bins의 개수를 정하고 pooling을 진행하기에 이미지의 크기에 상관없이 고정길이 feature 추출 가능) 
<img src="https://velog.velcdn.com/images/taemin-steve/post/4e1f7927-1159-407a-bd34-1afb85c7dabe/image.png" alt=""></li>
<li>Fully Connected Layers : 위에서 생성한 feature map을 FC layer에 입력. </li>
<li>분류 및 예측 : SVM, BBox 등 진행 </li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>Fast R-CNN
<img src="https://velog.velcdn.com/images/taemin-steve/post/34119371-c6eb-4d23-b96e-1b3d93005bb9/image.png" alt=""><ul>
<li>Selective Search : RoI(Resion Of Interset) 추출</li>
<li>ConvNet : Conv를 통해 feature map 추출</li>
<li>RoI pooling : RoI를 projection 시켜 해당 영역의 feature map에 대해서 RoI pooling 진행 </li>
<li>FC layer : FC layer를 활용하여 고정길이 vector로 변환<blockquote>
<blockquote>
<p>RoI Pooling : Receptive field가 RoI에 맞게끔 계산하여 영역을 정하고 해당 부분에 대해서 pooling을 진행. 아래 그림에서 정중앙이 아닌 이유는 영역의 크기가 홀수 여서 버림을 진행하였기 때문! 
<img src="https://velog.velcdn.com/images/taemin-steve/post/8f5a8c65-c75b-46c3-a846-94d862faf7df/image.png" alt=""></p>
</blockquote>
</blockquote>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>Faster R-CNN
<img src="https://velog.velcdn.com/images/taemin-steve/post/20abb39c-1fa4-4f92-836a-8d52790c4dfe/image.png" alt=""><ul>
<li>RPN(Region Proposal Network) : 기존의 Selective Search 대신 해당 기능을 수행하는 RPN을 학습시켜 보다 빠르게 진행.</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>YOLO</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Pytorch]]></title>
            <link>https://velog.io/@taemin-steve/Pytorch</link>
            <guid>https://velog.io/@taemin-steve/Pytorch</guid>
            <pubDate>Fri, 17 Nov 2023 02:50:04 GMT</pubDate>
            <description><![CDATA[<h2 id="1-pytorch">1. Pytorch</h2>
<hr>
<blockquote>
<p><strong>1.1 Pytorch</strong></p>
</blockquote>
<ul>
<li>Define and Run : 그래프를 먼저 정의 하고 실행 시점에 데이터를 feed해주는 방식. &gt;&gt; Tensorflow</li>
<li>Define by Run : 실행을 하면서 그래프를 생성하는 방식, 디버깅에 강점이 있다. &gt;&gt; Pytorch</li>
<li>중요 요소 : Numpy, AutoGrad, Function</li>
</ul>
<blockquote>
</blockquote>
<p>*<em>1.2 Tensor *</em></p>
<ul>
<li>다차원 Array를 표현하는 Pytorch의 클래스로 사실상 Numpy의 ndarray와 동일하다. </li>
<li>torch.tensor(list) 혹은 torch.from_numpy(ndarray)를 활용하여 생성할 수 있음</li>
<li>torch.ones_like(), torch.flatten()등의 함수도 numpy와 동일하게 사용 가능하며, 슬라이싱도 가능하다.</li>
<li>torch.to(&#39;cuda&#39;)를 활용하여 GPU에 올려서 사용가능. 단 이때 사용가능한 data type에 제한이 있다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/78be21e4-63e7-4052-8421-c8e02c49e4ad/image.png" alt=""></li>
</ul>
<blockquote>
</blockquote>
<p>*<em>1.3 Tensor()를 다루는 다양한 함수 *</em></p>
<ul>
<li><strong>torch.view()</strong>, torch.squeeze(), torch.unsqueeze()<pre><code class="language-python">import torch
# 초기 텐서 생성
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
# view를 사용하여 텐서의 모양 변경
y = x.view(3, 2)  # 결과: tensor([[1, 2], [3, 4], [5, 6]])
# 크기가 1인 차원을 가진 텐서 생성
z = torch.randn(1, 3, 1, 4)
# squeeze를 사용하여 크기가 1인 차원 제거
w = z.squeeze()  # 결과: tensor([[-0.1901,  0.2942, -0.9842,  1.3037],
               #         [ 0.4764,  0.1214,  0.8612,  0.5646],
               #         [ 0.3986, -0.2139, -0.5733, -0.5669]])
# 크기가 3인 차원을 가진 텐서 생성
a = torch.tensor([1, 2, 3])
# unsqueeze를 사용하여 인덱스 1에 차원 추가
b = a.unsqueeze(1)  # 결과: tensor([[1], [2], [3]])</code></pre>
</li>
<li><strong>torch.mm()</strong> : 행렬곱셈을 진행시켜준다. 단 torch.matmul 또한 행렬의 곱셈을 지원하지만, broadcasting 기능이 지원되기 때문에 명확하게 이해하고 사용하지 않으면 문제가 발생할 수 있음 </li>
</ul>
<blockquote>
</blockquote>
<p><strong>1.4 torch.reshape vs torch.view()</strong></p>
<ul>
<li>view 함수의 경우 텐서 내부 데이터를 공유하여 모양을 변경하기 때문에, 새로운 텐서는원래 텐서와 데이터를 공유하게 되며, <span style="background-color: #FFE082; padding: 2px;">연속적인 메모리에 할당</span>된다. </li>
<li>reshape의 경우 내부 데이터를 복사하여 모양을 변경하며, 연속적인 메모리 공간을 보장하지 않는다. </li>
</ul>
<blockquote>
</blockquote>
<p><strong>1.5 Autograd</strong>
Autograd는 PyTorch에서 제공하는 자동 미분 기능을 담당하는 패키지이다. PyTorch는 딥러닝 모델을 학습시키기 위해 역전파 알고리즘을 사용하는데, 이때 모델의 파라미터에 대한 손실 함수의 기울기(gradient)를 계산해야 한다. Autograd는 이러한 기울기를 자동으로 계산해주는 기능을 제공하여 딥러닝 모델의 학습을 간편하게 만들어줌.</p>
<ul>
<li>backward() 함수를 loss를 적용하면 하위 항목들에 모두 적용 된다. <pre><code class="language-python">import torch
from torch.autograd import Variable
x = Variable(torch.Tensor([2]), requires_grad=True)
y = x ** 2 + 3
loss = 10 - y
loss.backward()
print(x.grad)
# x.grad 값이 자동으로 계산되어 있다


</code></pre>
</li>
</ul>
<h2 id="2-pytorch-templete">2. Pytorch Templete</h2>
<hr>
<blockquote>
</blockquote>
<p>항상 하나의 주피터 노트북에서 학습하는 것은 한계가 있다.(배포의 어려움과, 실행 순서에 따른 결과가 상이해 질 수 있음) 언젠가는 OOP의 구조로 모델을 구성해야하는 시점이 온다. 이를 위해서 미리 지정된 <a href="https://github.com/victoresque/pytorch-template">Teamplete</a>을 활용하여 보다 편리하게 개발을 진행할 수 있다. 프로젝트는 아래와 같은 구조를 가지게 된다.</p>
<pre><code>pytorch-template/
│
├── train.py - main script to start training
├── test.py - evaluation of trained model
│
├── config.json - holds configuration for training
├── parse_config.py - class to handle config file and cli options
│
├── new_project.py - initialize new project with template files
│
├── base/ - abstract base classes
│   ├── base_data_loader.py
│   ├── base_model.py
│   └── base_trainer.py
│
├── data_loader/ - anything about data loading goes here
│   └── data_loaders.py
│
├── data/ - default directory for storing input data
│
├── model/ - models, losses, and metrics
│   ├── model.py
│   ├── metric.py
│   └── loss.py
│
├── saved/
│   ├── models/ - trained models are saved here
│   └── log/ - default logdir for tensorboard and logging output
│
├── trainer/ - trainers
│   └── trainer.py
│
├── logger/ - module for tensorboard visualization and logging
│   ├── visualization.py
│   ├── logger.py
│   └── logger_config.json
│  
└── utils/ - small utility functions
    ├── util.py
    └── ...</code></pre><h2 id="3-torchnnmodule">3. torch.nn.Module</h2>
<hr>
<blockquote>
<p><strong>3.1 torch.nn.Moudle 이란?</strong>
<span style="background-color: #FFE082; padding: 2px;">신경망 모델을 정의할 때 사용되는 기본 클래스</span>. torch.nn.Module을 상속하는 클래스는 다양한 신경망 계층(layer) 및 다른 모듈들을 포함할 수 있다. 이를 통해 복잡한 모델을 구축할 수 있고, 각 계층의 파라미터들은 모델 내에서 자동으로 추적되어 역전파를 통한 학습이 가능해짐.</p>
</blockquote>
<blockquote>
</blockquote>
<p><strong>3.2 nn.Paramerter()</strong></p>
<ul>
<li>모듈의 attributre가 될 수 있고, required_grad = True로 지정되어 <strong>학습 대상이 되는 Tensor</strong>. Tensor를 상속해서 구현한다. </li>
</ul>
<blockquote>
<p><strong>3.3 foward()</strong></p>
</blockquote>
<ul>
<li>모델이 입력 데이터를 받아 <span style="background-color: #FFE082; padding: 2px;">순전파(forward pass) 연산을 수행</sapn>하는 곳으로, 모델의 아키텍처를 정의하는 부분</li>
<li>해당 함수가 baward pass를 진행시킬 수 있게금 방향을 제시해준다. </li>
</ul>
<blockquote>
<p><strong>3.4 backward()</strong></p>
</blockquote>
<ul>
<li>PyTorch에서 자동 미분을 수행하는 데 사용되는 메서드로, 주로 손실 함수를 통한 역전파(backward propagation) 단계에서 호출. 역전파는 모델의 파라미터에 대한 손실 함수의 기울기<span style="background-color: #FFE082; padding: 2px;">(gradient)를 계산</span>하고, 이를 사용하여 모델의 파라미터를 업데이트하는 데 사용.</li>
<li>해당 함수를 호출하면 계산은 되지만, Update 되지는 않는다.</li>
</ul>
<blockquote>
</blockquote>
<p><strong>3.5 optimizer.step()</strong></p>
<ul>
<li>모델 파라미터 업데이트 할 때 사용</li>
</ul>
<h2 id="4-dataset--dataloaders">4. Dataset &amp; Dataloaders</h2>
<hr>
<blockquote>
<p><strong>4.1 Dataset</strong>
데이터 입력 형태를 정의하는 클래스로, <span style="background-color: #FFE082; padding: 2px;"><strong>init</strong>(), <strong>len</strong>(), <strong>getitem</strong>()</span> 등을 반드시 재정의 해주어야 한다. </p>
</blockquote>
<blockquote>
<p><strong>4.2 DataLoader</strong></p>
</blockquote>
<ul>
<li>Data의 Batch를 생성해주는 클래스로, 학습 직전에 데이터 변환을 책임진다. </li>
<li>주요 역할 : Tensor로 변환, Batch 처리 </li>
<li>iterable 형태로 돌려주기 때문에, 데이터가 크더라도 필요할 때만 불러오기 때문에 batch 사이즈만큼의 메모리 공간만을 차지하게 한다. </li>
</ul>
<h2 id="5-model-재활용하기">5. Model 재활용하기</h2>
<hr>
<blockquote>
<p><strong>5.1 model.save()</strong></p>
</blockquote>
<ul>
<li>학습 결과를 저장하기 위한 함수로, 형태와 파라미터(추천!)등을 저장할 수 있다.</li>
<li>요즘은 대부분 <span style="background-color: #FFE082; padding: 2px;">.pt</span> 파일로 저장하는 추세</li>
</ul>
<blockquote>
</blockquote>
<p><strong>5.2 model.load_state_dict()</strong>
동일한 형태의 모델의 파라미터들을 불러와서 model에 저장 가능. </p>
<h2 id="6-monitoring">6. Monitoring</h2>
<blockquote>
<p>훅, 데코레이터 등</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Python Basic]]></title>
            <link>https://velog.io/@taemin-steve/Naver-Boostcamp-AI-tech-Week1</link>
            <guid>https://velog.io/@taemin-steve/Naver-Boostcamp-AI-tech-Week1</guid>
            <pubDate>Fri, 10 Nov 2023 02:30:12 GMT</pubDate>
            <description><![CDATA[<h1 id="python">Python</h1>
<hr>
<p>그동안 파이썬을 쓰면서도 자세하게 알지 못했던 부분을 정리하고자 한다.</p>
<h2 id="1-sequence-type"><a href="https://dojang.io/mod/page/view.php?id=2205">1. Sequence Type</a></h2>
<blockquote>
</blockquote>
<p>리스트, 튜플, 문자열등과 같이 값이 연속적으로 이어진 자료형을 Sequence Type이라고 하며 다음과 같은 공통 method를 사용할 수 있다. </p>
<ul>
<li>인덱싱</li>
<li>복제 ([1,2,3] * 3)</li>
<li>덧셈 ([1,2,3] + [4,5,6])</li>
<li>in (특정 원소가 해당 자료형 안에 존재하는지 확인)</li>
<li>이터레이션 (for loop)</li>
<li>enumerate()</li>
<li>zip() </li>
</ul>
<h2 id="sequence-vs-iterable">Sequence vs Iterable</h2>
<blockquote>
<p>Iterable이 조금 더 큰 개념이다. indexing을 통해 개별 원소에 접근이 가능하다면 Sequence type이다!</p>
</blockquote>
<h2 id="2-shallow-copy-와-deep-copy"><a href="https://wikidocs.net/16038">2. Shallow copy 와 Deep copy</a></h2>
<blockquote>
<h3 id="mutable-과-immutable">mutable 과 immutable</h3>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/12532975-7126-4f1b-b267-9531379a27bd/image.png" alt="">
Mutable :  생성된 후에도 변경이 가능한 객체. 대표적으로 list, dict, set등이 있다.
Immutable : 생성이후에 변경이 불가능한 객체로 수정하기 위해서는 새로운 객체를 생성(메모리 할당)해야 한다. 대표적으로 int, str, tuple 등이 있다.</p>
</blockquote>
<pre><code class="language-python"># mutable
my_list = [1, 2, 3]
my_list[0] = 99  # 기존 객체를 직접 수정 가능
#immutable
a = 5
a = a + 1  # 이때 새로운 객체가 생성되어 할당됨</code></pre>
<h3 id="shallow-copy-와-deep-copy">Shallow copy 와 Deep copy</h3>
<blockquote>
</blockquote>
<p>Deep copy : 원본 객체와 복사된 객체가 서로 독립적인 객체를 참조
Shallow copy : 복사된 객체와 원본 객체가 동일한 객체를 참조
이때 immutable 객체에 대해서는 Deep copy가 발생하지만, mutable 객체에 대해서는 Shallow copy가 발생한다. 이때문에 아래와 같이 복사한 객체의 값을 바꾸면 <strong>원본 객체의 값도 변하는 문제가 발생</strong>한다. </p>
<pre><code class="language-python">import copy
original_list = [1, [2, 3], 4]
shallow_copied_list = copy.copy(original_list)
# 얕은 복사이므로 내부 리스트는 동일한 객체를 참조
print(original_list)            # [1, [2, 3], 4]
print(shallow_copied_list)      # [1, [2, 3], 4]
# 내부 리스트의 값을 변경하면 원본과 복사된 리스트에 모두 반영
shallow_copied_list[1][0] = 99
print(original_list)            # [1, [99, 3], 4]
print(shallow_copied_list)      # [1, [99, 3], 4]</code></pre>
<p>이런 문제를 해결하기 위해 copy 모듈의 <strong>deepcopy()</strong> method를 활용하여 해결 가능하다.</p>
<pre><code class="language-python">import copy
original_list = [1, [2, 3], 4]
deep_copied_list = copy.deepcopy(original_list)
# 깊은 복사이므로 내부 리스트도 새로운 객체를 참조
print(original_list)          # [1, [2, 3], 4]
print(deep_copied_list)        # [1, [2, 3], 4]
# 내부 리스트의 값을 변경해도 원본에만 영향을 줌
deep_copied_list[1][0] = 99
print(original_list)          # [1, [2, 3], 4]
print(deep_copied_list)        # [1, [99, 3], 4]</code></pre>
<h2 id="3interning">3.interning</h2>
<blockquote>
</blockquote>
<p>-5 ~ 256까지의 작은 정수를 메모리에 미리 할당하고, 동일한 값의 작은 정수가 생성될 때 마다 미리 할당된 메모리 주소를 참조하게끔 함.</p>
<pre><code class="language-python">a = 10
b = 10
print(a is b)  # True, 동일한 메모리 주소를 가리킴
c = 257
d = 257
print(c is d)  # False, 서로 다른 메모리 주소를 가리킴</code></pre>
<h2 id="4string">4.String</h2>
<blockquote>
</blockquote>
<h3 id="1-f-string">1) f-string</h3>
<p><a name="f-string"></a>
파이썬 3.6 버전부터 도입된 문자열 포매팅 방법 중 하나로, 문자열 안에 변수나 표현식을 간편하게 삽입할 수 있도록 하는 기능</p>
<pre><code class="language-python"># 변수값 직접 사용 
name = &quot;Alice&quot;
age = 25
message = f&quot;안녕하세요, {name}님! {age}살이시네요.&quot;
# 소수점 이하 자릿수 지정
height = 175.5
message = f&quot;키: {height:.2f}cm&quot;
# 정렬 및 폭 지정
name = &quot;Bob&quot;
age = 30
height = 175.5
message = f&quot;Name: {name:&lt;10}, Age: {age:03d}, Height: {height:.2f}&quot;
# 왼쪽 정렬, 총 10자리, 정수는 3자리, 소수는 2자리까지
# 빈칸 *지정, 가운데 정렬
x = 42
formatted_x = f&quot;The answer is: {x:*^20}&quot;</code></pre>
<h3 id="2-raw-string">2) raw string</h3>
<p><a name="rawstring"></a>
특수 문자(이스케이프 문자)를 해석하지 않고 그대로 텍스트로 처리</p>
<pre><code class="language-python">normal_string = &quot;This is a normal string.\nThis is a new line.&quot;
print(normal_string)
# 출력:
# This is a normal string.
# This is a new line.
raw_string = r&quot;This is a raw string.\nThis is not a new line.&quot;
print(raw_string)
# 출력:
# This is a raw string.\nThis is not a new line.</code></pre>
<h3 id="3-function-type-hints">3) function type hints</h3>
<p><a name="functiontypehints"></a>
함수의 매개변수와 반환 값에 대한 타입 정보를 제공하는 기능이다. Docstring으로 함수에 대한 설명, 변수 설명등을 적어 다른 개발자가 함수를 이해할 수 있도록 하는 것이 좋다. </p>
<pre><code class="language-python">def add_numbers(x: int, y: int) -&gt; int:
    &quot;&quot;&quot;
    두 정수를 더하는 함수
    Parameters:
    - x (int): 첫 번째 정수
    - y (int): 두 번째 정수
    Returns:
    int: 두 정수의 합
    &quot;&quot;&quot;
    return x + y
# 사용 예시
result = add_numbers(5, 10)
print(result)  # 출력: 15
# 타입 오류 발생 예시
# result = add_numbers(&quot;5&quot;, &quot;10&quot;)  # 문자열을 전달하면 타입 오류 발생</code></pre>
<h2 id="5-pythonic-code">5. Pythonic Code</h2>
<blockquote>
</blockquote>
<h3 id="1-join">1. join</h3>
<p>문자열을 &#39;+&#39;를 통해서 결합하는 경우 새로운 객체가 매번 생성되기 때문에 메모리를 많이 차지하게 된다. &#39;join&#39; method를 사용하는 경우 보다 효율적인 처리가 가능해짐</p>
<pre><code class="language-python"># Using join
result = &#39;&#39;.join(str(i) for i in range(10000))</code></pre>
<h3 id="2-list-comprehension">2. list comprehension</h3>
<p>보다 간결하게 list를 만들어내는 기법. 미세하게 속도가 빠름!</p>
<pre><code class="language-python">result = [x if x % 2 == 0 else x**2 for x in range(10)]</code></pre>
<h3 id="3-enumerate">3. enumerate</h3>
<p>iterable 객체를 입력받아 인덱스와 값을 포함하는 enumerate객체를 returen 해준다.</p>
<pre><code class="language-python">fruits = [&#39;apple&#39;, &#39;banana&#39;, &#39;cherry&#39;]
for index, value in enumerate(fruits):
    print(f&quot;Index: {index}, Value: {value}&quot;)
#Index: 0, Value: apple
#Index: 1, Value: banana
#Index: 2, Value: cherry</code></pre>
<h3 id="4-zip">4. zip</h3>
<p>두개 이상의 iterable을 묶어주는 역할</p>
<h3 id="5-map">5. map</h3>
<p>주어진 함수를 지정된 iterable의 모든 요소에 적용하여 새로운 map 객체를 생성한다. (iterator란 iterable에서 값을 하나씩 가져오는 객체로, map을 사용해서 객체를 생성하는경우 사용시점에 값을 생성하기 때문에 메모리 효율적이다)</p>
<h3 id="6-generator">6. generator</h3>
<p>yield 키워드를 활용하여 메모리에 저장하지 않는 특별한 종류의 iterator를 생성.
yield를 사용하여 값을 생성하고, 일시 중단.</p>
<pre><code class="language-python">def even_numbers_generator(limit):
    number = 0
    while number &lt; limit:
        yield number
        number += 2
# 제너레이터 객체 생성
even_gen = even_numbers_generator(10)
# 제너레이터를 사용하여 값 순회
for num in even_gen:
    print(num)</code></pre>
<p>데이터가 커져도 다룰수 있다는 장점을 가지고 있음 </p>
<h3 id="7-keyword-arguments">7. keyword arguments</h3>
<p>함수 호출 시 인자를 전달할 때, 각 인자의 이름을 명시적으로 지정하여 값을 전달하는 방식</p>
<h3 id="8-asterisk">8. asterisk</h3>
<p>단순 곱셈, 제곱 연산, 가변인자 활용, unpacking 까지 다양하게 사용</p>
<ul>
<li>unpacking : iterable(순회 가능한) 객체에서 요소를 개별 변수로 추출<pre><code class="language-python">def add_numbers(a, b, c):
  return a + b + c
numbers = [1, 2, 3]
# Unpacking 함수 인자
result = add_numbers(*numbers)
print(&quot;Result:&quot;, result)</code></pre>
</li>
</ul>
<h2 id="6oop">6.OOP</h2>
<blockquote>
<ul>
<li>OOP는 클래스와 실제 구현인 Instance로 구성된다. </li>
</ul>
</blockquote>
<ul>
<li>Inheritance : 클래스 간에 코드를 재사용하는 메커니즘을 제공</li>
<li>Polymorphism : 동일한 인터페이스를 사용하여 여러 객체 타입을 처리할 수 있는 능력으로 주로 메서드 오버라이딩과 관련
<img src="https://velog.velcdn.com/images/taemin-steve/post/fe3593bc-4bf8-4442-8900-836865a68b96/image.png" alt=""></li>
<li>Visibility : 객체의 속성이나 메서드에 대한 접근 권한을 제어하는 것<ul>
<li>public: 어떠한 제한도 없음.</li>
<li>_protected: 클래스 자체 및 해당 클래스를 상속받은 클래스에서 접근 가능.</li>
<li>__private: 해당 클래스에서만 접근 가능.</li>
</ul>
</li>
<li>Decorate : 함수를 받아 일부 작업을 수행한 후 해당 함수를 반환하는 함수<pre><code class="language-python">def trace(func):                             # 호출할 함수를 매개변수로 받음
  def wrapper():
      print(func.__name__, &#39;함수 시작&#39;)    # __name__으로 함수 이름 출력
      func()                               # 매개변수로 받은 함수를 호출
      print(func.__name__, &#39;함수 끝&#39;)
  return wrapper                           # wrapper 함수 반환
@trace    # @데코레이터
def hello():
  print(&#39;hello&#39;)
@trace    # @데코레이터
def world():
  print(&#39;world&#39;)
hello()    # 함수를 그대로 호출
world()    # 함수를 그대로 호출</code></pre>
</li>
</ul>
<h2 id="7정규식">7.정규식</h2>
<blockquote>
<p>문자열의 검색, 매칭, 교체 등의 작업을 수행하는데 사용되는 강력한 도구</p>
</blockquote>
<ul>
<li>문자 클래스 ([ ]): 괄호 안에 들어가는 문자 중 하나와 매치.</li>
<li>마침표(.): 어떤 한 문자와 매치됩니다. 단, 새 줄 문자(\n)는 제외됩니다.</li>
<li>반복 (*, +, ?):<ul>
<li>*: 0번 이상 반복</li>
<li>+: 1번 이상 반복</li>
<li>?: 0번 또는 1번 반복</li>
</ul>
</li>
<li>메타문자(^, $):<ul>
<li>^: 문자열의 시작과 매치</li>
<li>$: 문자열의 끝과 매치</li>
</ul>
</li>
</ul>
<h2 id="8-json">8. JSON</h2>
<h2 id="9-pandas">9. Pandas</h2>
<h2 id="10-numpy">10. Numpy</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[Geometry - Solution Set]]></title>
            <link>https://velog.io/@taemin-steve/Geometry-Solution-Set</link>
            <guid>https://velog.io/@taemin-steve/Geometry-Solution-Set</guid>
            <pubDate>Tue, 07 Nov 2023 10:18:31 GMT</pubDate>
            <description><![CDATA[<h2 id="homogeneous-system">Homogeneous System</h2>
<hr>
<blockquote>
<p>$Ax = 0$ 의 형태를 가진 선형방정식</p>
</blockquote>
<ul>
<li>Homogeneous System은 자유변수가 존재하면 Non Trivial Solution을 갖는다 == (자유변수가 존재한다 == Pivot 컬럼이 아닌 컬럼이 존재한다.)</li>
</ul>
<h2 id="parametric-vector-form">Parametric Vector Form</h2>
<hr>
<p>아래와 같은 형태를 Parametric Vector Form이라고 한다. </p>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/eeb4973c-fe24-4089-a9bb-1213148791de/image.png" alt=""></p>
<h2 id="solution-set">Solution Set</h2>
<hr>
<blockquote>
<p>$Ax = 0$를 만족하는 모든 x의 집합</p>
</blockquote>
<ul>
<li>결국 Solution Set은 특정 값 b를 찾기 위한 기저백터들의 계수 집합이라고 생각하면 편하다.</li>
<li>Tall Matrix(M &gt; N) 라고 하더라도 Pivot컬럼이 아닌 컬럼이 존재하면 무한해를 가지게 됨</li>
<li>$R^n$</li>
</ul>
<h2 id="column-span">Column Span</h2>
<hr>
<blockquote>
<p>$Ax = b$ 에서 가능한 모든 b의 집합</p>
</blockquote>
<ul>
<li>$R^m$</li>
</ul>
<h2 id="inhomogeneous-system">Inhomogeneous System</h2>
<hr>
<blockquote>
<p>$Ax = b$ 의 형태를 가진 선형방정식</p>
</blockquote>
<ul>
<li>기존의 Homogeneous System의 Solution Set에서 b 만큼 평행이동한 Span 영역이 해가 된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Geometry - Matrix Equation]]></title>
            <link>https://velog.io/@taemin-steve/Geometry-Matrix-Equation</link>
            <guid>https://velog.io/@taemin-steve/Geometry-Matrix-Equation</guid>
            <pubDate>Fri, 20 Oct 2023 08:09:39 GMT</pubDate>
            <description><![CDATA[<h2 id="matrix-x-vector">Matrix x Vector</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/e294175c-360b-4685-bd93-886ee4c19cb1/image.png" alt=""></p>
<p>반드시 Matrix의 <strong>열</strong>의 수와 Vector의 <strong>행</strong>의 수가 일치해야 곱할 수 있음 </p>
<h2 id="matrix-equation">Matrix Equation</h2>
<hr>
<p>$x_{1}v_{1} + x_{2}v_{2} + ... + x_{p}v_{p} = b$ 해당 식을 $Ax = b$와 같이 표현할 수 있고 이를 Matrix Equation이라고 한다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/d49e7d42-b9f4-4ed7-ae45-aade9957ed6d/image.png" alt=""></p>
<p>지금까지 배운것을 정리해보면 우리는 아래와 같이 동일한 식을 표현할 수 있고, 이때의 해는 모두 동일하다. </p>
<ol>
<li>System of Equation</li>
<li>Augmented Equation</li>
<li>Vector Equation</li>
<li>Matrix Equation </li>
</ol>
<h2 id="행백터로의-표현">행백터로의 표현</h2>
<hr>
<p>동일한 식을 다음과 같이 두가지 관점에서 바라볼 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/e09927c1-a949-423a-8388-8279b84471a1/image.png" alt=""></p>
<h2 id="spans-and-solution-of-equations">Spans and Solution of Equations</h2>
<hr>
<blockquote>
<p>$Ax = b$가 해를 가지고 있다 &gt;&gt; b는 A를 구성하는 columns에 의해 Span된다.</p>
</blockquote>
<p><a href="https://textbooks.math.gatech.edu/ila/demos/spans.html?v1=2,-1,1&amp;v2=1,0,-1&amp;target=0,2,2&amp;tlabel=b&amp;range=5">예시 링크</a></p>
<h2 id="when-solutions-always-exist">When Solutions Always Exist</h2>
<hr>
<p>Non-Augmented $m$ x $n$ Matrix $A$에 대하여 아래의 조건을 만족하면 항상 해가 존재한다. </p>
<blockquote>
<ol>
<li>$Ax = b$가 $R^m$에 존재하는 모든 b에 대해 해가 존재할 때 </li>
<li>$A$의 Span이 $R^m$인 경우 </li>
<li>모든 행에 pivot이 존재하는 경우 </li>
</ol>
</blockquote>
<p>3번식의 경우, A를 Augmented 시키더라도 마지막 행이 Pivot column이 될 수 없기 때문에 만족한다. </p>
<h2 id="properties-of-the-matrix---vector-product">Properties of the Matrix - Vector Product</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/2ed8af0b-a978-4773-8ff4-022087b51e3c/image.png" alt=""></p>
<p>선형성에 의거하여, $Ax=0$를 만족하는 벡터 {$u$,$v$}를 구한경우 $Ax = 0$의 solution set은 반드시 Span이다.   </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Geometry - Vector Equations and Spans]]></title>
            <link>https://velog.io/@taemin-steve/Geometry-Vector-Equations-and-Spans</link>
            <guid>https://velog.io/@taemin-steve/Geometry-Vector-Equations-and-Spans</guid>
            <pubDate>Fri, 20 Oct 2023 03:12:30 GMT</pubDate>
            <description><![CDATA[<h2 id="vector-equation의-augmented-matrices로의-표현">Vector Equation의 Augmented matrices로의 표현</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/f701e632-54c5-42f0-8391-aa29ed30b4c9/image.png" alt=""></p>
<p>우리는 위의 $x_{1}v_{1} + x_{2}v_{2} + ... + x_{p}v_{p}$ (Linear combinations of vectors == vector equations)를 아래의 Augmented matrices로 표현하는 것도 가능하다. </p>
<p><a href="https://textbooks.math.gatech.edu/ila/demos/spans.html?v1=1,2,6&amp;v2=-1,-2,-1&amp;target=8,16,3&amp;tlabel=b&amp;range=20&amp;camera=3,.5,1.5">예시</a>  : 2개의 3차원 백터의 올바른 계수를 찾는 과정</p>
<h2 id="span">Span</h2>
<hr>
<p>Span은 $x_{1}v_{1} + x_{2}v_{2} + ... + x_{p}v_{p} = b$ 에서 임의의 $x_{1},x_{2},...x_{p}$ 로 생성할 수 있는 모든 $b$의 집합을 의미한다. </p>
<p>이를 수식으로 표현하면 다음과 같다 </p>
<blockquote>
<p>$Span{v_{1},v_{2},...v_{p}} = {x_{1}v_{1} + x_{2}v_{2} + ... + x_{p}v_{p};|;x_{1},x_{2},...x_{p} ; in ; R }$</p>
</blockquote>
<p>이를 다르게 표현하면 $Span{v_{1},v_{2},...v_{p}}$ 이 $x_{1},x_{2},...x_{p}$ 에 의해서 Spanned by 혹은 generated by 라고 표현할수 있다.  </p>
<p>따라서 vector $b$가 $x_{1}v_{1} + x_{2}v_{2} + ... + x_{p}v_{p}$ 의 Span에 포함된다면, 해당 벡터 방정식은 해가 존재한다. </p>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/513a4731-2896-4be7-9c69-3d6b1f79051c/image.png" alt=""></p>
<p>위 그림의 1,2,3 번은 모두 동치이다.(하나 틀리면 다 틀리고 하나 맞으면 다 맞음)</p>
<p>※ 편하게 생각하면 Span이란 선형결합으로 표현 가능한 모든 백터의 값들이다. </p>
<h2 id="summary">Summary</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/423d8991-ac9b-435f-bb1f-c83bf398c055/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Geometry - Vectors]]></title>
            <link>https://velog.io/@taemin-steve/Geometry-Vectors</link>
            <guid>https://velog.io/@taemin-steve/Geometry-Vectors</guid>
            <pubDate>Fri, 20 Oct 2023 02:39:48 GMT</pubDate>
            <description><![CDATA[<h2 id="vector">Vector</h2>
<hr>
<blockquote>
<p>Vector : Element of $R^N$, drawn as an arrow </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/53cf3289-8e3f-4ed7-b7e2-ee09355ea14d/image.png" alt=""></p>
<p>우리는 백터끼리 더하고, scalr배 해줄수 있다. </p>
<h2 id="linear-combinations">Linear Combinations</h2>
<hr>
<p>$$ W = c_{1}v_{1} + c_{2}v_{2} + ... + c_{p}v_{p}
$$</p>
<blockquote>
<p>$W$ = Linear combintation of vectors $v_{1}$, $v_{2}$ ... $v_{p}$.</p>
</blockquote>
<p>이때 $c_{1}$, $c_{2}$ ... $c_{p}$는 weight 혹은 coefficients(계수) 라고 한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Parametric Form ]]></title>
            <link>https://velog.io/@taemin-steve/Parametric-Form</link>
            <guid>https://velog.io/@taemin-steve/Parametric-Form</guid>
            <pubDate>Fri, 20 Oct 2023 02:15:15 GMT</pubDate>
            <description><![CDATA[<h2 id="free-variable">Free variable</h2>
<hr>
<p>RREF 형태의 Consistent한 Matrix A에 대해 pivot cloumn이 아닌 column에 대응하는 변수를 자유변수라고 한다. </p>
<blockquote>
<ol>
<li>You can choose any value for the free variables in a (consistent) linear system.</li>
<li>Free variable come from column without pivots in a matrix in row echelon form </li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/be28f6ea-efa8-40c6-8958-7079b543604b/image.png" alt=""></p>
<p>아래와 같은 형태로 나타내는 것을 parametric form(일반해의 매개화된 형태)라고 한다. </p>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/2a56509b-860b-45fa-8bbc-65df16befb38/image.png" alt=""></p>
<h2 id="rref의-세가지-가능성">RREF의 세가지 가능성</h2>
<hr>
<h3 id="1-the-last-column-is-a-pivot-column">1. The last column is a pivot column</h3>
<p>해가 없다 
<img src="https://velog.velcdn.com/images/taemin-steve/post/321539ab-de75-4a51-aaa2-711c7c77336b/image.png" alt=""></p>
<h3 id="2-every-column-except-the-last-column-is-a-pivot-column">2. Every column except the last column is a pivot column</h3>
<p>유일해를 가지게 됨
<img src="https://velog.velcdn.com/images/taemin-steve/post/798819b9-76ee-4cd3-af1d-29b1ef326474/image.png" alt=""></p>
<h3 id="3-the-last-column-is-not-a-pivot-column-and-some-other-column-isnt-either">3. The last column is not a pivot column, and some other column isn&#39;t either</h3>
<p>무수히 많은 해를 가지게 되며, 자유변수를 가진다. 
<img src="https://velog.velcdn.com/images/taemin-steve/post/30d3a90f-3682-4a7e-b991-99472cb80277/image.png" alt=""></p>
<h2 id="summary">Summary</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/taemin-steve/post/c75d9003-0acb-405b-ac2a-a69f97754541/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>