<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>zyan.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 02 Feb 2024 08:45:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>zyan.log</title>
            <url>https://images.velog.io/images/bingbong-party/profile/342bc470-c3ae-4fbe-884b-942dededc27b/profile.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. zyan.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bingbong-party" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[전략패턴(Strategty Pattern)]]></title>
            <link>https://velog.io/@bingbong-party/%EC%A0%84%EB%9E%B5%ED%8C%A8%ED%84%B4Strategty-Pattern</link>
            <guid>https://velog.io/@bingbong-party/%EC%A0%84%EB%9E%B5%ED%8C%A8%ED%84%B4Strategty-Pattern</guid>
            <pubDate>Fri, 02 Feb 2024 08:45:32 GMT</pubDate>
            <description><![CDATA[<h3 id="전략패턴이란">전략패턴이란?</h3>
<blockquote>
<p>알고리즘군을 정의하고 캡슐화해서 각각의 알고리즘군을 수정해서 쓸 수 있게 해준다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분석해서 독립적으로 변경할 수 있다.
<em>참고: (도서)헤드 퍼스트 디자인 패턴</em></p>
</blockquote>
<p>만약 오리(Duck) 클래스가 있다고 하자.</p>
<ul>
<li>오리 클래스를 상속받는 클래스는 여러개가 있다.<ul>
<li>청둥오리(Mallard Duck), 원앙(Mandarin Duck), 러버덕(RubberDuck, 장난감) 등..</li>
</ul>
</li>
<li>각각의 오리의 생김새를 나타내는 추상메소드인 display가 Duck클래스에 존재한다.</li>
<li>몇몇의 오리에게는 &#39;날아가는&#39;행동을 하게끔 하고 싶은데, Duck클래스에 fly 메소드를 추가하기에는 무리가 있다. 러버덕은 날 수 없기 때문에..</li>
<li>그렇다고 자식 클래스가 특정 fly 인터페이스를 구현하도록 설계하면, 모든 자식 클래스마다 동일한 메소드를 구현해주어야 하고, 수정이 필요할 때도 마찬가지로 모든 클래스에서 수정하는 작업을 반복해야 한다. 물론 버그 발생 가능성이 높아진다.</li>
<li>따라서 &#39;날아가는&#39;행동을 오리클래스나 오리자식클래스에서 정의한 메소드를 사용하도록 하는 것이 아니라, 이 행위를 다른 클래스에 <strong>&#39;위임&#39;</strong>한다.</li>
</ul>
<p>이를 간단한 UML로 표현해보면 아래와 같다.
<img src="https://velog.velcdn.com/images/bingbong-party/post/a75829a2-3373-4f97-ab3b-725a23fbac4c/image.png" alt="">
이제 &#39;날아가는&#39;행위는 Duck 클래스의 flyBehavior 변수가 FlyBehavior 인터페이스를 구현한 클래스를 참조하게 함으로써 여러 종류의 오리가 각각 다른 &#39;날기&#39;를 할 수 있게 되었다.
flyBehavior가 참조하는 클래스를 동적으로 변경할 수 있도록 하려면 Duck 클래스에 setFlyBehavior 메소드를 추가하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[fork한 respository에 commit한 내역을 나의 repository에 그대로 반영시키는 법]]></title>
            <link>https://velog.io/@bingbong-party/fork%ED%95%9C-respository%EC%97%90-commit%ED%95%9C-%EB%82%B4%EC%97%AD%EC%9D%84-%EB%82%98%EC%9D%98-repository%EC%97%90-%EA%B7%B8%EB%8C%80%EB%A1%9C-%EB%B0%98%EC%98%81%EC%8B%9C%ED%82%A4%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@bingbong-party/fork%ED%95%9C-respository%EC%97%90-commit%ED%95%9C-%EB%82%B4%EC%97%AD%EC%9D%84-%EB%82%98%EC%9D%98-repository%EC%97%90-%EA%B7%B8%EB%8C%80%EB%A1%9C-%EB%B0%98%EC%98%81%EC%8B%9C%ED%82%A4%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Fri, 26 Jan 2024 05:35:43 GMT</pubDate>
            <description><![CDATA[<ol>
<li>fork한 repository의 root 디렉토리로 이동</li>
<li><code>git push --mirror {나의_repository_URL}</code> 커맨드 실행</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[docker compose 커맨드 사용법]]></title>
            <link>https://velog.io/@bingbong-party/docker-compose-%EC%BB%A4%EB%A7%A8%EB%93%9C-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@bingbong-party/docker-compose-%EC%BB%A4%EB%A7%A8%EB%93%9C-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Fri, 26 Jan 2024 05:15:51 GMT</pubDate>
            <description><![CDATA[<h3 id="docker-composeyml-파일-실행">docker-compose.yml 파일 실행</h3>
<pre><code>docker-compose up -d</code></pre><p><code>docker-compse up</code> | docker.compose.yml에 정의되어 있는 모든 서비스 컨테이너를 한 번에 생성하고 실행함. 커맨드가 실행되는 디렉토리에 있는 docker-compose.yml 파일을 설정파일로 사용함.
<code>-f</code> | 다른 이름이나, 다른 경로에 있는 설정파일을 사용하고 싶을 경우 해당 옵션으로 명시 가능 
<code>-d</code> | 백그라운드에서 컨테이너를 띄움</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Singleton Pattern] Singleton Pattern]]></title>
            <link>https://velog.io/@bingbong-party/Singleton-Pattern</link>
            <guid>https://velog.io/@bingbong-party/Singleton-Pattern</guid>
            <pubDate>Wed, 29 Sep 2021 13:25:00 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-singleton-pattren">🍋 Singleton Pattren</h2>
<p>프로그램이 실행될 때, 특정 클래스가 <strong><em>최초 한 번만</em></strong> 메모리를 할당하고(static) 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴</p>
<p>생성자가 여러차례 호출되더라도 실제로 생성되는 객체는 하나이고, 최초 생성 이후에 호출된 생성자는 최초에 생성한 객체를 반환한다. </p>
<ul>
<li><p>생성자를 private으로 선언해서 생성 불가하게 하고, getInstance()로 받아씀</p>
<p>  → getInstance() 메소드를 통해 모든 클라이언트에게 동일한 인스턴스 반환</p>
</li>
</ul>
<pre><code class="language-java"> public class singleton {

    private static singleton instance = new singleton();

        public static singleton getInstance() {
            return instance;
        }
    }</code></pre>
<h3 id="🟡-싱글톤-패턴을-사용하는-이유">🟡 싱글톤 패턴을 사용하는 이유</h3>
<ul>
<li>메모리를 추가로 할당하지 않기 때문에 메모리 낭비를 방지할 수 있다.</li>
<li>싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스이기 때문에, 다른 클래스의 인스턴스들이 데이터를 공유하기 쉽다.</li>
</ul>
<p><em>출처 <a href="https://jeong-pro.tistory.com/86">https://jeong-pro.tistory.com/86</a></em></p>
<hr>
<p>열심히 찾아본다고 인터넷을 많이도 뒤져봤지만, 사실 아직 이해가 잘 되지 않는다. 따라서 기록은 이쯤 하고, 조금 더 학습 후에 내용을 추가해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DAO] DAO]]></title>
            <link>https://velog.io/@bingbong-party/DAO-DAO</link>
            <guid>https://velog.io/@bingbong-party/DAO-DAO</guid>
            <pubDate>Wed, 29 Sep 2021 13:23:37 GMT</pubDate>
            <description><![CDATA[<p>Data Access Object의 약자이며, sql + java, 즉 crud 메소드들로 구성된 클래스를 의미한다. db연동 클래스를 정형화하여 개발하게 하는 구조.</p>
<p>아래 코드와 같이 구성된 pattern을 DAO라 한다.</p>
<pre><code class="language-java">package step02.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

import util.DBUtil;

public class DeptDAO {

//@Test
public void deleteOne() {
    Connection con = null;
    Statement stmt = null;

    try {
        con = DBUtil.getConnection();
        stmt = con.createStatement();

        int result = stmt.executeUpdate(&quot;DELETE FROM dept WHERE deptno=60&quot;);

        if(result == 1) {
            System.out.println(&quot;삭제 성공&quot;);
        }else {
            System.out.println(&quot;deptno 삭제 실패&quot;);
        }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(con, stmt);
        }            
}


//@Test    
public void updateOne() {
    Connection con = null;
    Statement stmt = null;

    try {
        con = DBUtil.getConnection();
        stmt = con.createStatement();

        int result = stmt.executeUpdate(&quot;UPDATE dept SET loc=&#39;평양&#39; WHERE deptno=60&quot;);

        if(result == 1) {
            System.out.println(&quot;수정 성공&quot;);
        }else {
            System.out.println(&quot;deptno 수정 실패&quot;);
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        DBUtil.close(con, stmt);
    }        
}


//@Test
public void insertOne() {
    Connection con = null;
    Statement stmt = null;

    try {
        con = DBUtil.getConnection();
        stmt = con.createStatement();

        //executeUpdate() : insert/update/delete sql문장 처리 메소드 
        int result = stmt.executeUpdate(&quot;insert into dept values (60, &#39;교육부&#39;, &#39;남부&#39;)&quot;);

        if(result == 1) {
            System.out.println(&quot;저장 성공&quot;);
        }else {
            System.out.println(&quot;deptno 중복 저장 불허&quot;);
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        DBUtil.close(con, stmt);
    }        
}





//부서번호(deptno)로 한 부서 정보만 검색
//@Test
public void selectOne() {
    Connection con = null;
    Statement stmt = null;
    ResultSet rset = null;

    try {
        con = DBUtil.getConnection();
        stmt = con.createStatement();

        rset = stmt.executeQuery(&quot;select * from dept where deptno=10&quot;);

        if(rset.next()) {
                System.out.println(rset.getInt(&quot;deptno&quot;) + &quot;/&quot; + rset.getString(&quot;dname&quot;) + &quot;/&quot; + rset.getString(&quot;loc&quot;));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(con, stmt, rset);
        }
}


//모든 검색
@Test
public void selectAll() {
    Connection con = null;
    Statement stmt = null;
    ResultSet rset = null;

    try {
        con = DBUtil.getConnection();  
        stmt = con.createStatement();   

        rset = stmt.executeQuery(&quot;select * from dept&quot;);

        while(rset.next()) {
                System.out.println(rset.getInt(&quot;deptno&quot;) + &quot;/&quot; + rset.getString(&quot;dname&quot;) + &quot;/&quot; + rset.getString(&quot;loc&quot;));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(con, stmt, rset);
        }
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 상속]]></title>
            <link>https://velog.io/@bingbong-party/JAVA-%EC%83%81%EC%86%8D</link>
            <guid>https://velog.io/@bingbong-party/JAVA-%EC%83%81%EC%86%8D</guid>
            <pubDate>Wed, 29 Sep 2021 13:19:03 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-상속">🍋 상속</h2>
<ul>
<li>클래스간의 상속을 의미</li>
<li>이미 존재하는 클래스를 기반으로 새로운 클래스 개발</li>
<li>부모클래스 / 자식클래스 구조 관리</li>
<li>부모클래스에서 자식클래스에로 상속될 때, 멤버변수와 메소드만 상속됨</li>
</ul>
<pre><code class="language-java">class Parent {
    int age;
    String name;

    void print() {
        System.out.println(age);
        System.out.println(name);
    }
}

public class Child extends Parent { //상속
    String job = &quot;it&quot;;

    void print() {
        super.print();
        System.out.println(job);
    }
}</code></pre>
<h3 id="🟡-재정의override--overriding">🟡 재정의(override / overriding)</h3>
<p>메소드를 상속받고 내용 수정</p>
<h3 id="🟡-다형성">🟡 다형성</h3>
<ul>
<li><p>많은 형태를 보유할 수 있다는 의미</p>
</li>
<li><p>상위 타입 변수는 하위 타입의 모든 객체를 수용</p>
</li>
<li><p>상위 타입 변수 = 하위 타입 객체</p>
</li>
<li><p>전제 조건</p>
<p>  상속 관계여야만 성립되는 문법</p>
</li>
<li><p>rule</p>
<p>  상위타입 변수로 생성된 자식 객체의 멤버를 호출할 시에는 상속 시킨 멤버에 한해서만 access(호출)가능. 만약, Parents를 상속받은 Child클래스에만 존재하는 변수를 Parents를 통해 호출하고 싶은 경우, 형변환은 필수이다.</p>
</li>
</ul>
<pre><code class="language-java">    Parent p = new Child2(); //다형성 객체 생성 문법 O
    Child c = new Child2();  //다형성 객체 생성 문법 X

    Child c2 = (Child)p; //형변환

    c2.job = &quot;manager&quot;; //job은 Child클래스에만 있는 멤버변수</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] Wrapper]]></title>
            <link>https://velog.io/@bingbong-party/JAVA-Wrapper</link>
            <guid>https://velog.io/@bingbong-party/JAVA-Wrapper</guid>
            <pubDate>Wed, 29 Sep 2021 13:17:28 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-wrapper-class">🍋 Wrapper Class?</h2>
<p>기본 값을 객체화해서 객체들만의 제약조건이 있는 상황에 사용 가능하게 해주는 것</p>
<h3 id="🟡-용도">🟡 용도</h3>
<ul>
<li>객체들만 저장 가능한 자료구조 클래스에 활용</li>
<li>기본 타임 형식의 데이터들을 가공해야할 경우 주로 사용
ex) &quot;3&quot;을 int로 변경할 때, 메소드를 통해서 처리 ⇒ Integer.parseInt(&quot;3&quot;)</li>
</ul>
<h3 id="🟡-autoboxing-unboxing">🟡 autoboxing, unboxing</h3>
<ul>
<li><p>autoboxing</p>
<p>기본 타입의 데이터를 객체로 자동 변환</p>
</li>
<li><p>unboxing</p>
<p>객체 타입의 데이터를 기본 타입으로 자동 변환</p>
</li>
</ul>
<pre><code class="language-java">package step02.api;

import java.util.ArrayList;

public class WrapperTest {
    public static void main(String[] args) {
        //i1은 객체타입(int-기본타입 / Integer-참조(객체)타입)
        //즉, 깁노 타입의 데이터를 객체로 자동 변환하는 autoboxing
        Integer i1 = 3; //Integer i1 = new Integer(3);
        System.out.println(i1);

        //객체 타입을 기본타입으로 변환해서 대입
        int i2 = new Integer(7); //int i2 = (new Integer(7)).intValue();

        ArrayList&lt;Integer&gt; al = new ArrayList&lt;&gt;();
        al.add(3); //al.add(new Integer(3));

        Integer i4 = al.get(0); //Integer객체 반환
        System.out.println(i4.doubleValue()); //3.0
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] optional api]]></title>
            <link>https://velog.io/@bingbong-party/JAVA-optional-api</link>
            <guid>https://velog.io/@bingbong-party/JAVA-optional-api</guid>
            <pubDate>Wed, 29 Sep 2021 13:14:41 GMT</pubDate>
            <description><![CDATA[<h3 id="ofnullable">ofNullable()</h3>
<pre><code class="language-java">String s1 = null;
Optional&lt;String&gt; opt = Optional.ofNullable(s1);</code></pre>
<ul>
<li>value(위 코드에선 s1)가 null일 경우, 비어있는 Optional반환 → Optional.empty</li>
</ul>
<h3 id="ispresent">isPresent()</h3>
<pre><code class="language-java">String s1 = &quot;playdata&quot;;
Optional&lt;String&gt; opt2 = Optional.ofNullable(s1);
System.out.println(opt2.isPresent()); // 데이터가 존재할 경우 true 반환 
System.out.println(opt.isPresent());  // null인 경우는 false반환</code></pre>
<ul>
<li>데이터가 존재할 경우, true를 반환하고 null인 경우에는 false를 반환</li>
</ul>
<h3 id="ifpresent">ifPresent()</h3>
<pre><code class="language-java">String s1 = &quot;playdata&quot;;
Optional&lt;String&gt; opt = Optional.ofNullable(s1);

opt.ifPresent(data -&gt; {
            System.out.println(data.length()); //8
            });</code></pre>
<ul>
<li>최종적인 연산이 끝난 후, 값이 비어있지 않다면 입력값으로 주어짐. 값이 비어있다면 해당 로직은 실행되지 않는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] IO]]></title>
            <link>https://velog.io/@bingbong-party/JAVA-IO</link>
            <guid>https://velog.io/@bingbong-party/JAVA-IO</guid>
            <pubDate>Wed, 29 Sep 2021 13:12:14 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-ioinput-output">🍋 IO(Input Output)</h2>
<h3 id="🟡-buffer">🟡 buffer</h3>
<p>데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 임시 메모리 영역</p>
<h3 id="🟡-bufferedreaderbufferedwriter">🟡 BufferedReader/BufferedWriter</h3>
<p>BufferedReader/BufferedWrite 는 이름 그대로, 버퍼를 이용해 읽고 쓰는 함수</p>
<ul>
<li><p>버퍼를 사용하지 않는 입력</p>
<p>  키보드의 입력이 키를 누르는 즉시 바로 전달 됨 (키보드→프로그램)</p>
</li>
<li><p>버퍼를 사용하는 입력</p>
<p>  키보드의 입력이 있을 때마다 한 문자씩 버퍼로 전송. 버퍼가 가득 차거나 개행 문자가 나타나면 버퍼의 내용을 한 번에 전송함</p>
</li>
</ul>
<p><em>⇒ 입력값을 하나하나 전달하는 것보다 입력받은 값들을 한번에 전달하는 것이 더 효율적이다.</em></p>
<ol>
<li><p><strong>BufferedReader</strong></p>
<ul>
<li><p>readLine()</p>
<p>  readLine()이라는 메소드를 통해 입력받는다. 이 경우 리턴값은 String으로 고정되기에, String이 아닌 다른 타입으로 입력받기 위해서는 형변환이 필수이다.</p>
</li>
<li><p>예외처리</p>
<p>  예외처리가 필수적이다. readLine()실행 시마다 try&amp;catch를 활용해 예외처리를 해주거나, throw IOExceptiond을 이용한다.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="language-java">BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        try {

            String data = null;

            while ((data=in.readLine()) != null) {
                System.out.println(data);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }</code></pre>
<ol start="2">
<li><p><strong>BufferedWriter</strong></p>
<ul>
<li><p>write(), flush(), close()</p>
<p>  write()를 사용하여 데이터를 입력하고, flush()를 통해 버퍼를 비워내는 동시에 콘솔에 출력 출력이 끝난 후에는 close()를 통해 스트림을 닫아준다.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="language-java">public static void io2() {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter out = null; //try블록에서 선언할 경우 finally블록에서 종료불가. 따라서 선언은 try밖에서
        try {
            out = new BufferedWriter(new FileWriter(&quot;playdata.txt&quot;));
            String data = null;

            while ((data=in.readLine()) != null) {
                out.write(data);
                out.newLine(); //라인바꿈 반영해서 출력
                out.flush(); //버퍼 메모리에 존재하는데이터를 파일에 잔존 데이터 없이 출력
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JDBC] JDBC]]></title>
            <link>https://velog.io/@bingbong-party/JDBC-JDBC</link>
            <guid>https://velog.io/@bingbong-party/JDBC-JDBC</guid>
            <pubDate>Wed, 29 Sep 2021 13:09:18 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-jdbcjava-database-connectivity">🍋 JDBC(Java Database Connectivity)</h2>
<p>JDBC란, 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. </p>
<h3 id="🟡-jdbc-프로그래밍의-전체적인-흐름">🟡 JDBC 프로그래밍의 전체적인 흐름</h3>
<p>*<em>1. 실행중인 DB
*</em>
    사용하려는 DB가 실행중이어야 한다. 이는 윈도우 검색창에 &#39;서비스&#39;를 검색하고, 해당 DB를 찾아보면 실행 여부를 알 수 있다.</p>
<p><strong>2. 드라이버 매니저를 통해 특정 DB에 접속 객체 생성</strong></p>
<pre><code class="language-java">    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(&quot;jdbc:oracle:thin:@127.0.0.1:1521:xe&quot;,&quot;ora01&quot;,&quot;oracle_4U&quot;);
    }</code></pre>
<ul>
<li>ip : oracle 설치 ip</li>
<li>db 종류 : oracle</li>
<li>id/pw : 각각 2,3번째 파라미터 값</li>
</ul>
<p><strong>3. sql문장이 실행 가능한 객체 생성</strong></p>
<pre><code class="language-java">    Statement stmt = null;
    stmt = con.createStatement(); //oracle db에 접속된
                      //Connection객체로 부터 획득</code></pre>
<p><strong>4. sql문장 실행 (메소드 호출)</strong></p>
<pre><code class="language-java">    ResultSet rset = null;
    rset = stmt.executeQuery(&quot;select * from dept&quot;);</code></pre>
<p><strong>5. 결과 활용</strong></p>
<pre><code class="language-java">    while(rset.next()) {
        System.out.println(rset.getInt(&quot;deptno&quot;) + &quot;/&quot; 
                   + rset.getString(&quot;dname&quot;) + &quot;/&quot; 
                   + rset.getString(&quot;loc&quot;));
    }</code></pre>
<p><strong>6. 자원 반환</strong></p>
<pre><code class="language-java">public void close(Connection con, Statement stmt, ResultSet rset) {
    try {
        if (rset != null) {
            rset.close();
            rset = null;
        }
        if (stmt != null) {
            stmt.close();
            stmt = null;
        }
        if (con != null) {
            con.close();
            con = null;
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

public void close(Connection con, Statement stmt) {
    try {
         if (stmt != null) {
                    stmt.close();
                 stmt = null;
         }
         if (con != null) {
                 con.close();
                 con = null;
         }
    } catch (SQLException e) {
         e.printStackTrace();
    }
}</code></pre>
<p>❗❗ 자원 반환 순서 매우 중요 ❗❗ </p>
<blockquote>
<p>ResultSet → Statment → Connection</p>
</blockquote>
<h3 id="🟡-dept-table-crud작업">🟡 dept table crud작업</h3>
<ul>
<li>deleteOne()</li>
</ul>
<pre><code class="language-java">public void deleteOne() {
    Connection con = null;
    Statement stmt = null;

    try {
        con = getConnection();
        stmt = con.createStatement();

        int result = stmt.executeUpdate
                 (&quot;DELETE FROM dept WHERE deptno=60&quot;);

        if (result == 1) {
            System.out.println(&quot;삭제 성공&quot;);
        } else {
            System.out.println(&quot;삭제 실패&quot;);
        }

        if (stmt != null) {
            stmt.close();
            stmt = null;
        }
        if (con != null) {
            con.close();
            con = null;
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}</code></pre>
<ul>
<li>updateOne()</li>
</ul>
<pre><code class="language-java">public void updateOne() {
    Connection con = null;
    Statement stmt = null;

    try {
        con = getConnection();
        stmt = con.createStatement();

        //executeUpdate : insert/update/delete sql문장 처리 메소드
        int result = stmt.executeUpdate
                (&quot;UPDATE DEPT SET loc=&#39;평양&#39; WHERE deptno=60&quot;);

        if (result == 1) {
            System.out.println(&quot;수정 성공&quot;);
        } else {
            System.out.println(&quot;수정 실패&quot;);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(con, stmt);
    }
}</code></pre>
<ul>
<li>inserOne()</li>
</ul>
<pre><code class="language-java">public void insertOne() {
    Connection con = null;
    Statement stmt = null;

    try {
        con = getConnection();
        stmt = con.createStatement();

        //executeUpdate : insert/update/delete sql문장 처리 메소드
        int result = stmt.executeUpdate(&quot;insert into dept values 
                        (60, &#39;교육부&#39;, &#39;남부&#39;)&quot;);

        if (result == 1) {
            System.out.println(&quot;저장 성공&quot;);
        } else {
            System.out.println(&quot;deptno 중복 저장 불허&quot;);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(con, stmt, null);
}</code></pre>
<ul>
<li>selectOne()</li>
</ul>
<pre><code class="language-java">public void selectOne() {
    Connection con = null;
    Statement stmt = null;
    ResultSet rset = null;
    try {
        con = getConnection();
        stmt = con.createStatement();
        rset = stmt.executeQuery(&quot;select * from dept where 
                      deptno=10&quot;);

        if(rset.next()) { 
            System.out.println(rset.getInt(&quot;deptno&quot;) + &quot;/&quot; 
                              + rset.getString(&quot;dname&quot;) + &quot;/&quot; 
                      + rset.getString(&quot;loc&quot;));
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(con, stmt, rset);
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue.js] Component와 PROPS, EMIT]]></title>
            <link>https://velog.io/@bingbong-party/Vue.js-Component%EC%99%80-PROPS-EMIT</link>
            <guid>https://velog.io/@bingbong-party/Vue.js-Component%EC%99%80-PROPS-EMIT</guid>
            <pubDate>Wed, 29 Sep 2021 12:49:58 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-component란">🍋 Component란?</h2>
<p>component는 기본 HTML element를 확장하여 재사용 할 수 있게 하는 &#39;캡슐화&#39;를 돕는다. Vue component는 Vue instance이기도 하며, 모든 옵션 객체 사용이 가능하다. (루트에만 사용하는 옵션은 제외한다.) </p>
<hr>
<h3 id="🟡-component의-전역-로컬-등록">🟡 Component의 전역, 로컬 등록</h3>
<ul>
<li>전역 등록</li>
</ul>
<pre><code class="language-jsx">Vue.component(&#39;my-component&#39;, {
  // 옵션
})</code></pre>
<ul>
<li>로컬 등록</li>
</ul>
<pre><code class="language-jsx">new Vue({
  // ...
  components: {
    // &lt;my-component&gt; 는 상위 템플릿에서만 사용할 수 있다.
    &#39;my-component&#39;: Child
  }
})</code></pre>
<p>위와 같이 컴포넌트가 등록된 이후에는 커스텀 엘리먼트로 사용할 수 있다.</p>
<pre><code class="language-jsx">&lt;div id=&quot;example&quot;&gt;
  &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;</code></pre>
<hr>
<h2 id="🍋-component간-데이터-전달--props-emit">🍋 Component간 데이터 전달 : PROPS, EMIT</h2>
<p>분리된 상태의 부모, 자식 컴포넌트간에 긴밀히 소통해야할 때가 있는데, 이 때 필요한 것이 component통신, 즉 props와 emit이다.</p>
<p><img src="https://user-images.githubusercontent.com/85170623/135270838-262f4364-5d17-497d-aebb-2377a3fd8982.png" alt="Untitled"></p>
<h3 id="🟡-props">🟡 PROPS</h3>
<p>부모에서 자식으로 데이터를 전달하기 위해 사용</p>
<ul>
<li>사용 예시</li>
</ul>
<pre><code class="language-html">&lt;!-- 상위 component template --&gt;
&lt;div id=&quot;app3&quot;&gt;
  &lt;btn-com3 v-bind:msg=&quot;m&quot;&gt;&lt;/btn-com3&gt;
&lt;/div&gt;

&lt;script&gt;
  &lt;!-- 하위 component --&gt;
  Vue.component(&quot;btn-com3&quot;, {
      template: &#39;&lt;button&gt;{{msg}}&lt;/button&gt;&#39;,
      props: [&#39;msg&#39;]
  })

  new Vue({
      el: &quot;#app3&quot;, 
      data: {
          m: &quot;빙봉빙봉&quot;,
          n: &quot;zyanzyan&quot;
      }
  });
&lt;/script&gt;</code></pre>
<blockquote>
<p>🚨 <strong>props는 반드시 배열로 받아야 함에 주의한다.</strong> 🚨</p>
</blockquote>
<hr>
<h3 id="🟡-emits">🟡 EMITS</h3>
<p>자식이 부모에게 데이터를 전달하기 위해서 <strong>이벤트를 발생</strong>시키는 것</p>
<ul>
<li>사용 예시</li>
</ul>
<pre><code class="language-html">&lt;div id=&quot;app5&quot;&gt;
  &lt;child-com v-on:event-data1=&quot;viewData&quot;&gt;&lt;/child-com&gt;
  &lt;child-com v-on:event-data2=&quot;viewData&quot;&gt;&lt;/child-com&gt;
  &lt;child-com v-on:event-data2=&quot;viewData2&quot;&gt;&lt;/child-com&gt;
  &lt;span&gt;{{msg}}&lt;/span&gt; - {{myname}}
&lt;/div&gt;

&lt;script&gt;
  Vue.component(&#39;child-com&#39;, {
      template: &#39;&lt;button v-on:click=&quot;showLog&quot;&gt;데이터 보기&lt;/button&gt;&#39;,
      methods: {
          showLog: function() {
          //$emit(key, 전송데이터)
          //key는 사용자정의 tag의 속성명으로 사용
          this.$emit(&#39;event-data1&#39;, &#39;자식이 부모에게 공유한 데이터&#39;);
          this.$emit(&#39;event-data2&#39;, &#39;하하 졸리다 &#39;);
          }
      }
  })

  new Vue({
      el: &quot;#app5&quot;,
      data: {
          msg: &quot;msg&quot;,
          myname: &quot;myname&quot;
      },
      methods: {
      //자식이 전송하는 데이터를 받기 위한 parameter선언 
          viewData: function(v) {
         this.msg = v;
          },
          viewData2: function(v) {
          this.myname = this.myname + v;
          }
      }
  })
&lt;/script&gt;</code></pre>
<p><em>참고 <a href="https://im-designloper.tistory.com/16">https://im-designloper.tistory.com/16</a></em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tech]]></title>
            <link>https://velog.io/@bingbong-party/Tech</link>
            <guid>https://velog.io/@bingbong-party/Tech</guid>
            <pubDate>Wed, 15 Sep 2021 10:57:27 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Web]]></title>
            <link>https://velog.io/@bingbong-party/Web</link>
            <guid>https://velog.io/@bingbong-party/Web</guid>
            <pubDate>Wed, 15 Sep 2021 10:56:50 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[[Ajax] Ajax]]></title>
            <link>https://velog.io/@bingbong-party/Ajax-Ajax</link>
            <guid>https://velog.io/@bingbong-party/Ajax-Ajax</guid>
            <pubDate>Wed, 15 Sep 2021 10:52:52 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-ajax">🍋 Ajax</h2>
<p>Ajax란 Asynchronous JavaScript and XML의 약자이다. XML이 풀네임(?)에 포함되어있으나, 실제로는 거의 이용하지 않는다고 한다. 나 또한 실습 때 JSON을 이용했다.</p>
<p>이러한 Ajax는 웹 페이지 전체를 다시 로딩하지 않고도 일부분만 갱신하는 것을 가능하게 한다. 즉, 백그라운드 영역에서 서버와 통신하여 그 결과를 웹페이지의 일부분에만 표시할 수 있는 것이다. 서버와는 아래의 다양한 형태의 데이터를 주고받을 수 있다.</p>
<ul>
<li>JSON</li>
<li>XML</li>
<li>HTML</li>
<li>TXT</li>
</ul>
<p>웹 페이지 전체를 리로딩하지 않고, 일부분만 갱신한다는 것에 대해 조금 더 자세히 생각해보자. 기본적으로 HTTP프로토콜은 클라이언트가 request를 하고, 서버에서 response하게 되는데, 이 때 이어져있던 연결이 끊긴다. 따라서 새롭게 화면을 갱신하기 위해서는 request와 response를 반복해야 한다. 이는 엄청난 자원낭비와 시간낭비를 초래한다. </p>
<p>그에 반해 Ajax는 서버에서 데이터를 받아올 때 XMLHttpRequest 객체를 통해 request를 수행하여 필요한 데이터만 받아 페이지의 일부를 갱신한다. </p>
<hr>
<h3 id="🟡-xmlhttprequest를-이용한-ajax구현">🟡 XMLHttpRequest를 이용한 Ajax구현</h3>
<p><strong>1. XMLHttpRequest 객체 생성</strong></p>
<pre><code class="language-jsx">const xhttp = new XMLHttpRequest();</code></pre>
<ul>
<li>IE를 제외한 브라우저는 기본적으로 XMLHttpRequest 객체를 지원한다.</li>
</ul>
<p><strong>2. 웹 서버에 요청 전송하기</strong></p>
<pre><code class="language-jsx">//get방식으로 ajaxRes.jsp에게 요청을 &quot;설정&quot;
xhttp.open(&quot;GET&quot;, &quot;ajaxRes.jsp&quot;);

//get방식으로 ajaxRes.jsp에게 요청을 &quot;수행&quot;
xhttp.send();</code></pre>
<ul>
<li><p><strong>open()  - 요청 초기화</strong></p>
<p>  1) 첫 번째 인자 : GET, POST, HEAD중 하나의 방식을 넣는다.</p>
<p>  2) 두 번째 인자 : 접속할 URL입력. 보안상(동일출처원칙)에 의해 현재 페이지와 같은 도메인에 있어야 한다.</p>
<p>  3) 세 번째 인자 : 동기/비동기 방식 설정(true일 경우 비동기)</p>
</li>
<li><p><strong>send() - 요청 실행</strong></p>
<p>  1) GET방식으로 요구한 경우 파라미터가 없어도 된다.</p>
<p>  2) POST방식으로 요구한 경우 서버로 보내고 싶은 어떠한 데이터라도 가능하다. 다만 데이터는 서버에서 쉽게 parse할 수 있는 형식(format)이어야 하거나 JSON, SOAP 등과 같은 다른 형식으로도 가능하다.</p>
</li>
</ul>
<p><strong>3. 서버 응답 처리하기</strong></p>
<pre><code class="language-jsx">xhttp.onreadystatechange = function() {
  if (this.readyState == 4 &amp;&amp; this.status == 200) {
    let data = this.responseText;
    document.getElementById(&quot;div1&quot;).innerHTML = data;
  }
};</code></pre>
<ul>
<li><p>서버로부터 응답을 받았으면, 알맞게 처리한다.</p>
</li>
<li><p>onreadystatechange</p>
<p>  서버로부터 응답이 도착하면 호출될 함수를 지정</p>
</li>
</ul>
<p><strong>4. XMLHttpRequest 객체의 상태</strong></p>
<ul>
<li><p>readyState</p>
<p>  <em>readyState  Holds the status of the XMLHttpRequest.</em></p>
<p>  <strong>0</strong> : request not initialized / 객체만 생성되고 아직 초기화되지 않은 상태, open() 메서드가 호출되지 않았음</p>
<p>  <strong>1</strong> : server connection established / open() 메서드가 호출되고 아직 send() 메서드가 호출되지 않은 상태</p>
<p>  <strong>2</strong> : request received / send() 메서드가 호출되었지만 STATUS와 헤더는 도착하지 않은 상태</p>
<p>  <strong>3</strong> : processing request / 데이터의 일부를 받은 상태</p>
<p>  <strong>4</strong> : request finished and response is ready / 데이터를 전부 받은 상태</p>
<p>  보통은 readyState값이 4인 경우만 원하는 기능을 수행하지만, 가끔 시간이 오래 걸리는 작업일 경우 아래의 예제 코드와 같이 나머지 값을 유용하게 사용할 수 있다.</p>
</li>
</ul>
<pre><code class="language-jsx">function callbackFunction(){
  if(httpRequest.readyState == 1  ||  httpRequest.readyState == 2
           || httpRequest.readyState ==3 ){
                           //화면에 작업 중 메시지 출력
          }else if(httpRequest.readyState == 4){
               if(httpRequest.status == 200){
                       //서버 응답 결과에 따라 알맞은 작업 처리
               }else{
                   alert(&quot;문제 발생:&quot; + httpRequest.status);
               }
          }
    }</code></pre>
<p><strong>5. 서버로부터의 응답 상태</strong></p>
<ul>
<li><p>status</p>
<p>  200 : OK / 요청 성공</p>
<p>  403 : Forbidden / 접근 거부</p>
<p>  404 : Not Found / 페이지 없음</p>
<p>  500 : Internal Server Error / 서버 오류</p>
</li>
</ul>
<p><strong>6. 응답 데이터 사용하기</strong></p>
<ul>
<li><p>responseText</p>
<p>  서버 응답에 따른 확인 사항 처리 후, (readyState == 4 &amp;&amp; status == 200) 이상이 없다면 서버가 전송한 데이터를 사용해야 한다.</p>
<p>  위의 코드3을 참고하자. </p>
</li>
</ul>
<p><strong>7. XMLHttpRequest 객체를 사용하는 Ajax의 전체적인 통신 과정</strong></p>
<pre><code class="language-jsx">function loadDoc() {
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 &amp;&amp; this.status == 200) {
      let data = this.responseText;
      alert(data);
      document.getElementById(&quot;div1&quot;).innerHTML = data;
    }
  };

  //get방식으로 ajaxRes.jsp에게 요청을 &quot;설정&quot;
  xhttp.open(&quot;GET&quot;, &quot;ajaxRes.jsp&quot;);

  //get방식으로 ajaxRes.jsp에게 요청을 &quot;수행&quot;
  xhttp.send();
}</code></pre>
<p>1) 사용자의 이벤트가 발생하면 이벤트 처리 함수를 호출한다(AJax를 구현해놓은).</p>
<p>2) 이벤트 처리 함수에서는 XMLHttpRequest 객체의 send() 메서드를 호출한다.</p>
<p>3) XMLHttpRequest 객체의 send() 메서드가 호출되면 웹 서버에 요청이 전송된다.</p>
<p>4) 웹 서버는 알맞게 처리한 뒤 응답 결과를 XMLHttpRequest에 전송한다.</p>
<p>5) XMLHttpRequest 객체에 응답이 도착하면 onreadystatechange 프로퍼티를 통해 지정한 콜백 함수를 호출한다.</p>
<p>6) 콜백 함수 내에서 서버 측이 응답이 올바른 것인지 readyState 프로퍼티와 status 프로퍼티를 통해 판단한다.</p>
<p>7) 이상이 없으면 서버 응답 데이터를 responseText 프로퍼티를 사용하여 처리한다.</p>
<p>참고 : <a href="https://myeonguni.tistory.com/m/1526">https://myeonguni.tistory.com/m/1526</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Project]]></title>
            <link>https://velog.io/@bingbong-party/Project</link>
            <guid>https://velog.io/@bingbong-party/Project</guid>
            <pubDate>Tue, 14 Sep 2021 14:48:12 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[[Project 후기] 후기적후기적 커뮤니티]]></title>
            <link>https://velog.io/@bingbong-party/Project-%ED%9B%84%EA%B8%B0%EC%A0%81%ED%9B%84%EA%B8%B0%EC%A0%81</link>
            <guid>https://velog.io/@bingbong-party/Project-%ED%9B%84%EA%B8%B0%EC%A0%81%ED%9B%84%EA%B8%B0%EC%A0%81</guid>
            <pubDate>Tue, 14 Sep 2021 14:42:35 GMT</pubDate>
            <description><![CDATA[<h2 id="후기적-후기적--세상-모든-것의-후기가-있는-커뮤니티"><strong>후기적 후기적 : 세상 모든 것의 후기가 있는 커뮤니티</strong></h2>
<p>후기적후기적 커뮤니티는 나의 첫 웹 프로젝트다.
게시글을 작성하고, 수정하고, 삭제하는 것이 가능한 어찌 보면 평범한 커뮤니티지만, 이번 프로젝트를 진행하며 내가 너무나도 당연하게 여겼던 기존의 기능들을 직접 구현하기란 절대 쉽지 않다는 것을 뼈저리게 느낄 수 있었다. 정말 값졌던 시간.</p>
<Br>

<p><strong>📜 개발 환경과 언어</strong></p>
<p><code>HTML</code> <code>CSS</code> <code>JSP</code> <code>JPQL</code> <code>LOMBOK</code> <code>JAVA</code> <code>JPA</code> <code>JSTL</code></p>
<blockquote>
<p>이번 프로젝트를 통해 JSP, JPA를 조금 더 deep하게 review할 수 있었다. 또, &#39;로그인정보 유지&#39;를 구현하기 위한 노력의 과정에서 <code>session</code>에 대해 더 많은 공부를 하기도 했다. 회원 자신이 작성한 게시글만 수정, 삭제할 수 있도록 처리하기 위한 필수적인 과정이었다.</p>
</blockquote>
<p><strong>🔑 깃허브 바로가기</strong>
<a href="https://github.com/yyhhha/review-world">GitHub - yyhhha/review-world</a></p>
<p><strong>📝 노션 바로가기</strong>
<a href="https://peapeago.notion.site/3158ea6ac9d7493eb3168067d3443e4c">Notion - 후기적후기적 : 세상 모든 후기모음</a>
<br></p>
<h2 id="📚-db">📚 <strong>DB</strong></h2>
<p><img src="https://user-images.githubusercontent.com/85170623/133267249-2aaa7009-3c4f-4af9-8ce9-ccb44521dbfc.png" alt="Untitled"></p>
<p><strong>1. 회원이 탈퇴할 경우에도, 작성한 게시글은 DB에 남아있음.</strong>
    &nbsp;&nbsp;&nbsp;&nbsp;작성자 명을 &quot;익명&quot; 으로 수정 후 활용
<strong>2. 게시글이 삭제되면 댓글도 삭제됨</strong>
    &nbsp;&nbsp;&nbsp;&nbsp;댓글이 삭제되어도 게시글은 유지</p>
<blockquote>
<ul>
<li>모든 OneToMany 관계는 단방향으로 이루어져있다. 오직 <code>R_BOARD</code>만이 다른 entity들을 참조한다. (FK)</li>
</ul>
</blockquote>
<ul>
<li>회원이 탈퇴하더라도 그들이 과거에 작성한 게시글들은 DB에 존재할 수 있게끔 하고싶었기 때문에 <code>R_USER</code>가 삭제되더라도 자식 table인 <code>R_BOARD</code>에 영향이 없게끔 <code>USER_ID</code>를 <code>null</code>값으로 처리했는데, 덕분에 게시글 자체는 여전히 DB에 남아있을 수 있었다.
<strong>하지만</strong> 이로 인해 <code>USER_ID</code>를 통한 게시글(<code>R_BOARD</code>)조회에 어려움을 겪었다. 회원 탈퇴 후에도 DB는 남겨놓는 것이 어떻냐는 피드백도 받기도 했는데, 현재 실제로 서비스 중인 커뮤니티에서는 이러한 문제를 어떠한 방식으로 처리하고 있는지 궁금해졌다. 탈퇴한 회원의 정보까지 영구적으로 보존하면 개인정보와 관련한 이슈가 존재하지 않을까..?</li>
</ul>
<hr>
<h2 id="🚫-우리가-만난-에러사항">🚫 우리가 만난 에러사항</h2>
<ul>
<li><p><strong>게시글작성시 발생하는 에러</strong></p>
<p>  → 게시글의 제목, 내용의 길이가 길어질 경우 에러 발생</p>
<p>  ⇒ <code>ALTER</code>를 통해 수정</p>
<p>  <code>ALTER TABLE R_BOARD MODIFY TITLE VARCHAR2(200)</code></p>
</li>
<li><p><strong>데이터 추가 시, default값을 가진 컬럼의 데이터가 자동으로 추가되지 않는 에러</strong></p>
<p>  ⇒ <code>@DynamicInsert</code>를 사용하여 해결 : 해당 어노테이션 사용 시 dafault값 자동 삽입</p>
<pre><code class="language-java">  @NoArgsConstructor
  @AllArgsConstructor
  @Getter
  @Setter
  @Builder
  @DynamicInsert
  @Entity
  @Table(name=&quot;R_BOARD&quot;)
  @SequenceGenerator(name=&quot;boardId_seq_gen&quot;, sequenceName=&quot;BOARD_ID_seq&quot;, initialValue=1, allocationSize=1)
  public class RBoard {
      @Id
      @Column(name = &quot;BOARD_ID&quot;)
      @GeneratedValue(strategy=GenerationType.SEQUENCE, generator=&quot;boardId_seq_gen&quot;)
      private int boardId; 

      private String title;
      private String content;

      @Column(name = &quot;BOARD_DATE&quot;)
      private String boardDate;

      private int views; 
      private int likes;

</code></pre>
</li>
</ul>
<pre><code>    @ManyToOne
    @JoinColumn(name = &quot;CATEGORY_ID&quot;)
    private RCategory category;

    @ManyToOne
    @JoinColumn(name = &quot;USER_ID&quot;)
    private RUser userId;

    }
```</code></pre><ul>
<li><p><strong>image파일이 깨지는 에러</strong></p>
<p>  → 여러 페이지에서 쓰이는 image파일을 <code>nav.jsp</code>파일 하나에서 관리하는데, 각 페이지들의 경로가 다르기 때문에 image파일을 제대로 불러오지 못하는 에러 발생 (경로문제)</p>
<p>  → 절대경로를 통해 해결 시도하였으나 해결하지 못함</p>
<p>  ⇒ 타 사이트에 저장된 이미지 주소값으로 설정하여 일시적으로 해결한 상태</p>
</li>
<li><p><strong><code>resultlist.add()</code> 관련 에러</strong></p>
<p>  → 탈퇴한 회원이 add되면 리스트 출력에 에러가 발생함</p>
<p>  ⇒ null처리되는 값은 <code>userId</code>와 <code>nickName</code>이다. 이 두 값이 null일 경우 &quot;익명&quot; 으로 값을 변경하도록 설정 (즉, 탈퇴한 회원의 게시글의 글쓴이는 &quot;익명&quot; 으로 넘어가도록 SET)</p>
<p><strong>변경 전</strong></p>
<pre><code class="language-java">  for (RBoard board : list) {
    resultList.add(new BoardDTO(board.getBoardId(), board.getTitle(), board.getContent(),
                    board.getBoardDate(), board.getViews(), board.getLikes(),
                    board.getCategory().getCategoryName(), board.getUserId().getNickName(), 
                    board.getUserId().getUserId(), board.getCategory().getCategoryId()));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return resultList;
    }</code></pre>
<p><strong>변경 후</strong></p>
<pre><code class="language-java">if(user == null) { 
    resultList.add(new BoardDTO(board.getBoardId(),board.getTitle(), board.getContent(),
              board.getBoardDate(), board.getViews(),board.getLikes(),
                    category.getCategoryName(),&quot;익명&quot;, &quot;익명&quot;,
                    board.getCategory().getCategoryId())); 
} else {
    resultList.add(new BoardDTO(board.getBoardId(), board.getTitle(), board.getContent(),
              board.getBoardDate(), board.getViews(), 
                    board.getLikes(), category.getCategoryName(),
              user.getNickName(), board.getUserId().getUserId(),
                    board.getCategory().getCategoryId()));
}

</code></pre>
</li>
</ul>
<ul>
<li>기타 에러사항<pre><code>- 응답이 이미 커밋된 후에는 forward될 수 없음
- 404 요청된 리소스가 가용하지 않습니다. -&gt; 경로문제 혹은 중복 servlet문제</code></pre>  응답이 이미 커밋된 후에는 forward 될 수 없음</li>
</ul>
<hr>
<h2 id="👨👧👧-동료">👨‍👧‍👧 동료</h2>
<p><strong>😄 박서은 :</strong> <a href="https://github.com/westsi1ver">https://github.com/westsi1ver</a></p>
<p><strong>😊 유영훈 :</strong> <a href="https://github.com/yyhhha">https://github.com/yyhhha</a></p>
<p><strong>😀 정은진 :</strong> <a href="https://github.com/bingbong-party">https://github.com/bingbong-party</a></p>
<blockquote>
<p>  코드에서 오타 찾아내기, 트러블 슈팅, 클린코드와 리팩토링에 대해 고민하기 등등..
  동료가 머리를 맞댈 때 더 빛을 발하는 것이 &#39;개발&#39;이라는 것을, 몸소 깨닫고 느끼는 요즈음이다.
  유연한 커뮤니케이션을 위한 고민과 노력을 꾸준히 이어가야겠다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Controller VS Service]]></title>
            <link>https://velog.io/@bingbong-party/Controller-VS-Service</link>
            <guid>https://velog.io/@bingbong-party/Controller-VS-Service</guid>
            <pubDate>Mon, 06 Sep 2021 15:21:02 GMT</pubDate>
            <description><![CDATA[<p>게시판 기능이 주가되는 사이트를 제작해보는 미니 프로젝트 진행 중, controller와 service는 왜 굳이 분리되어야 하며 각각의 쓰임이 어떻게 다른지에 대한 궁금증이 생겼다. </p>
<p><em>사실 MVC와 Service로 구성된 디자인 패턴의 프로그램은 다수 접해보았고, 관련한 프로젝트도 진행했었지만 프로그램이 실행되도록 만들기에 급급해서(나무에만 집중하느라) 숲을 보지 못했던 것 같다.</em></p>
<h2 id="🍋-controller-vs-service">🍋 Controller VS Service</h2>
<p>MVC 패턴의 구조는 service의 유무에 따라 아래와 같이 나뉜다.</p>
<ul>
<li><p>service가 없을 때</p>
<p>  M ↔ V ↔ C</p>
</li>
<li><p>service가 있을 때</p>
<p>  M ↔ S ↔ C ↔ V</p>
</li>
</ul>
<p>View는 service와 상관 없이 controller와 상호작용하는데, 이는 Service가 필요한 이유중 하나이다.</p>
<h3 id="🟡-controller">🟡 Controller</h3>
<ul>
<li>브라우저를 통해 사용자에게 데이터를 전달 받는다 (request or session)</li>
<li>전달 받은 데이터에 따라 알맞은 service를 호출한다</li>
<li>로직 실행 결과를 view로 연결한다 (response)</li>
</ul>
<h3 id="🟡-service">🟡 Service</h3>
<ul>
<li>controller에서 호출될 경우, 로직을 실행한다</li>
<li>DB가 필요할 경우 DAO을 호출하여 로직을 처리한다</li>
</ul>
<hr>
<p>service는 종속적이지 않고 독립적이라는 것이 특징이다. (위에서 언급했듯, view는 service와 관계 없이 controller와 연결되어있다)  이러한 특징은 service로 하여금 재사용이 용이하게 만들어준다. 즉, service에 의해 비지니스 로직의 재사용성이 높아진다는 의미다.</p>
<p>예시로, web으로 구현된 기능들을 app에서도 작동시켜야 하는데 이 경우 view에 변화가 생기게 되지만 service는 독립적이기 때문에 별다른 수정 없이 얼마든지 재사용이 가능하다. 변화에 대응하기 쉽고 확장성도 높은 로직인 것이다. 이를 보고 &#39;모듈화 되었다&#39;라고 표현하기도 한다.</p>
<p><strong>*ref</strong> <a href="https://velog.io/@2cong/MVC">https://velog.io/@2cong/MVC</a>*</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Servlet & JSP] Servelt]]></title>
            <link>https://velog.io/@bingbong-party/Servelt-JSP</link>
            <guid>https://velog.io/@bingbong-party/Servelt-JSP</guid>
            <pubDate>Mon, 30 Aug 2021 09:49:02 GMT</pubDate>
            <description><![CDATA[<h2 id="🍋-servlet">🍋 Servlet</h2>
<p>서블릿(servlet)은 클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet클래스의 구현 규칙을 시킨 자바 웹 프로그래밍 기술이다. </p>
<p>다른 말로는, 서버에서 웹페이지를 동적(혹은 정적까지도)으로 생성하거나 데이터 처리를 수행하기 위해 <strong>자바로 작성된 프로그램</strong>이라고 할 수 있다. 따라서 확장자는 .java이며, 해당 코드 안에 HTML태그가 삽입된다.</p>
<h3 id="🟡-servlet의-특징">🟡 servlet의 특징</h3>
<ul>
<li>클라이언트의 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트</li>
<li>html을 사용하여 요청에 응답</li>
<li>Java Thread를 이용하여 동작</li>
<li>MVC 패턴에서 Controller로 이용됨</li>
<li>HTTP 프로토콜 서비스를 지원하는 <code>javax.servlet.http.HttpServlet</code> 클래스를 상속받음</li>
<li>UDP보다 처리 속도가 느림</li>
<li>HTML 변경 시 servlet을 재컴파일해야함</li>
</ul>
<hr>
<h3 id="🟡-개발-시-알아-두어야-할-사항">🟡 개발 시 알아 두어야 할 사항</h3>
<ol>
<li><p><strong>브라우저 언어와 servlet, 또는 JSP만 직접 소통</strong></p>
<p> html / css / java script 는 절대 일반 순수 자바 클래스와 소통이 불가하다. </p>
<p> 즉, 웹 요청/응답 처리 시 servlet이나 JSP로 개발해야 한다.</p>
</li>
<li><p>이클립스에서의 웹 개발 구조</p>
<ul>
<li>src<ol>
<li><code>*.java</code> 개발</li>
<li>순수 DAO와 DTO 혹은 일반 모든 자바 소스 개발</li>
<li>web상에서 http기반으로 요청/응답을 직접 처리하는 <strong>servlet</strong></li>
</ol>
</li>
<li>WebContent<ol>
<li><code>.html</code> / <code>.css</code> / <code>.js</code>  / <code>.jsp</code> / 이미지, 동영상</li>
</ol>
</li>
</ul>
</li>
</ol>
<hr>
<h3 id="🟡-servlet-api">🟡 servlet API</h3>
<ol>
<li><p><strong><code>HttpServlet</code></strong></p>
<ul>
<li>http 프로토콜을 사용할 수 있도록 구현된 클래스</li>
<li>이를 상속받은 servlet은 재정의로만 쉽게 개발 가능</li>
</ul>
</li>
<li><p><strong><code>HttpServletRequest</code></strong></p>
<ul>
<li><p>http 프로토콜 기반으로 요청하는 client의 정보를 보유</p>
<p>  → 접속한 client의 ip, 브라우저 기본정보, client가 server에 전송하는 입력 데이터 등.. </p>
</li>
<li><p><code>doGet()</code> or <code>doPost()</code> 메소드 실행 시 parameter로 쓰임. 즉, 메소드 실행을 위해 필요한 client의 정보를 제공해주는 API</p>
</li>
</ul>
</li>
<li><p><strong><code>HttpServletResponse</code></strong></p>
<ul>
<li><p>http 프로토콜 기반으로 요청하는 client에게만 응답하는 처리 수행</p>
</li>
<li><p>응답 포멧 설정 가능</p>
<p>  → 속성지정 가능 (ex.한글로 응답하기 위한 속성 설정)</p>
<p>  → <code>setContentType()</code> : client 브라우저에 응답하는 포멧 + 인코딩 설정</p>
<p>  → <code>getWriter()</code> : 2byte출력이 가능하고, 사용 시 <code>PrintWriter</code> 객체를 생성해주어야 함.  (<code>PrintWriter</code>는 접속된 client에게만 출력)</p>
<p>  → <code>PrintWriter</code>는 2byte 단위로 출력됨</p>
</li>
<li><p>client 브라우저에 응답하는 객체</p>
</li>
</ul>
</li>
</ol>
<p>아래 코드처럼 작성하면 된다.</p>
<pre><code class="language-java">public class Servlet2Validation extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getParameter(&quot;id&quot;);
        String pw = request.getParameter(&quot;pw&quot;);

        System.out.println(&quot;id : &quot; + id + &quot; pw : &quot; + pw);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getParameter(&quot;id&quot;);
        String pw = request.getParameter(&quot;pw&quot;);
        System.out.println(&quot;id : &quot; + id + &quot; pw : &quot; + pw);
    }

}</code></pre>
<hr>
<h3 id="🟡-servlet-container">🟡 servlet container</h3>
<p>servlet container란 말 그대로 servlet을 관리해주는 container이다.</p>
<p>우리가 서버에 서블릿을 만들었다고 해서 스스로 작동하는 것이 아니고 서블릿을 관리해주는 것이 필요한데, 그러한 역할을 하는 것이 바로 서블릿 컨테이너이다. 서블릿 컨테이너는 클라이언트의 요청(Request)을 받아주고 응답(Response)할 수 있게, 웹서버와 소켓으로 통신하며 대표적인 예로 <strong>톰캣(Tomcat)</strong>이 있다. 톰캣은 실제로 웹 서버와 통신하여 JSP(자바 서버 페이지)와 Servlet이 작동하는 환경을 제공해준다.</p>
<p><em>출처 : <a href="https://mangkyu.tistory.com/14">https://mangkyu.tistory.com/14</a></em></p>
<hr>
<h3 id="🟡-servlet-lifecycle">🟡 servlet lifecycle</h3>
<p>servlet lifecycle은 servlet container에서 관리한다.</p>
<ol>
<li><strong>기본 생성자 (parameter가 없는 생성자)</strong><ul>
<li>최초 client가 호출시 실행돼서 객체 생성</li>
<li>새로운 로직의 갱신된 객체 생성시 단 한 번 생성 (갱신 직후 최초 client가 요청시 단 한 번 실행)</li>
</ul>
</li>
<li><strong><code>init()</code></strong><ul>
<li>생성자 호출 직후에 단 한 번 실행</li>
<li>공유 자원 초기화 로직으로 적합</li>
</ul>
</li>
<li><strong><code>doGet() / doPost()</code></strong><ul>
<li>client 요청 시 1:1 실행 (Java Thread를 이용하여 동작됨)</li>
<li>service 메소드라 표현</li>
</ul>
</li>
<li><strong><code>destroy()</code></strong><ul>
<li>갱신된 servlet bytecode가 서버 메모리에 로딩시 자동 호출</li>
<li>즉, 구버전 객체 메모리 해제시에 자동 실행</li>
<li>자원 반환용 로직 구현시 적합</li>
<li>서버 다운 직전에도 자동 호출됨</li>
</ul>
</li>
</ol>
<hr>
<h3 id="🟡-servlet-method">🟡 servlet method</h3>
<pre><code class="language-html">&lt;form action=&quot;idcheck&quot; method=&quot;post&quot;&gt;
    id 입력 from : &lt;input type=&quot;text&quot; name=&quot;id&quot;&gt; &lt;br&gt; 
    pw 입력 from : &lt;input type=&quot;password&quot; name=&quot;pw&quot;&gt; &lt;br&gt;
    &lt;input type=&quot;submit&quot; value=&quot;로그인&quot;&gt;
&lt;/form&gt;</code></pre>
<p>위 코드에서처럼, <code>&lt;from&gt;</code>태그에는 <code>method</code>속성을 정해줄 수 있다. 이 속성은 form data가 서버로 제출될 때 사용되는 HTTP 메소드를 명시한다. <code>method</code>의 속성으로는 아래 네 가지가 있다.</p>
<ol>
<li><strong><code>get</code></strong><ul>
<li>서버에 데이터 전송시 url에 전송되는 데이터가 오픈돼서 전송</li>
<li>보안 철저히 고려하지 않음</li>
<li>소량의 데이터 전송에 간혹 쓰임</li>
<li>즐겨찾기, 즉 webpage 구분용으로 사용 (url 상에 노출되니까)
예시 url : <a href="https://book.naver.com/bookdb/book_detail.nhn?bid=20743750">https://book.naver.com/bookdb/book_detail.nhn?bid=20743750</a></li>
<li>servlet은 <code>doGet()</code>으로 처리</li>
</ul>
</li>
<li><strong><code>post</code></strong><ul>
<li>우편물처럼 데이터를 봉투에 담아서 은닉해서 전송하는 것과 같은 원리</li>
<li>데이터 서버에 전송할 때 보안을 고려해서, 또는 데이터양이 많을 경우 사용되는 방식</li>
<li>servlet은 <code>doPost()</code>으로 처리</li>
</ul>
</li>
<li><strong><code>put</code></strong></li>
<li><strong><code>delete</code></strong></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA]]></title>
            <link>https://velog.io/@bingbong-party/JPA</link>
            <guid>https://velog.io/@bingbong-party/JPA</guid>
            <pubDate>Sun, 29 Aug 2021 08:38:10 GMT</pubDate>
            <description><![CDATA[<p>JPA 공부 기록</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Python]]></title>
            <link>https://velog.io/@bingbong-party/Python</link>
            <guid>https://velog.io/@bingbong-party/Python</guid>
            <pubDate>Sun, 29 Aug 2021 08:36:43 GMT</pubDate>
            <description><![CDATA[<p>공부 과정에서 새롭게 배운 Python 기록</p>
]]></description>
        </item>
    </channel>
</rss>