<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>lostfind</title>
    <description></description>
    <link>http://lostfind.github.io/</link>
    <atom:link href="http://lostfind.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 17 Aug 2021 13:45:29 +0000</pubDate>
    <lastBuildDate>Tue, 17 Aug 2021 13:45:29 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>Go 언어의 인터페이스</title>
        <description>&lt;p&gt;Go에서의 인터페이스는 메서드의 집합체로, 인터페이스를 만족하기 위해서는 위해서는 인터페이스가 갖고있는 모든 메소드를 구현 하기만 하면 된다.&lt;/p&gt;

&lt;p&gt;단, Java의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implements&lt;/code&gt;와 같은 표기는 하지 않기 때문에 어떤 인터페이스를 구현 한건지 코드만 봤을땐 파악하기 힘들다는 단점이 있다.&lt;/p&gt;

&lt;h2 id=&quot;예제&quot;&gt;예제&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pet&lt;/code&gt;이라는 구조체가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animal&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; 두개의 인터페이스를 구현하는 예제이다.&lt;/p&gt;

&lt;h3 id=&quot;인터페이스-정의&quot;&gt;인터페이스 정의&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-go:lostfind/playground/zoo/animal.go&quot;&gt;package zoo

type Animal interface {
	Walk()
}

type Cat interface {
	Cry()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;인터페이스-구현&quot;&gt;인터페이스 구현&lt;/h3&gt;
&lt;p&gt;두 인터페이스가 정의 되어있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zoo&lt;/code&gt;패키지를 import한 후, 각 메소드를 구현 한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-go:main.go&quot;&gt;package main

import (
	&quot;fmt&quot;
	&quot;lostfind/playground/zoo&quot;
)

type Pet struct {
	name string
	age  int
}

// Cat의 인터페이스 구현
func (p *Pet) Cry() {
	fmt.Println(&quot;Nya&quot;)
}

// Animal 인터페이스의 구현
func (p *Pet) Walk() {
	fmt.Println(&quot;I walk with four feet.&quot;)
}

func main() {
	// 인터페이스 변수
	var animal zoo.Animal
	var cat zoo.Cat

	myPet := &amp;amp;Pet{
		name: &quot;Nyanko&quot;,
		age:  10,
	}

	// myPet은 Cat, Animal의 인터페이스를 구현 하였으므로 각 인터페이스 변수에 대입 가능
	cat = myPet
	animal = myPet

	cat.Cry() // Nya
	animal.Walk() // I walk with four feet.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;java에서의-표현&quot;&gt;Java에서의 표현&lt;/h3&gt;
&lt;p&gt;단순히 이해를 돕기위한 코드로 Java를 코딩 안한지 꽤 오랜 시간이 지나서 문법이 정확하지 않을 수 있다.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Walk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Walk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;I walk with four feet.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Nya&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 14 Jul 2019 18:28:00 +0000</pubDate>
        <link>http://lostfind.github.io/development/2019/07/14/go-interface.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/development/2019/07/14/go-interface.html</guid>
        
        <category>Go</category>
        
        <category>Interface</category>
        
        
        <category>Development</category>
        
      </item>
    
      <item>
        <title>Go 언어의 메소드와 함수</title>
        <description>&lt;h2 id=&quot;함수&quot;&gt;함수&lt;/h2&gt;
&lt;p&gt;함수는 단순히 파라미터 리턴값을 갖는다.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Meow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;function: my name is %s. MEOW~&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;메소드&quot;&gt;메소드&lt;/h2&gt;
&lt;p&gt;메소드는 함수와 거의 동일하지만, 구조체에 붙여서 사용하며 구조체 이외에도
기본타입 이외의 어떠한 타입에든 붙여서 사용할 수 있다.
특정 구조체에 붙여 사용하기 위해서 메소드명 앞의 리시버에 구조체(혹은 타입명)를 명시한다.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;// Cat 구조체의 메소드 Meow&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Meow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my name is %s. MEOW~&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;// neco *Cat&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;neco&quot;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;

	&lt;span class=&quot;c&quot;&gt;// nabi Cat&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;nabi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Meow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// my name is neco. MEOW~&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Meow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// my name is nabi. MEOW~&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;포인터-리시버&quot;&gt;포인터 리시버&lt;/h3&gt;
&lt;p&gt;Go 언어는 일반적으로는 값을 전달하기 때문에 메모리상에서 변수가 복제되어 전달되지만
리시버를 포인터 리시버로 정의하면 불필요한 복제를 방지하며, Call by reference와 같이 동작한다.&lt;/p&gt;

&lt;p&gt;아래의 코드와 같이 포인터 리시버를 사용한 메소드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt;구조체의 필드 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;age&lt;/code&gt;의 값을 직접 수정한다.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;// Cat 구조체의 메소드 AddAge (포인터 리시버)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AddAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 구조체의 필드를 직접 수정&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;// neco *Cat&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;neco&quot;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;

	&lt;span class=&quot;c&quot;&gt;// nabi Cat&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;nabi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 0&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 1&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 1&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 2&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그렇다면, 포인터 리시버 메소드의 경우에는 구조체를 포인터형으로 생성해야 하는가?
위 코드의 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;neco&lt;/code&gt;는 Go의 내장함수&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new()&lt;/code&gt;을 통해 생성했기 때문에 포인터형(*Cat)으로 생성되어 있고
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nabi&lt;/code&gt;는 직접 생성했기 때문에 포인터가 아닌 객체(Cat)로 생성되었다.&lt;/p&gt;

&lt;p&gt;하지만, 동일한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddAge()&lt;/code&gt;메소드를 호출하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;neco&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nabi&lt;/code&gt; 둘 다 직접 값이 수정되어 있다.
이는, 컴파일러가 암묵적으로 변환해 주기 때문에 가능한 것이다. &lt;a href=&quot;https://golang.org/ref/spec#Calls&quot;&gt;Go매뉴얼 Calls&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;명시적으로 포인터형의 메소드를 호출하는 것도 가능하며, 결과는 동일하다.&lt;/p&gt;
&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 0&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 1&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// nabi.AddAge()와 동일&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 1&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nabi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;함수-vs-메소드&quot;&gt;함수 vs 메소드&lt;/h2&gt;
&lt;p&gt;함수의 경우에는 프로그램 전체적으로 파라미터에 대해 일정한 처리를 하는 경우에 사용하고,
메소드는 객체별 기능을 구현할 때 사용하는 것이 좋다고 생각한다.&lt;/p&gt;

&lt;p&gt;비슷한 기능이라도 구조체별로 다른 동작을 하는 경우에 메소드로 한다면
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hogeSave()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fugeSave()&lt;/code&gt;이 아니라 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;객체명.Save()&lt;/code&gt;와 같이 이름을 짓기도 편하며
수정이 발생하는 경우에 어디까지 영향이 미치는지 범위를 파악하기도 쉬워진다.&lt;/p&gt;

&lt;p&gt;특별한 경우가 아니라면 기본적으로 메소드로 구현하는 것이 나을 듯하다.&lt;/p&gt;
</description>
        <pubDate>Sun, 30 Jun 2019 11:28:00 +0000</pubDate>
        <link>http://lostfind.github.io/development/2019/06/30/golang-method.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/development/2019/06/30/golang-method.html</guid>
        
        <category>Go</category>
        
        <category>Method</category>
        
        
        <category>Development</category>
        
      </item>
    
      <item>
        <title>가계부 자산관리 모델</title>
        <description>&lt;p&gt;‘자산관리’의 모델 부분 개발의 현재까지 진행상황 정리&lt;/p&gt;

&lt;h2 id=&quot;개발-과정&quot;&gt;개발 과정&lt;/h2&gt;
&lt;h3 id=&quot;일단-스파게티-코드&quot;&gt;일단 스파게티 코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-PHP&quot;&gt;class Account
{
  // 데이터 항목
  public $id = '';
  public $accountName = '';
  public $balance = 0;
  public $sort = 0;
  public $accountType = '';
  public $accountTypeName = '';

  function getAll()
  {
    $mysqli = new mysqli('localhost', 'dwkim', 'dwkim', 'accountbook');
    if (mysqli_connect_errno()) {
      printf(&quot;Connect failed: %s\n&quot;, mysqli_connect_error());
      exit;
    }

    $query = &quot;쿼리생략&quot;;
    $result = mysqli_query($mysqli, $query);
    $mysqli-&amp;gt;close();

    return $result;
  }

  function getAccount($id)
  {
    // ...생략
    if ($result) {
      $this-&amp;gt;id = $result-&amp;gt;id;
      // ...생략
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;현재-코드의-문제점&quot;&gt;현재 코드의 문제점&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;DB커넥션이 각 메소드에서 반복되며 되고 관리가 불편함&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysqli&lt;/code&gt;를 사용함으로 특정 DB에 의존&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;해결방안&quot;&gt;해결방안&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;DB커넥션을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model&lt;/code&gt;클래스에 구현하고 각 모델에서 상속&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.php.net/manual/en/class.pdo.php&quot;&gt;PDO&lt;/a&gt;로 DB의존해소&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;db연결-부분-분리&quot;&gt;DB연결 부분 분리&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-PHP&quot;&gt;class Model
{
  public $db;

  function __construct() {
    $dbServer = 'localhost';
    $dbUser = 'dwkim';
    $dbPass = 'dwkim';
    $dbName = 'accountbook';

    $dsn = &quot;mysql:host={$dbServer};dbname={$dbName};charset=utf8&quot;;

    try {
      $this-&amp;gt;db = new PDO($dsn, $dbUser, $dbPass);
    } catch (PDOException $e) {
      echo '접속실패' . h($e-&amp;gt;getMessage());
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-PHP&quot;&gt;class Account extends Model
{
  // ...생략
  function getAll()
  {
    $sql = &quot;쿼리생략&quot;;
    $prepare = $this-&amp;gt;db-&amp;gt;prepare($sql);
    $prepare-&amp;gt;execute();
    $result = $prepare-&amp;gt;fetchAll(PDO::FETCH_ASSOC);

    return $result;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;현재-코드의-문제점-1&quot;&gt;현재 코드의 문제점&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;전체 레코드를 조회하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAll()&lt;/code&gt;메소드는 데이터 항목 변수를 사용하지 못함&lt;/li&gt;
  &lt;li&gt;한 레코드 조회용 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAccount()&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getALL()&lt;/code&gt;이 반환하는 형식이 달라 컨트롤러에서 각각 대응이 필요&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;해결방안-1&quot;&gt;해결방안&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;데이터 객체를 별로도 작성하여 컨트롤러와는 데이터 객체를 통해 데이터를 주고 받는다&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;데이터-객체-생성&quot;&gt;데이터 객체 생성&lt;/h3&gt;
&lt;p&gt;테이블 구조와 거의 동일한 데이터 클래스 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AccountData&lt;/code&gt; 작성&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-PHP&quot;&gt;class AccountData
{
  public $id = '';
  public $accountName = '';
  public $balance = 0;
  public $sort = 0;
  public $accountType = '';
  public $accountTypeName = '';

  function __construct($data = array())
  {
    foreach ($data as $key =&amp;gt; $value) {
      switch ($key) {
        case 'id':
          $this-&amp;gt;id = $data[$key];
          break;
        case 'account_name':
        case 'accountName':
          $this-&amp;gt;accountName = $data[$key];
          break;
        case 'balance':
          $this-&amp;gt;balance = $data[$key];
          break;
        case 'sort':
          $this-&amp;gt;sort = $data[$key];
          break;
        case 'account_type':
        case 'accountType':
          $this-&amp;gt;accountType = $data[$key];
          break;
        case 'account_type_nm':
        case 'accountTypeName':
          $this-&amp;gt;accountTypeName = $data[$key];
          break;
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-PHP&quot;&gt;class Account extends Model
{
  // ...생략
  function getAll()
  {
    $sql = &quot;쿼리생략&quot;;
    $prepare = $this-&amp;gt;db-&amp;gt;prepare($sql);
    $prepare-&amp;gt;execute();
    $result = $prepare-&amp;gt;fetchAll(PDO::FETCH_ASSOC);

    $accounts = array();

    foreach ($result as $row) {
      $account = new AccountData($row);
      $accounts[] = $account;
    }

    return $accounts;
  }

  function getAccount($id)
  {
    $sql = &quot;쿼리생략&quot;;
    $prepare = $this-&amp;gt;db-&amp;gt;prepare($sql);
    $prepare-&amp;gt;bindValue(':id', $id, PDO::PARAM_INT);
    $prepare-&amp;gt;execute();
    $result = $prepare-&amp;gt;fetch(PDO::FETCH_ASSOC|PDO::FETCH_UNIQUE);

    $account = new AccountData($result);

    return $account;
  }
  // ...생략
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;남은-과제&quot;&gt;남은 과제&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;DB커넥션에 대한 정보가 Model에서 Config로 옮기기
    &lt;ul&gt;
      &lt;li&gt;(Model에 있는 것보다 Config에서 관리하는게 타당할 경우)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터객체의 get, set기능
    &lt;ul&gt;
      &lt;li&gt;DB의 스네이크 표기법과 컨트롤러, 뷰의 카멜 표기법 자동 매칭
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;account_name&lt;/code&gt; ↔ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accountName&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 03 May 2019 15:20:00 +0000</pubDate>
        <link>http://lostfind.github.io/development/2019/05/03/account-Model.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/development/2019/05/03/account-Model.html</guid>
        
        <category>PHP</category>
        
        <category>가계부</category>
        
        
        <category>Development</category>
        
      </item>
    
      <item>
        <title>개인용 가계부 시스템 개발</title>
        <description>&lt;p&gt;아이폰으로 넘어온 후로 지금껏 안드로이드에서 사용중이던 가계부 어플을 계속해서 사용할 수 없게 되었다.&lt;/p&gt;

&lt;p&gt;웹, 어플과도 연동 되는 Moneytree등 좋은 서비스들이 많이 있지만,
몇년간 사용하며 쌓아온 데이터를 버리기도 아깝고, 카테고리 관리등 내가 원하는 방식과는 좀 달랐기 때문에 지속적인 사용으로 연결되지 않는 문제가 있었다.&lt;/p&gt;

&lt;p&gt;그런 이유로 내가 사용 할 가계부 시스템을 만들기로 했으며, 진행과정과 시행착오, 변경점 등을 기록해 나가고자 한다.&lt;/p&gt;

&lt;h2 id=&quot;구현할-기능&quot;&gt;구현할 기능&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;카테고리
    &lt;ul&gt;
      &lt;li&gt;상위, 하위 카테고리 기능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자산관리
    &lt;ul&gt;
      &lt;li&gt;현금 / 통장 / 전자머니&lt;/li&gt;
      &lt;li&gt;은행, 전자머니 회사에서 제공하는 API로 내역 동기화&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;예산관리
    &lt;ul&gt;
      &lt;li&gt;카테고리별 고정지출&lt;/li&gt;
      &lt;li&gt;카테고리별 고정수입&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;신용카드 관리
    &lt;ul&gt;
      &lt;li&gt;사용기간 / 결제일&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데빗카드 관리
    &lt;ul&gt;
      &lt;li&gt;연결 계좌 설정&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이력, 통계&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;주식매매 기록&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;부가기능 (혹은 필수적인)
    &lt;ul&gt;
      &lt;li&gt;보안을 위한 최소한의 기능&lt;/li&gt;
      &lt;li&gt;로그인 기능 (유저별)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;개발환경&quot;&gt;개발환경&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;PHP 7.3.4&lt;/li&gt;
  &lt;li&gt;mysql 8.0.15&lt;/li&gt;
  &lt;li&gt;Apache/2.4.34&lt;/li&gt;
  &lt;li&gt;MVC라우터 https://github.com/pokeb/php-mvc-router&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;mvc라우터에-대해&quot;&gt;MVC라우터에 대해&lt;/h3&gt;
&lt;p&gt;프레임워크 없이 모든 기능을 구현 하려 했으나, 라우터 기능을 레일즈처럼 간단하게 사용하기 위해 직접 구현하려고 하니 가계부 시스템 개발과는 다른 방향으로 공부가 필요 한 것 같아서 github에서 가벼운 MVC 라우터를 찾아서 사용하게 되었다.&lt;/p&gt;

&lt;h2 id=&quot;설계&quot;&gt;설계&lt;/h2&gt;
&lt;h3 id=&quot;데이터-설계&quot;&gt;데이터 설계&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/accountbook_datamodel.png&quot; title=&quot;Accountbook Data Model&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m_code&lt;/code&gt;- 각종 타입, 구분등을 공통으로 관리&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m_account&lt;/code&gt; - 자산 구분과 잔액 관리&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m_category&lt;/code&gt; - 수입, 지출에 대한 카테고리&lt;/li&gt;
  &lt;li&gt;수정 / 추가가 필요한 부분
    &lt;ul&gt;
      &lt;li&gt;신용카드 사용기간, 결제일&lt;/li&gt;
      &lt;li&gt;예산관리&lt;/li&gt;
      &lt;li&gt;주식매매 관련&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;라우트&quot;&gt;라우트&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-PHP&quot;&gt;$GLOBALS['routes'] = array(
  '/' =&amp;gt; '/DepositHistory',
  '/deposits' =&amp;gt; 'DepositHistory',
  '/deposits/detail/(deposit)' =&amp;gt; 'DepositHistory:action',
  '/deposits/income' =&amp;gt; 'DepositHistory:income',
  '/deposits/outgo' =&amp;gt; 'DepositHistory:income',
  '/categories' =&amp;gt; 'Category',
  '/categories/:kind' =&amp;gt; 'Category:index',
  '/categories/detail/(category)' =&amp;gt; 'Category:action',
  '/accounts' =&amp;gt; 'Account',
  '/accounts/new' =&amp;gt; 'Account:new',
  '/accounts/:id' =&amp;gt; 'Account:detail',
);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;디렉토리-구조&quot;&gt;디렉토리 구조&lt;/h3&gt;
&lt;p&gt;MVC라우터 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php-mvc-router&lt;/code&gt;가 제공하는 기본적인 디렉토리 구조를 따른다.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;accountbbok/
├ common/autoload.php
├ config/
│　├ config.php
│　└ routes.php
├ helpers/
│　├ Router.php
│　└ utility.php
├ htdocs/
│　├ .htaccess
│　├ 404.php
│　└ index.php
├ controllers/
│　└ 컨트롤러 클래스
├ models/
│　└ 모델 관련 클래스
├ views/
│　├ accounts/
│　└ categories/
│　└ deposits/
└ bootstrap.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;화면-설계&quot;&gt;화면 설계&lt;/h3&gt;
&lt;p&gt;간단한 HTML을 이용하여 형편없는 디자인으로 일단 구현 할 예정이다.&lt;/p&gt;

&lt;p&gt;MVC모델로 잘 구현이 되었다면 뷰에 관련된 변경은 최종적으로 진행 하여도 설계, 내부 코드 수정은 없어야 한다고 믿고 있으며, 그렇게 진행 하고자 한다.&lt;/p&gt;

&lt;h2 id=&quot;정리&quot;&gt;정리&lt;/h2&gt;
&lt;p&gt;개발에 착수 한지는 3개월가량 지났지만 프레임워크를 사용할지 말지에 대한 고민과 php-MVC라우터에 대한 이해 없이 내역(deposits), 카테고리(categories)의 컨트롤러와 모델을 개발 하며 같은 곳을 여러번 수정하는 바람에 아무런 진척이 없는 상태에서, 클린아키텍처 설계까지 도입 하고 싶은 욕심이 강해 더더욱 진행이 되지 않는 상태였다.&lt;/p&gt;

&lt;p&gt;소스가 지저분하게 되더라도 일단 구현을 하며 문제점을 파악 한 후 리팩토링으로 클린 아키택쳐가 되도록 진행하고자는 결론에 도달했다.&lt;/p&gt;

&lt;h3 id=&quot;전체적인-계획&quot;&gt;전체적인 계획&lt;/h3&gt;
&lt;p&gt;PHP로 기능 구현 → Vue.js로 프론트 구현 → 백엔드 Go언어로 마이그레이션&lt;/p&gt;
</description>
        <pubDate>Wed, 01 May 2019 18:17:00 +0000</pubDate>
        <link>http://lostfind.github.io/development/2019/05/01/%EA%B0%80%EA%B3%84%EB%B6%80%EA%B0%9C%EB%B0%9C.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/development/2019/05/01/%EA%B0%80%EA%B3%84%EB%B6%80%EA%B0%9C%EB%B0%9C.html</guid>
        
        <category>PHP</category>
        
        <category>가계부</category>
        
        
        <category>Development</category>
        
      </item>
    
      <item>
        <title>소프트웨어 설계 원칙 : SOLID</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/4048930656/ref=cm_sw_em_r_mt_dp_U_PfzQCbF5KA7KC&quot;&gt;Clean Architecture&lt;/a&gt;를 읽고 있는 중, SOLID 원칙에 대해 일단 간단하게 정리 해 두려고 한다.&lt;/p&gt;

&lt;p&gt;SOLID 원칙이란, 로버트 마틴(엉클밥)이 객체지향 설계에서 지켜야 할 5가지 기본 원칙이다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;변경에 강하고&lt;/li&gt;
  &lt;li&gt;이해하기 쉬우며&lt;/li&gt;
  &lt;li&gt;컴포넌트 기반으로서, 많은 소프웨어 시스템에서 사용 되는 것&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;위 세가지의 성질을 가진 중간레벨 소프트웨어를 만드는 것이 목적이다.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;예제를 포함해 상세한 부분은 각 원칙별 별도 포스트로 정리할 예정이다.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;단일-책임-원칙-single-responsibility-principle의-정의&quot;&gt;단일 책임 원칙 (Single Responsibility Principle)의 정의&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;모듈을 변경하는 이유는 단 하나여야만 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;처음에 이걸 봤을 땐 “어차피 변경하는 이유는 한가지 아닌가?” 라고 생각했기 때문에
애매모호하며 무엇이 중요한지 이해하기가 쉽지 않았다.&lt;/p&gt;

&lt;p&gt;변경하려는 이유에 관점을 두는 것이 아니라, &lt;strong&gt;변경하는 이유를 만드는 주체(액터)&lt;/strong&gt; 에 관점을 두는 것이 중요했다.
액터는 같은 목적을 가지고 그 기능을 사용하는 대상을 뜻한다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;한 액터만이 유일한 변경의 원천이어야만 하며, 액터가 서로 다른 코드는 분리해야만 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;개방-폐쇄-원칙-ocp--open-closed-principle&quot;&gt;개방 폐쇄 원칙 (OCP : Open-Closed Principle)&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;소프트웨어의 구성요소는 확장에 대해 열려있고, 수정에 대해선 닫혀 있어야 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;확장에 대한 Open : 요구사항의 변경에 맞게 모듈을 확장 가능해야 한다.&lt;/li&gt;
  &lt;li&gt;수정에 대한 Closed : 기능의 확장을 할 때 기존 코드의 수정은 없어야 한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;바꿔 말하면, 기존의 동작은 수정없이 유지하며 추가 기능을 확장할 수 있어야 한다.
예를 들어, 화면 출력 방식 변경/추가를 할 떄, 비즈니스 로직이나 데이터 저장 등의 기존 기능의 수정이 없이 이루어져야 한다.&lt;/p&gt;

&lt;h2 id=&quot;리스코브-치환원칙-lsp--liskov-substitution-principle&quot;&gt;리스코브 치환원칙 (LSP : Liskov Substitution Principle)&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;자식 클래스를 부모 클래스의 자리에 넣어도 문제 없이 작동 해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;프로그램의 실행에는 영향을 주지 않으면서 기본 클래스의 참조를 파생클래스의 참조로 변경할 수 있어야 한다.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Porsche&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Porsche&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Porsche&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;위와 같이 부모 클래스로 업캐스팅 해도 동작에는 문제가 발생하지 않아야 한다.&lt;/p&gt;

&lt;h2 id=&quot;인터페이스-분리-원칙-ispinterface-segregation-principle&quot;&gt;인터페이스 분리 원칙 (ISP：Interface Segregation Principle)&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;직접 필요로 하지 않는 모듈을 의존하지 않는 것으로, 예상치 못한 문제의 발생을 억제 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;자신이 필요로 하지 않는 메소드에는 의존하지 않아야 한다.
그렇지 않은경우, 참조하고 있는 클래스에 필요로 하지 않는 메소드의 수정으로 인해 재컴파일, 재배포가 발생한다.&lt;/p&gt;

&lt;p&gt;이는 정적 언어에만 해당 하는 경우이지만, 아키텍처 레벨에도 ISP의 근본적인 사상을 적용 하는 것이 문제 발생을 억제 할 수 있다.&lt;/p&gt;

&lt;h2 id=&quot;의존관계-역전-원칙-dipdependency-inversion-principle&quot;&gt;의존관계 역전 원칙 (DIP：Dependency Inversion Principle)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;추상화 된 것을 참조, 상속 (의존) 해야 한다.&lt;/li&gt;
  &lt;li&gt;구체 클래스가 추상 클래스를 의존해야 한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;가장 유연한 시스템은 소스의 의존관계가 인터페이스만을 참조하고 있는 경우이다.&lt;/p&gt;

&lt;h2 id=&quot;solid는-객체지향에만-적용-되는가&quot;&gt;SOLID는 객체지향에만 적용 되는가?&lt;/h2&gt;
&lt;p&gt;SOLID 원칙에 대해서 찾아보면 ‘객체지향’이라는 단어가 항상 붙어 나와서,
객체지향에서만 적용되는 원칙같아 보이지만 꼭 그렇지만은 않다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/4048930656/ref=cm_sw_em_r_mt_dp_U_PfzQCbF5KA7KC&quot;&gt;Clean Architecture&lt;/a&gt;에서 엉클밥은 어떠한 소프트웨어 시스템이라도 OOP의 클래스처럼 몇가지의 기능과 데이터를 모아 두는 구조가 있을 것이며, SOLID는 그런 구조에 적용하는 원칙이라고 말한다.&lt;/p&gt;

&lt;h2 id=&quot;마무리&quot;&gt;마무리&lt;/h2&gt;
&lt;p&gt;개념의 타이틀 수준으로만 정리 했지만, 예를 들어가며 설명하기에는 아직 이해가 많이 부족하며, 역시 간단하게 정리가 될 만큼 쉬운내용은 아니란걸 깨달았다.&lt;/p&gt;

&lt;p&gt;각 원칙에 대해 예를 들어가며 설명이 될 정도로 공부해서 재 포스팅을 할 예정이다.&lt;/p&gt;
</description>
        <pubDate>Sun, 07 Apr 2019 14:53:00 +0000</pubDate>
        <link>http://lostfind.github.io/architecture/2019/04/07/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84%EC%9B%90%EC%B9%99.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/architecture/2019/04/07/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84%EC%9B%90%EC%B9%99.html</guid>
        
        <category>architecture</category>
        
        <category>SOLID</category>
        
        
        <category>Architecture</category>
        
      </item>
    
      <item>
        <title>[엔지니어의 지적생산기술]을 읽고 난 정리</title>
        <description>&lt;p&gt;엔지니어의 지적생산기술이라는 책을 읽고 감상을 정리해둡니다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://amzn.to/2uOvS0D&quot;&gt;エンジニアの知的生産術&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;읽어보면 당연한 말을 하는 것 같지만, 의외로 평소에 크게 생각하지 않으며 지냈다는 것을 깨달았다.&lt;/p&gt;

&lt;p&gt;저자도 여러 가지 방법론을 익혀서 실천해 본 후 자신에 맞는 방법을 만들어 낸 것 같다. 나도 일단 실천해 보고 판단하여 개선해 나갈 계획이다.&lt;/p&gt;

&lt;h2 id=&quot;1장-새로운-것을-배우려면&quot;&gt;1장 새로운 것을 배우려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;정보수집
    &lt;ul&gt;
      &lt;li&gt;우선은 대략 전체 구조를 파악한다. 그게 안 된다면 닥치는 대로 수집.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;추상화, 모델화
    &lt;ul&gt;
      &lt;li&gt;수집한 정보에서 패턴을 발견해 추상화, 모델화를 진행한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;배운 것을 실천, 검증함으로 직접적인 경험이 된다.
    &lt;ul&gt;
      &lt;li&gt;프로그램이라면 직접 작성해봄으로 검증 가능.&lt;/li&gt;
      &lt;li&gt;블로그나 타인에게 대한 설명으로 자신의 이해도가 부족하지 않은지 무엇을 더 보충해야 하는지 알게 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;위의 3가지를 반복한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2장-의욕을-내려면&quot;&gt;2장 의욕을 내려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;지금 하려는 작업 한 개만 선택한다. 여러 개를 처리하려고 하면 의욕이 나기 어렵다.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Getting_Things_Done&quot;&gt;Getting Things Done&lt;/a&gt; 일단 할 일을 모두 한곳에 모아 전체를 파악한 후, 하나씩 처리해 나간다.&lt;/li&gt;
  &lt;li&gt;긴급함이 아니라 중요함을 우선으로 작업을 선택한다.
    &lt;ul&gt;
      &lt;li&gt;단, 우선순위를 반드시 지정할 필요는 없다. 그 자체도 공수가 많이 들기 때문&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%84%B1%EA%B3%B5%ED%95%98%EB%8A%94_%EC%82%AC%EB%9E%8C%EB%93%A4%EC%9D%98_7%EA%B0%80%EC%A7%80_%EC%8A%B5%EA%B4%80&quot;&gt;“성공하는 사람들의 7가지 습관”&lt;/a&gt;의 습관3&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;작업을 하나만 선택해도 그 자체가 너무 크면 의욕이 사라진다.
    &lt;ul&gt;
      &lt;li&gt;작업 하나가 너무 큰 경우(2시간 이상) 업무를 더 작은 단위로 나누기&lt;/li&gt;
      &lt;li&gt;작업 처리 견적을 제대로 잡기 위해 자신의 처리 능력을 파악해둔다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3장-기억을-단련시키려면&quot;&gt;3장 기억을 단련시키려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;반복 학습과 아웃풋을 통해 기억을 단련한다.&lt;/li&gt;
  &lt;li&gt;SuperMemo등 여러 공부 방법을(암기법?) 소개했지만 중요한 건 역시 반복과 아웃풋을 통해 이해도를 높여 가는 것.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4장-효율적으로-읽으려면&quot;&gt;4장 효율적으로 읽으려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;1페이지 2초 이하의 속도로 전체 내용을 대략 읽어 정보를 발견한다.&lt;/li&gt;
  &lt;li&gt;1페이지 3분 이상의 속도로 머릿속에서 정보를 조립하여 이해한다.&lt;/li&gt;
  &lt;li&gt;습득한 정보나 지식을 다른 사람을 가르치기 위한 자료를 작성한다.
    &lt;ul&gt;
      &lt;li&gt;실제로 가르치지 않더라도 자료 작성으로 복습, 기억 강화 효과가 발생&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;5장-생각을-정리하려면&quot;&gt;5장 생각을 정리하려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;생각이 정리 안 되는 이유는 정보량이 너무 많거나 혹은 너무 적거나.&lt;/li&gt;
  &lt;li&gt;정보량이 적은지 많은지 확인하는 방법
    &lt;ul&gt;
      &lt;li&gt;수단어 ~ 한문장 정도로 관련 정보 100개 정도 작성 가능한지를 기준으로 잡는다.
내용의 질이나 중복은 생각하지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;정보가 많을 경우 관계성을 파악해나가며 그룹화한다.
    &lt;ul&gt;
      &lt;li&gt;그룹을 미리 정해 두지 않는다. 미리 정해 두면 새로운 발견이나 관계성 파악에 방해가 될 뿐이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;6장-아이디어를-생각해내려면&quot;&gt;6장 아이디어를 생각해내려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;경작, 발아, 성장시키기 단계로 진행한다.
    &lt;ul&gt;
      &lt;li&gt;경작 : 정보수집&lt;/li&gt;
      &lt;li&gt;발아 : 관계발견, 추상화, 모델화, 정보의 결합&lt;/li&gt;
      &lt;li&gt;성장 : 아이디어의 언어화, 구체화&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;아이디어는 주관적으로 기존의 틀을 깨, 보수적인 판단에서 벗어난다.&lt;/li&gt;
  &lt;li&gt;생각해 낸 아이디어를 예를 들 수 있는 언어화, 구체화해나간다.&lt;/li&gt;
  &lt;li&gt;아이디어를 실체화해 나갈 때는 타인의 시점이 매우 중요하다.&lt;/li&gt;
  &lt;li&gt;아이디어가 발아될 때까지 정보 수집을 계속해 나간다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;7장-무엇을-배울지-정하려면&quot;&gt;7장 무엇을 배울지 정하려면&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;무엇을 배울지 고민만 하면 아무런 결과가 발생하지 않는다. 일단 배워보고 방향성이 맞았는지 틀렸는지 판단한다.&lt;/li&gt;
  &lt;li&gt;지식의 양이 조금 줄어들더라도 분야를 넓게 하여 여러 사람과 커뮤니케이션이 가능하도록 한다.
커뮤니케이션, 연결고리 역할을 통해 지식의 양이 늘어간다.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 24 Mar 2019 15:48:00 +0000</pubDate>
        <link>http://lostfind.github.io/book/2019/03/24/%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EC%9D%98-%EC%A7%80%EC%A0%81%EC%83%9D%EC%82%B0%EA%B8%B0%EC%88%A0.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/book/2019/03/24/%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EC%9D%98-%EC%A7%80%EC%A0%81%EC%83%9D%EC%82%B0%EA%B8%B0%EC%88%A0.html</guid>
        
        <category>기술서적</category>
        
        
        <category>book</category>
        
      </item>
    
      <item>
        <title>PHP 세션관리</title>
        <description>&lt;p&gt;웹 개발자로서 기본적으로 알고 있어야 할 지식이지만, 남에게 확신을 가지고 설명 할 수 없는 상태였기 때문에 공부 한 후 정리 해둔다.&lt;/p&gt;

&lt;h2 id=&quot;php에서-세션&quot;&gt;PHP에서 세션&lt;/h2&gt;

&lt;p&gt;프레임 워크를 없이 순수 PHP에서의 세션 관리를 위한 방법.&lt;/p&gt;

&lt;h3 id=&quot;세션의-시작-재개&quot;&gt;세션의 시작, 재개&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 각 페이지의 스크립트 최상단에서 호출 해야 한다.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;session_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;세션의-종료&quot;&gt;세션의 종료&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;session_destroy();&lt;/code&gt;만으로는 슈퍼전역변수 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_SESSION&lt;/code&gt;과 세션쿠키를 해제하지 않기 때문에 세션 파괴 전에 처리 해야 할 필요가 있다.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# session_destroy를 호출하기 전에 세션을 재개&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;session_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 세션 글로벌 변수를 초기화&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$_SESSION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 세션ID를 보관 하고 있는 쿠키 삭제&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_COOKIE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;session_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;setcookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;session_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 현재 세션에 관련된 모든 데이터를 파괴.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;session_destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;h2 id=&quot;샘플코드&quot;&gt;샘플코드&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-php:session_start.php&quot;&gt;&amp;lt;?php
  session_start();

  if (!isset($_SESSION['count'])) {
    $_SESSION['count'] = 0;
  }
  if (!isset($_SESSION['createTime'])) {
    $_SESSION['createTime'] = date(&quot;Y/m/d H:i:s&quot;);
  }
?&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;/&amp;gt;
    &amp;lt;title&amp;gt;PLAYGROUND&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div&amp;gt;
      세션ID : &amp;lt;?= session_id() ?&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      액세스 수 : &amp;lt;?= $_SESSION['count']++ ?&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      세션생성일시 : &amp;lt;?= $_SESSION['createTime'] ?&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;a href=&quot;session_check.php&quot;&amp;gt;세션유지확인&amp;lt;/a&amp;gt;
      &amp;lt;a href=&quot;session_destroy.php&quot;&amp;gt;세션파괴&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-php:session_check.php&quot;&gt;&amp;lt;?php
session_start();
?&amp;gt;

&amp;lt;div&amp;gt;
  세션 ID : &amp;lt;?= session_id() ?&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;
  세션생성일시 : &amp;lt;?= $_SESSION['createTime'] ?&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div&amp;gt;
  &amp;lt;a href=&quot;session_start.php&quot;&amp;gt;세션생성&amp;lt;/a&amp;gt;
  &amp;lt;a href=&quot;session_destroy.php&quot;&amp;gt;세션파괴&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-php:session_destroy.php&quot;&gt;&amp;lt;?php
session_start();

echo &quot;파괴 전의 세션 내용&amp;lt;br&amp;gt;&quot;;
print_r($_SESSION);
$_SESSION = array();

if (isset($_COOKIE[session_name()])) {
  setcookie(session_name(), '', time() - 3600, '/');
}
session_destroy();

echo &quot;&amp;lt;hr&amp;gt;세션 파괴 후&amp;lt;br&amp;gt;&quot;;
print_r($_SESSION);
?&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div&amp;gt;
  &amp;lt;a href=&quot;session_start.php&quot;&amp;gt;세션생성&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;세션이란&quot;&gt;세션이란&lt;/h2&gt;

&lt;p&gt;동적 웹 프로그래밍에서 필수적인 요소이다.
HTTP 프로토콜은 상태를 저장 할 수 없는 일회성인 요청과 응답만이 있는 프로토콜이기 때문에,
웹 서버와 클라이언트 간의 상태를 유지시켜 지속적인 통신을 하기 위해 쿠키나 세션을 사용한다.&lt;/p&gt;

&lt;p&gt;그 중 세션은 사용자의 요청에 대한 정보를 세션 아이디를 부여한 후 웹 서버에 저장하고,
세션 아이디를 사용자의 쿠키에 저장하여 HTTP 요청 시 쿠키에 저장된 ID로 사용자의 세션을 판단한다.&lt;/p&gt;

&lt;p&gt;동일한 도메인을 가진 경우 웹 브라우저에서는 세션이 공유 되지만, 타 브라우저 혹은 시크릿 모드와는 기본적으로 세션 공유가 되지 않는다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;
&lt;p&gt;PHP 매뉴얼&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/en/reserved.variables.session.php&quot;&gt;슈퍼전역변수 $_SESSION&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/en/function.session-start.php&quot;&gt;session_start()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://php.net/manual/en/function.session-destroy.php&quot;&gt;session_destroy()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 03 Mar 2019 16:37:00 +0000</pubDate>
        <link>http://lostfind.github.io/php/2019/03/03/PHP%EC%84%B8%EC%85%98%EA%B4%80%EB%A6%AC.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/php/2019/03/03/PHP%EC%84%B8%EC%85%98%EA%B4%80%EB%A6%AC.html</guid>
        
        <category>session</category>
        
        <category>php</category>
        
        
        <category>php</category>
        
      </item>
    
      <item>
        <title>Docker로 Rails, MySQL개발 환경 설정</title>
        <description>&lt;p&gt;Docker에서 Rails로 웹개발을 하기 위해 세팅했던 내용들&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-dockerfile:./docker/mysql/Dockerfile&quot;&gt;FROM mysql:5.7.25
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y apt-utils locales &amp;amp;&amp;amp; \
    rm -rf /var/lib/apt/lists/* &amp;amp;&amp;amp; echo &quot;ja_JP.UTF8 UTF-8&quot; &amp;gt; /etc/locale.gen &amp;amp;&amp;amp; \
    locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
ADD ./docker/mysql/my.cnf /etc/my.cnf
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-dockerfile:./docker/ruby/Dockerfile&quot;&gt;FROM ruby:2.6.1
ENV LANG C.UTF-8

#for MySQL
RUN apt-get update -qq &amp;amp;&amp;amp; apt-get install -y apt-utils \
      build-essential libpq-dev nodejs mysql-client

RUN gem install bundler

WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install

ENV APP_HOME /accountbook
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD . $APP_HOME
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-yml:docker-compose.yml&quot;&gt;version: '2'
services:
  datastore:
    image: busybox
    volumes:
      - /share
      - ./docker/mysql/volumes:/var/lib/mysql
  server:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    ports:
      - '8090:80'
    volumes_from:
      - datastore
    depends_on:
      - datastore
  web:
    build:
      context: .
      dockerfile: ./docker/ruby/Dockerfile
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - '3600:3000'
    volumes:
      - .:/accountbook
    environment:
      RAILS_ENV: development
    volumes_from:
      - datastore
    depends_on:
      - db
    links:
      - db
      - db:database
      - db:mysql
    extends:
      file: ./docker/mysql/password.yml
      service: password
  db:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    ports:
      - '3606:3306'
    volumes_from:
      - datastore
    depends_on:
      - datastore
    extends:
      file: ./docker/mysql/password.yml
      service: password
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;레일즈-초기-설정&quot;&gt;레일즈 초기 설정&lt;/h3&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; web rails new &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--database&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;mysql &lt;span class=&quot;nt&quot;&gt;--skip-bundle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;db-초기설정-레일즈-이용&quot;&gt;DB 초기설정 (레일즈 이용)&lt;/h3&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; web bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;rake db:create
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;트러블&quot;&gt;트러블&lt;/h2&gt;
&lt;p&gt;레일즈가 제대로 시작되지 않을 때&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;tmp/pids/server.pid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;docker-compose-관련-명령어&quot;&gt;docker-compose 관련 명령어&lt;/h2&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 중지&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose down

&lt;span class=&quot;c&quot;&gt;# 실행&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose up

&lt;span class=&quot;c&quot;&gt;# 실행 (데몬, 백그라운드)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose up

&lt;span class=&quot;c&quot;&gt;# 현재 상태 확인&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 03 Feb 2019 20:35:00 +0000</pubDate>
        <link>http://lostfind.github.io/development/2019/02/03/docker-rails-mysql.html</link>
        <guid isPermaLink="true">http://lostfind.github.io/development/2019/02/03/docker-rails-mysql.html</guid>
        
        <category>Rails</category>
        
        <category>Docker</category>
        
        
        <category>Development</category>
        
      </item>
    
  </channel>
</rss>
