<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jiyoon9-velog.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요 :)</description>
        <lastBuildDate>Sat, 20 Apr 2024 05:28:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jiyoon9-velog.log</title>
            <url>https://velog.velcdn.com/images/jiyoon9-velog/profile/c93e3d74-cbb7-4ce7-b404-7d5352e56d1a/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jiyoon9-velog.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jiyoon9-velog" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Java] 인텔리제이 자주 쓰는 단축키]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-%EC%9D%B8%ED%85%94%EB%A6%AC%EC%A0%9C%EC%9D%B4-%EB%8B%A8%EC%B6%95%ED%82%A4</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-%EC%9D%B8%ED%85%94%EB%A6%AC%EC%A0%9C%EC%9D%B4-%EB%8B%A8%EC%B6%95%ED%82%A4</guid>
            <pubDate>Sat, 20 Apr 2024 05:28:33 GMT</pubDate>
            <description><![CDATA[<h4 id="계속-업데이트할-예정">계속 업데이트할 예정</h4>
<blockquote>
<p><strong><code>ALT + Insert</code></strong> Constructor, getter &amp; setter
<strong><code>sout</code></strong> System.out.println
<strong><code>main</code></strong> main 함수
<strong><code>Alt + F12</code></strong> 터미널 창 열기
<strong><code>Shift + F6</code></strong> 이름 일괄 변경
<strong><code>Ctrl + Space</code></strong> 주요 키워드 찾아서 자동 완성
<strong><code>Ctrl + O</code></strong> overriding
<strong><code>Ctrl + /</code></strong> 라인 단위 주석 처리 //
<strong><code>Ctrl + /</code></strong> 블록 단위 주석 처리 /* <em>/
*</em><code>Shift + Enter</code>** 커서 바로 아래 행에 라인 추가 및 이동
<strong><code>Ctrl + Shift + Space</code></strong> 스마트 자동완성
<strong><code>Shift + F10</code></strong> 프로젝트 실행</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] MyBatis]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-MyBatis</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-MyBatis</guid>
            <pubDate>Wed, 17 Apr 2024 00:19:16 GMT</pubDate>
            <description><![CDATA[<h2 id="1-mybatis">1. MyBatis</h2>
<ul>
<li>Database 연동을 도와주는 Framework<blockquote>
<p>💡 기존 바닐라 형태 JDBC는 연동 과정도 복잡하고, 반복적인 코드가 나오면서 SQL 문장이 자바 코드와 섞여 있어서 유지보수가 힘들다. 따라서 이런 점을 개선하여 편의성과 유지보수성을 높이기 위하 목적으로 사용된다.   </p>
</blockquote>
</li>
<li>Controller에서 Service를 호출하고 Service에서 DAO를 이용해서 Database를 처리할 때 DAO에서 MyBatis를 사용해서 Database 처리를 하게 된다.</li>
</ul>
<h3 id="11-mybatis-특징">1.1 MyBatis 특징</h3>
<ul>
<li>복잡한 JDBC 코드를 걷어내고 <strong><code>깔끔한 소스 코드</code></strong>를 유지할 수 있다.</li>
<li>SQL 실행 결과가 기본적으로 <strong><code>Map에 Mapping</code></strong> 된다.<ul>
<li>기본 JDBC는 ResultSet이라는 커서를 리턴 받아서 일반적으로 while을 돌면서 결과 처리를 하게 되는데, 이 과정이 생략되고 자동으로 결과 데이터가 HashMap에 저장된다. HashMap 뿐만 아니라 <strong><code>VO에도 저장이 가능</code></strong>하다.</li>
</ul>
</li>
<li>SQL 문장을 자바 소스 코드에서 분리해서 따로 <strong><code>XML 파일</code></strong>로 관리한다.</li>
<li>DataSource 기능과 Transaction 처리 기능을 제공한다.<ul>
<li>DataSource(Connection Pool)</li>
<li>Pool은 Resource를 모아놓은 저장소</li>
<li>Connection의 집합체 = Connection Pool
  <img src="https://velog.velcdn.com/images/jiyoon9-velog/post/f29271a6-f1d7-4ae2-9191-967d64b8d46b/image.png" alt=""></li>
</ul>
</li>
</ul>
<h2 id="2-mybatis-download--설정">2. MyBatis download &amp; 설정</h2>
<ul>
<li><a href="https://mybatis.org/mybatis-3/">https://mybatis.org/mybatis-3/</a></li>
<li>Configuration, Mapper DTD 등록</li>
</ul>
<blockquote>
<ul>
<li>Location : <a href="http://mybatis.org/dtd/mybatis-3-config.dtd">http://mybatis.org/dtd/mybatis-3-config.dtd</a></li>
<li>Key Type : Public ID (Default)</li>
<li>Key : -//mybatis.org/DTD Config 3.0//EN</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>Location : <a href="http://mybatis.org/dtd/mybatis-3-mapper.dtd">http://mybatis.org/dtd/mybatis-3-mapper.dtd</a></li>
<li>Key Type : Public ID (Default)</li>
<li>Key : -//mybatis.org/DTD Mapper 3.0//EN</li>
</ul>
</blockquote>
<h2 id="3-xmlsqlmapconfigxml파일-생성">3. XML(SqlMapConfig.xml)파일 생성</h2>
<ul>
<li><p>resources/SqlMapConfig.xml</p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE configuration
      PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;
      &quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;&gt;
&lt;configuration&gt;

  &lt;!-- driver properties 파일--&gt;
  &lt;properties resource=&quot;./driver.properties&quot; /&gt;

  &lt;!-- MyBatis setting에 대한 내용 --&gt;
  &lt;settings&gt;
      &lt;setting name=&quot;jdbcTypeForNull&quot; value=&quot;NULL&quot;/&gt;
      &lt;!-- 만약 MyBatis의 SQL Query(select)를 이용해서 처리했는데
      데이터베이스에서 가져온 내용이 없다면 Java 객체 NULL로 리턴한다. --&gt;
  &lt;/settings&gt;
  &lt;!-- Alias를 설정할 수 있다. 여기서 설정하는 Alias(별칭)은 오직 XML에서만 사용된다.
  단순히 타이핑을 줄이기 위한 용도로 사용된다. --&gt;
  &lt;typeAliases&gt;
      &lt;typeAlias alias=&quot;BookVO&quot; type=&quot;example.vo.BookVO&quot; /&gt;
  &lt;/typeAliases&gt;

  &lt;!-- Database 연결에 대한 설정
  일반적으로 개발용, 운영용처럼 여러 개의 환경을 설정해놓고
  상황에 맞게 이용하는 방식을 사용한다. --&gt;
  &lt;environments default=&quot;development&quot;&gt;
      &lt;environment id=&quot;development&quot;&gt;
          &lt;!-- transactionManager는 type이 2개가 있다.
           JDBC라고 쓰면 수동으로 transaction을 관리한다는 의미
           MANAGED라고 쓰면 Container가 TR을 관리한다는 의미 --&gt;
          &lt;transactionManager type=&quot;JDBC&quot;&gt;

          &lt;/transactionManager&gt;

          &lt;!-- dataSource 설정은 Connection Pool 설정하는 것이다.
          #{}이랑 ${}이랑 의미가 조금 다르다. --&gt;
          &lt;dataSource type=&quot;POOLED&quot;&gt;
              &lt;property name=&quot;driver&quot; value=&quot;${driver}&quot;/&gt;
              &lt;property name=&quot;url&quot; value=&quot;${url}&quot;/&gt;
              &lt;property name=&quot;username&quot; value=&quot;${username}&quot;/&gt;
              &lt;property name=&quot;password&quot; value=&quot;${password}&quot;/&gt;
          &lt;/dataSource&gt;
      &lt;/environment&gt;
  &lt;/environments&gt;

  &lt;!-- 사용할 Mapper에 대한 설정이 나온다. --&gt;
  &lt;mappers&gt;
      &lt;mapper resource=&quot;./sqlmap/Book.xml&quot; /&gt;
  &lt;/mappers&gt;
&lt;/configuration&gt;</code></pre>
</li>
<li><p>resources/sqlmap/Book.xml</p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE mapper
      PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;
      &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot; &gt;
&lt;mapper namespace=&quot;example.mybook&quot;&gt;
  &lt;select id=&quot;selectByISBNHashMap&quot; parameterType=&quot;String&quot; resultType=&quot;HashMap&quot;&gt;
      &lt;![CDATA[
      SELECT bisbn, btitle, bprice, bauthor
      FROM book
      WHERE bisbn = #{bisbn}
      ]]&gt;
  &lt;/select&gt;

  &lt;select id=&quot;selectByAllHashMap&quot; parameterType=&quot;String&quot; resultType=&quot;HashMap&quot;&gt;
      &lt;![CDATA[
      SELECT bisbn, btitle, bprice, bauthor
      FROM book
      ]]&gt;
  &lt;/select&gt;

  &lt;select id=&quot;selectByISBNBookVO&quot; parameterType=&quot;String&quot; resultType=&quot;BookVO&quot;&gt;
      &lt;![CDATA[
      SELECT bisbn, btitle, bprice, bauthor
      FROM book
      WHERE bisbn = #{bisbn}
      ]]&gt;
  &lt;/select&gt;

  &lt;resultMap id=&quot;result_1&quot; type=&quot;BookVO&quot;&gt;
      &lt;result property=&quot;bisbn&quot; column=&quot;my_isbn&quot; jdbcType=&quot;VARCHAR&quot; javaType=&quot;String&quot; /&gt;
      &lt;result property=&quot;btitle&quot; column=&quot;my_title&quot; /&gt;
      &lt;result property=&quot;bprice&quot; column=&quot;my_price&quot; /&gt;
      &lt;result property=&quot;bauthor&quot; column=&quot;my_author&quot; /&gt;
  &lt;/resultMap&gt;

  &lt;select id=&quot;selectByISBNResultMap&quot; parameterType=&quot;String&quot; resultMap=&quot;result_1&quot;&gt;
      &lt;![CDATA[
      SELECT bisbn AS my_isbn,
             btitle AS my_title,
             bprice AS my_price,
             bauthor AS my_author
      FROM book
      WHERE bisbn = #{bisbn}
      ]]&gt;
  &lt;/select&gt;

  &lt;update id=&quot;titleUpdate&quot; parameterType=&quot;BookVO&quot;&gt;
      &lt;![CDATA[
      UPDATE book
      SET btitle = #{btitle}
      WHERE bisbn = #{bisbn}
      ]]&gt;
  &lt;/update&gt;
&lt;/mapper&gt;</code></pre>
</li>
<li><p>resources/driver.properties</p>
<pre><code>driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/library?characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;useSSL=false&amp;allowPublicKeyRetrieval=true
username=root
password=****</code></pre></li>
<li><p>src/example/dao/BookDAO.java</p>
<pre><code class="language-java">package example.dao;
</code></pre>
</li>
</ul>
<p>import example.vo.BookVO;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;</p>
<p>import java.util.HashMap;
import java.util.List;</p>
<p>public class BookDAO {</p>
<pre><code>// 여기서 SqlSessionFactory를 직접 얻어내지 않는다.
// 생성자를 통해 주입받아서 사용한다.
private SqlSessionFactory sqlSessionFactory;

public BookDAO() {
}

// 생성자 주입 Constructor Injection
public BookDAO(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
}

// 1. ISBN 번호를 입력으로 받아서 책 1권의 데이터를 HashMap으로 만들어서 리턴하는 method를 작성해보자.
public HashMap&lt;String, Object&gt; selectByISBNHashMap(String bisbn) {

    HashMap&lt;String, Object&gt; result = null;
    SqlSession session = sqlSessionFactory.openSession();

    try {
        result = session.selectOne(&quot;example.mybook.selectByISBNHashMap&quot;, bisbn);
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        session.close();
    }
    return result;
}

// 2. 모든 책의 데이터를 HashMap의 List로 만들어서 리턴하는 method를 작성해보자.
public List&lt;HashMap&lt;String, Object&gt;&gt; selectByAllHashMap() {

    List&lt;HashMap&lt;String, Object&gt;&gt; result = null;
    SqlSession session = sqlSessionFactory.openSession();

    try {
        result = session.selectList(&quot;example.mybook.selectByAllHashMap&quot;);
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        session.close();
    }
    return result;
}

// 3. ISBN 번호를 입력으로 받아서 책 1권의 데이터를 BookVO로 만들어서 리턴하는 method를 작성해보자.
public BookVO selectByISBNBookVO(String bisbn) {

    BookVO result = null;
    SqlSession session = sqlSessionFactory.openSession();

    try {
        result = session.selectOne(&quot;example.mybook.selectByISBNBookVO&quot;, bisbn);
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        session.close();
    }
    return result;
}

// 4. ISBN 번호를 이용해서 책 1권의 정보를 BookVO로 변환해서 가져오기
// 그러나 table의 column명이 VO의 field명과 다른 경우 하는 방법
public BookVO selectByISBNResultMap(String bisbn) {

    BookVO result = null;
    SqlSession session = sqlSessionFactory.openSession();

    try {
        result = session.selectOne(&quot;example.mybook.selectByISBNBookVO&quot;, bisbn);
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        session.close();
    }
    return result;
}

// 5. ISBN 번호를 이용해서 책 1권의 정보를 변경하고 싶다.
// 책 제목을 바꿀 때
public int titleUpdate(BookVO bookVO) {

    int result = 0;
    SqlSession session = sqlSessionFactory.openSession();

    try {
        result = session.update(&quot;example.mybook.titleUpdate&quot;, bookVO);
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        session.commit(); // update 계열은 반드시 처리해야 한다. 하지 않으면 데이터베이스에 반영이 안된다.
        session.close();
    }
    return result;
}</code></pre><p>}</p>
<pre><code>
- src/example/mybatis/MyBatisConnectionFactory.java
```java
package example.mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.Reader;

public class MyBatisConnectionFactory {
    // 실제 프로그램에서 (DAO)에서 사용하는 데이터베이스 연결 객체는
    // 기존에는(JDBC)일 때는 Connection 객체를 이용했다.
    // MyBatis에서는 SqlSession이라는 객체를 이용한다.
    private static SqlSessionFactory sqlSessionFactory;

    // 이 Factory 객체는 해당 클래스로부터 객체가 1개만 만들어져서 사용되도록 처리할 것이다.
    // =&gt; Singleton으로 동작하게끔 만든다.
    static {
        try {
            String resource = &quot;./SqlMapConfig.xml&quot;;
            Reader reader = Resources.getResourceAsReader(resource);

            if (sqlSessionFactory == null) {
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

}</code></pre><ul>
<li>src/example/vo/BookVO.java<pre><code class="language-java">package example.vo;
</code></pre>
</li>
</ul>
<p>import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;</p>
<p>@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookVO {
    private String bisbn;
    private String btitle;
    private int bprice;
    private String bauthor;
}</p>
<pre><code>
- src/example/main.java
```java
package example;

import example.dao.BookDAO;
import example.mybatis.MyBatisConnectionFactory;
import example.vo.BookVO;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.HashMap;
import java.util.List;

public class Main {
    public static void main(String[] args) {

        // 데이터베이스 처리
        // DAO가 있어야 데이터베이스 처리를 할 수 있다.
        // DAO를 만들려면 SqlSessionFactory를 먼저 확보해야 이것을 주입해서 DAO를 만들 수 있다.
        SqlSessionFactory factory = MyBatisConnectionFactory.getSqlSessionFactory();
        BookDAO dao = new BookDAO(factory);

        // 1.
//        HashMap&lt;String, Object&gt; result = dao.selectByISBNHashMap(&quot;89-7914-274-9&quot;);
//
//        for (String key : result.keySet()) {
//                System.out.println(key + &quot; : &quot; + result.get(key));
//        }

        // 2.
//        List&lt;HashMap&lt;String, Object&gt;&gt; result = dao.selectByAllHashMap();
//        for(HashMap&lt;String, Object&gt; map : result) {
//            for (String key: map.keySet()) {
//                System.out.println(key + &quot; : &quot; + map.get(key));
//            }
//            System.out.println();
//        }

        // 3. ISBN 번호로 책 1권의 정보 BookVO로 변환
//        BookVO result = dao.selectByISBNBookVO(&quot;89-7914-274-9&quot;);
//        System.out.println(result);

        // 4. ISBN 번호를 이용해서 책 1권의 정보를 BookVO로 변환해서 가져오기
        // 그러나 table의 column명이 VO의 field명과 다른 경우 하는 방법
//        BookVO result = dao.selectByISBNResultMap(&quot;89-7914-274-9&quot;);
//        System.out.println(result);

        // 5. ISBN 번호를 이용해서 책 1권의 정보를 변경하고 싶다.
        // 책 제목을 바꿀 때
        BookVO bookVO = new BookVO(&quot;89-7914-274-9&quot;, &quot;나는 고수 프로그래머다.&quot;, 0, null);
        int result = dao.titleUpdate(bookVO);
        System.out.println(&quot;영향을 받은 행의 개수: &quot; + result);
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Lombok]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Lombok-yk8875zo</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Lombok-yk8875zo</guid>
            <pubDate>Tue, 16 Apr 2024 08:59:11 GMT</pubDate>
            <description><![CDATA[<h2 id="1-lombok">1. Lombok</h2>
<ul>
<li>자바 코드 다이어트 라이브러리</li>
<li>VO 작성 시 반복적인 getter, setter, 생성자, toString 재정의 같은 작업을 수행하게 되는데 이 작업을 조금 더 쉽게 할 수 있도록 도와준다.</li>
<li>코드 상에서는 당연히 Lombok의 annotation을 이용해서 처리하고, 컴파일되면 class 내에 해당 getter나 setter 등이 포함되는 구조</li>
</ul>
<h2 id="2-lombok-annotation">2. Lombok Annotation</h2>
<h3 id="21-getter-setter">2.1 @Getter, @Setter</h3>
<ul>
<li>getter, setter를 자동으로 만들어준다.</li>
</ul>
<h3 id="22-noargsconstructor">2.2 @NoArgsConstructor</h3>
<ul>
<li>인자를 가지지 않는 생성자를 자동으로 만들어준다.</li>
<li>default 생성자</li>
</ul>
<h3 id="23-allargsconstructor">2.3 @AllArgsConstructor</h3>
<ul>
<li>모든 private field를 인자로 가지는 생성자를 자동으로 만들어준다.</li>
</ul>
<h3 id="24-requiredargsconstructor">2.4 @RequiredArgsConstructor</h3>
<ul>
<li>생성자에 포함되는 인자를 내가 결정해서 생성자를 자동으로 만들어준다. @NonNull 이용</li>
</ul>
<h3 id="25-tostring">2.5 @ToString</h3>
<ul>
<li>객체의 내용을 문자열로 표현하기 위해 우리는 toString method를 overriding해서 사용하는데 이걸 자동으로 만들어준다.</li>
<li>이들 외에도 여러 가지 Annotation이 제공된다.</li>
</ul>
<h3 id="26-data">2.6 @Data</h3>
<ul>
<li>@Setter, @Getter, @RequiredArgsConstructor, @ToString을 포함하고 있는 Annotation</li>
<li>사용하지 않는 여러 생성자나 toString이 같이 포함될 수 있기 때문에 자원의 낭비(class 크기가 상대적으로 커진다.)가 발생할 여지가 있다. 그래서 이를 꺼려 하는 사용자도 있다.</li>
</ul>
<pre><code class="language-java">import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
public class BookVO {

    @NonNull
    private String bisbn;
    @NonNull
    private String btitle;
    private int bprice;
    private String bauthor;
}</code></pre>
<pre><code class="language-java">import lombok.*;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookVO {

    @NonNull
    private String bisbn;
    @NonNull
    private String btitle;
    private int bprice;
    private String bauthor;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] JDBC MVC Pattern]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-JDBC-MVC-Pattern</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-JDBC-MVC-Pattern</guid>
            <pubDate>Sat, 13 Apr 2024 05:42:32 GMT</pubDate>
            <description><![CDATA[<h2 id="1-layered-architecture">1. Layered Architecture</h2>
<ul>
<li>Layered Architecture는 소프트웨어 개발에서 일반적으로 널리 사용되는 아키텍처를 지칭하는 용어.</li>
<li>프로그램을 개발할 때 몇 개의 계층(Layer)를 이용할 지에 따라서 그 형태가 달라지는 데 일반적으로 많이 사용하는 것은 4계층이다. (4-Tier Architecture)</li>
<li>객체지향적 개념으로 보자면 관심사의 분리(Seperation of Concern)와 동일한 개념이라고 생각하면 된다.</li>
<li>Layered Architecture는 소프트웨어 시스템을 여러 개의 논리적인 계층으로 나누어 구조화하는 방법론.</li>
<li>각 계층은 특정한 역할을 수행하며, 시스템을 유연하고 유지보수가 용이하도록 만든다.</li>
<li>각 계층은 서로 분리되어 있어, 한 계층의 변경이 다른 계층에 미치는 영향을 최소화한다.</li>
<li>이렇게 각 계층은 자신의 역할에 집중하며, 시스템을 구조화하여 유지보수와 확장을 용이하게 한다.</li>
<li>변경이 필요한 경우 한 계층만 수정하면 되므로 시스템의 유연성이 향상된다.
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/00b23447-cb84-43fb-8529-6482eefca348/image.png" alt=""></li>
<li>Presentation Layer : 사용자 인터페이스(UI), HTML, CSS, JavaScript<ul>
<li>화면을 만들어주는 Class ⇒ View 라고 한다.</li>
</ul>
</li>
<li>Business Layer : 비즈니스 로직을 처리하고, 시스템의 핵심 기능을 구현, 주문을 처리하거나 계산을 수행하는 등의 작업 (데이터를 이용해서 로직을 수행, 단, DB 처리 제외)<ul>
<li>Service(실제 로직을 담당하는 객체), (Domain) Model이라고 하는 데이터 객체가 포함된다. (VO)</li>
</ul>
</li>
<li>Persistence Layer : 데이터의 영구적인 저장과 관리 담당, 데이터베이스와의 상호작용을 처리하고, 데이터를 저장하거나 불러오는 등의 작업, CRUD<ul>
<li>데이터베이스를 핸들링하는 객체(DAO - Data Access Object)</li>
</ul>
</li>
<li>Database Layer : 실제 데이터를 저장하고 관리, 데이터베이스 관리 시스템(DBMS)<ul>
<li>MySQL, Oracle</li>
</ul>
</li>
</ul>
<h2 id="2-mvc-pattern">2. MVC Pattern</h2>
<ul>
<li>MVC는 소프트웨어 시스템을 3가지 타입의 component로 분할해서 개발하는 소프트웨어 개발 패턴.</li>
<li>Model(M) - Service (Model), Domain Model(VO)</li>
<li>View(V) - 사용자 interface 담당</li>
<li>Controller(C) - 시스템 흐름제어(View와 Service 간의 Bridge)</li>
</ul>
<h2 id="3-도서-검색-프로그램을-mvc-형태로-구현">3. 도서 검색 프로그램을 MVC 형태로 구현</h2>
<ul>
<li>View : Class 하나 이용해서 화면 처리를 해야 한다. FXML로 처리한다.</li>
<li>booksearch.controller.BookSearchController.java</li>
</ul>
<pre><code class="language-java">package booksearch.controller;

import booksearch.service.BookSearchService;
import booksearch.vo.BookVO;
import javafx.beans.Observable;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;

import java.net.URL;
import java.util.ResourceBundle;

public class BookSearchController implements Initializable {

    @FXML private TextField textField;
    @FXML private Button searchBtn;
    @FXML private Button deleteBtn;
    @FXML private TableView tableView;

    @FXML private TableColumn&lt;BookVO, String&gt; isbn;
    @FXML private TableColumn&lt;BookVO, String&gt; title;
    @FXML private TableColumn&lt;BookVO, Integer&gt; price;
    @FXML private TableColumn&lt;BookVO, String&gt; author;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

        isbn.setCellValueFactory(new PropertyValueFactory&lt;&gt;(&quot;bisbn&quot;));
        title.setCellValueFactory(new PropertyValueFactory&lt;&gt;(&quot;btitle&quot;));
        price.setCellValueFactory(new PropertyValueFactory&lt;&gt;(&quot;bprice&quot;));
        author.setCellValueFactory(new PropertyValueFactory&lt;&gt;(&quot;bauthor&quot;));

        searchBtn.setOnAction(e -&gt; {
            // 검색 버튼을 눌렀을 때 해야 하는 작업
            // 실제 로직 처리는 Controller가 하지 않는다.
            // 로직 객체를 따로 만들어서 사용해야 한다.
            // 서비스 객체가 필요하다.
            BookSearchService service = new BookSearchService();

            // 해당 객체를 통해 비즈니스 수행
            String keyword = textField.getText();
            ObservableList&lt;BookVO&gt; data = service.searchBookByKeyword(keyword);
            tableView.setItems(data);
        });

        deleteBtn.setOnAction(e -&gt; {
            // 삭제 버튼을 눌렀을 때 해야 하는 작업
            // 삭제할 책의 ISBN을 가져온다.
            BookVO selectedBook = (BookVO) tableView.getSelectionModel().getSelectedItem();
            if (selectedBook == null) {
                System.out.println(&quot;삭제할 책을 선택해주세요.&quot;);
                return;
            }

            String keywordDelete = selectedBook.getBisbn();

            String currentKeyword = textField.getText();

            BookSearchService service = new BookSearchService();
            ObservableList&lt;BookVO&gt; updatedData = service.deleteBookByKeyword(keywordDelete);
            ObservableList&lt;BookVO&gt; searchData = service.searchBookByKeyword(currentKeyword);

            tableView.setItems(searchData);

            tableView.getSelectionModel().clearSelection();
        });

    }
}</code></pre>
<ul>
<li>booksearch.dao.BookDAO.java</li>
</ul>
<pre><code class="language-java">package booksearch.dao;

import booksearch.vo.BookVO;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class BookDAO {
    private Connection con;
    public BookDAO() {
        // JDBC Driver Loading
        try {
            Class.forName(&quot;com.mysql.cj.jdbc.Driver&quot;);
            String id = &quot;root&quot;;
            String pw = &quot;jiyun9163!&quot;;
            String JDBC_URL = &quot;jdbc:mysql://localhost:3306/library?characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;useSSL=false&amp;allowPublicKeyRetrieval=true&quot;;
            con = DriverManager.getConnection(JDBC_URL, id, pw);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public ObservableList&lt;BookVO&gt; select(String keyword) {
        // IN Parameter를 이용해서 PreparedStatement를 생성한다.
        String sql = &quot;SELECT bisbn, btitle, bprice, bauthor FROM book &quot; + &quot;WHERE btitle Like ?&quot;;
        ObservableList&lt;BookVO&gt; data = FXCollections.observableArrayList();
        try {
            PreparedStatement pstmt = con.prepareStatement(sql);
            // 당연히 In Parameter를 채워줘야 실행이 가능하다.
            pstmt.setString(1, &quot;%&quot; + keyword + &quot;%&quot;);
            ResultSet rs = pstmt.executeQuery();

            // rs는 결과 레코드 집합의 포인터이다. 이것을 움직여서 우리가 select한 결과를 얻는다.
            while (rs.next()) { // 계속해서 내려간다.
                BookVO book = new BookVO(
                        rs.getString(&quot;bisbn&quot;),
                        rs.getString(&quot;btitle&quot;),
                        rs.getInt(&quot;bprice&quot;),
                        rs.getString(&quot;bauthor&quot;));
                data.add(book);
            }

        } catch (Exception e) {

        }
        return data;
    }

    public ObservableList&lt;BookVO&gt; delete(String keyword) {
        String sqlDelete = &quot;DELETE FROM book WHERE bisbn = ?&quot;;
        String sqlSelect = &quot;SELECT bisbn, btitle, bprice, bauthor FROM book&quot;;
        ObservableList&lt;BookVO&gt; data = FXCollections.observableArrayList();

        try {
            // 먼저 책을 삭제한다.
            PreparedStatement pstmtDelete = con.prepareStatement(sqlDelete);
            pstmtDelete.setString(1, keyword);
            int rowsAffected = pstmtDelete.executeUpdate();

            if (rowsAffected &gt; 0) {
                System.out.println(keyword + &quot;을(를) 삭제했습니다.&quot;);

                // 삭제 후에 변경된 데이터를 다시 조회한다.
                PreparedStatement pstmtSelect = con.prepareStatement(sqlSelect);
                ResultSet rs = pstmtSelect.executeQuery();

                // 새로 조회한 결과를 ObservableList에 추가한다.
                while (rs.next()) {
                    BookVO book = new BookVO(
                            rs.getString(&quot;bisbn&quot;),
                            rs.getString(&quot;btitle&quot;),
                            rs.getInt(&quot;bprice&quot;),
                            rs.getString(&quot;bauthor&quot;));
                    data.add(book);
                }
            } else {
                System.out.println(&quot;삭제할 데이터가 없습니다.&quot;);
            }
        } catch (Exception e) {
            System.out.println(&quot;삭제 중 오류 발생: &quot; + e.getMessage());
            e.printStackTrace();
        }

        return data;
    }

}</code></pre>
<ul>
<li>booksearch.service.BookSearchService.java</li>
</ul>
<pre><code class="language-java">package booksearch.service;

import booksearch.dao.BookDAO;
import booksearch.vo.BookVO;
import javafx.collections.ObservableList;

public class BookSearchService {

    public ObservableList&lt;BookVO&gt; searchBookByKeyword(String keyword) {
        // 이 안에서는 로직 처리를 한다.
        // 만약 Database 처리를 하게 되면 DAO 만들어서 사용해야 한다.
        // 별 다른 로직처리를 할 게 없다면 그냥 DB 처리만 하면 된다.
        BookDAO dao = new BookDAO();
        ObservableList&lt;BookVO&gt; result =  dao.select(keyword);

        return result;
    }
    // 로직 처리 객체
    // 당연히 이 안에는 business method가 존재한다.
    public ObservableList&lt;BookVO&gt; deleteBookByKeyword(String keyword) {
        // 이 안에서는 로직 처리를 한다.
        // 만약 Database 처리를 하게 되면 DAO 만들어서 사용해야 한다.
        // 별 다른 로직처리를 할 게 없다면 그냥 DB 처리만 하면 된다.
        BookDAO dao = new BookDAO();
        ObservableList&lt;BookVO&gt; result =  dao.delete(keyword);

        return result;
    }
}</code></pre>
<ul>
<li>booksearch.vo.BookVO.java</li>
</ul>
<pre><code class="language-java">package booksearch.vo;

public class BookVO {
    private String bisbn;
    private String btitle;
    private int bprice;
    private String bauthor;

    public BookVO() {
    }

    public BookVO(String bisbn, String btitle, int bprice, String bauthor) {
        this.bisbn = bisbn;
        this.btitle = btitle;
        this.bprice = bprice;
        this.bauthor = bauthor;
    }

    public String getBisbn() {
        return bisbn;
    }

    public void setBisbn(String bisbn) {
        this.bisbn = bisbn;
    }

    public String getBtitle() {
        return btitle;
    }

    public void setBtitle(String btitle) {
        this.btitle = btitle;
    }

    public int getBprice() {
        return bprice;
    }

    public void setBprice(int bprice) {
        this.bprice = bprice;
    }

    public String getBauthor() {
        return bauthor;
    }

    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }
}</code></pre>
<ul>
<li>booksearch.view.JavaFXBookSearchTableView.fxml</li>
</ul>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;?import javafx.geometry.Insets?&gt;
&lt;?import javafx.scene.control.Button?&gt;
&lt;?import javafx.scene.control.Label?&gt;
&lt;?import javafx.scene.control.TableColumn?&gt;
&lt;?import javafx.scene.control.TableView?&gt;
&lt;?import javafx.scene.control.TextField?&gt;
&lt;?import javafx.scene.layout.BorderPane?&gt;
&lt;?import javafx.scene.layout.FlowPane?&gt;

&lt;BorderPane fx:controller=&quot;booksearch.controller.BookSearchController&quot; maxHeight=&quot;-Infinity&quot; maxWidth=&quot;-Infinity&quot; minHeight=&quot;-Infinity&quot; minWidth=&quot;-Infinity&quot; prefHeight=&quot;400.0&quot; prefWidth=&quot;600.0&quot; xmlns=&quot;http://javafx.com/javafx/21&quot; xmlns:fx=&quot;http://javafx.com/fxml/1&quot;&gt;
    &lt;bottom&gt;
        &lt;FlowPane prefHeight=&quot;28.0&quot; prefWidth=&quot;600.0&quot; BorderPane.alignment=&quot;CENTER&quot;&gt;
            &lt;children&gt;
                &lt;Label prefHeight=&quot;60.0&quot; prefWidth=&quot;60.0&quot; text=&quot;검색키워드&quot;&gt;
                    &lt;FlowPane.margin&gt;
                        &lt;Insets left=&quot;10.0&quot; /&gt;
                    &lt;/FlowPane.margin&gt;
                &lt;/Label&gt;
                &lt;TextField fx:id=&quot;textField&quot; prefHeight=&quot;39.0&quot; prefWidth=&quot;263.0&quot;&gt;
                    &lt;FlowPane.margin&gt;
                        &lt;Insets left=&quot;10.0&quot; /&gt;
                    &lt;/FlowPane.margin&gt;
                &lt;/TextField&gt;
                &lt;Button fx:id=&quot;searchBtn&quot; mnemonicParsing=&quot;false&quot; prefHeight=&quot;31.0&quot; prefWidth=&quot;103.0&quot; text=&quot;검색&quot;&gt;
                    &lt;FlowPane.margin&gt;
                        &lt;Insets left=&quot;20.0&quot; /&gt;
                    &lt;/FlowPane.margin&gt;
                &lt;/Button&gt;
                &lt;Button fx:id=&quot;deleteBtn&quot; mnemonicParsing=&quot;false&quot; prefHeight=&quot;30.0&quot; prefWidth=&quot;105.0&quot; text=&quot;선택된 책 삭제&quot;&gt;
                    &lt;FlowPane.margin&gt;
                        &lt;Insets left=&quot;20.0&quot; /&gt;
                    &lt;/FlowPane.margin&gt;
                &lt;/Button&gt;
            &lt;/children&gt;
        &lt;/FlowPane&gt;
    &lt;/bottom&gt;
    &lt;center&gt;
        &lt;TableView fx:id=&quot;tableView&quot; prefHeight=&quot;200.0&quot; prefWidth=&quot;200.0&quot; BorderPane.alignment=&quot;CENTER&quot;&gt;
            &lt;columns&gt;
                &lt;TableColumn fx:id=&quot;isbn&quot; prefWidth=&quot;75.0&quot; text=&quot;책 ISBN&quot; /&gt;
                &lt;TableColumn fx:id=&quot;title&quot; prefWidth=&quot;322.0&quot; text=&quot;책 제목&quot; /&gt;
                &lt;TableColumn fx:id=&quot;price&quot; minWidth=&quot;0.0&quot; prefWidth=&quot;75.0&quot; text=&quot;책 가격&quot; /&gt;
                &lt;TableColumn fx:id=&quot;author&quot; prefWidth=&quot;106.0&quot; text=&quot;책 저자&quot; /&gt;
            &lt;/columns&gt;
        &lt;/TableView&gt;
    &lt;/center&gt;
&lt;/BorderPane&gt;</code></pre>
<pre><code class="language-java">package booksearch.view;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class BookSearchView extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = null;
        FXMLLoader loader = new FXMLLoader(
                getClass().getResource(&quot;JavaFXBookSearchTableView.fxml&quot;));
        try {
            root = loader.load();
        } catch (Exception e) {
            System.err.println(e);
        }

        Scene scene = new Scene(root);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] JDBC란?]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-JDBC%EB%9E%80</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-JDBC%EB%9E%80</guid>
            <pubDate>Fri, 12 Apr 2024 08:59:05 GMT</pubDate>
            <description><![CDATA[<h2 id="1-database">1. Database</h2>
<ul>
<li>데이터베이스는 데이터의 집합체를 의미한다.</li>
<li>대용량의 데이터 집합을 체계적으로 구성해 놓은 것.</li>
<li>이런 데이터의 집합체는 당연히 관리가 필요하다. 프로그램으로 관리하게 된다.</li>
<li>이런 프로그램들의 집합체를 <strong><code>DBMS(Database Management System)</code></strong>이라고 한다.</li>
<li>DBMS 종류<ul>
<li>Oracle(제품명) - Oracle(제작사) - 유료(상용시장 점유율 1등)</li>
<li>MySQL(제품명) - Oracle(인수함) - 유료, 무료</li>
<li>MariaDB(제품명) - MariaDB(MySQL 제작자와 동일) - 무료</li>
<li>PostgreSQL(제품명) - PostgreSQL - 무료</li>
<li>DB2(제품명) - IBM - 메인 프레임 시장 1등</li>
<li>SQL Server(제품명) - MS</li>
</ul>
</li>
</ul>
<h2 id="2-dbms의-특징">2. DBMS의 특징</h2>
<ol>
<li>Integrity(무결성) : 데이터 안에 오류가 생기는 것을 막아준다. 이런 결함을 방지하기 위해서 당연히 사용자가 제약사항(constraints)을 걸어줘야 한다.</li>
<li>독립성 : 데이터베이스를 변경해도 기존 프로그램에는 영향이 없어야 한다.</li>
<li>보안</li>
<li>데이터 중복의 최소화</li>
</ol>
<h2 id="3-dbms의-종류">3. DBMS의 종류</h2>
<ul>
<li>계층형 데이터베이스</li>
<li>네트워크형 데이터베이스 → 계층형 데이터베이스의 단점을 극복하기 위해서 등장했지만 망했다.</li>
<li>(1970년대) E.F.Codd라는 사람이 등장함. (IBM에 근무하던 수학자) → Relational Model 논문을 발표했다.<ul>
<li>IBM에서 prototype으로 만든다. ⇒ 현재의 DB2로 이어져 내려오고 있다.</li>
<li>모든 vendor들이 관계형 데이터베이스를 만들고 이걸 사용하게 된다.</li>
</ul>
</li>
<li>(1990년~) 객체지향 데이터베이스가 등장 ⇒ 큰 흥행을 하지 못했다. 하지만 객체지향 개념은 중요하다.</li>
<li>현재는 관계형 데이터베이스에 객체지향 개념을 섞었다. ⇒ 객체-관계형 데이터베이스 ⇒ Oracle</li>
<li>아주 최근에는 정형 데이터가 아닌 비정형 데이터가 많아졌다.</li>
<li>이런 비정형 데이터인 경우 NoSQL 계열의 데이터베이스를 사용한다.</li>
</ul>
<h2 id="4-mysql">4. MySQL</h2>
<ul>
<li>MySQL community server 설치</li>
<li>여러가지 Database Client 프로그램들을 활용한다.</li>
<li>대표적인 유료 툴 : DataGrip(JetBrains), DBeaver(현업에서 많이 사용)</li>
<li>MySQL 무료 툴을 하나 제공해 준다. ⇒ WorkBench</li>
</ul>
<h3 id="41-데이터베이스-생성">4.1 데이터베이스 생성</h3>
<ul>
<li>WorkBench에서 확인해 보자.</li>
<li>테이블 : 데이터가 실제로 저장되어 있는 객체</li>
<li>views : 가상의 테이블(실제 데이터를 가지고 있는 테이블이 아니라, 테이블을 이용한 가상의 테이블, 주로 회사에서도 뷰로 작업함.)</li>
<li>Stored Procedure : 자주 사용되며 효율이 필요한 쿼리들을 함수로 만들어서 프로그래머나 일반 사용자에게 함수로 제공하는 것.</li>
</ul>
<h2 id="5-jdbc-개요">5. JDBC 개요</h2>
<ul>
<li>JDBC는 Java Database Connectivity의 약자로 Java로 데이터베이스에 있는 값을 활용하기 위해서 사용되는 class와 interface의 집합이다.</li>
<li>데이터베이스 vendor들은 각자 자신의 데이터베이스 운영시스템(DBMS)를 가지고 있고 이 데이터베이스를 Program 언어가 사용할 수 있도록 무엇인가를 제공해야 한다.</li>
<li>당연히 Java인 경우는 class와 interface로 제공해준다.</li>
<li>이렇게 제공되는 클래스 중에 DBMS와 직접적으로 통신하는 class가 있는데 이를 <strong><code>Driver</code></strong>라고 한다.
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/4f6ea1d2-04c8-4f2b-82fe-81a37fda99a7/image.png" alt=""><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/ef4fa2a6-a669-46ab-ba83-60e2f098ff2f/image.png" alt=""></li>
</ul>
<pre><code class="language-java">package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

// 1. DBMS가 제공하는 JDBC Driver class를 우리가 사용할 수 있어야 한다.
// library에 추가하자.
public class BasicJDBCConnect {
    public static void main(String[] args) throws ClassNotFoundException {
        // 2. 우리는 MySQL에 연결한다.
        // MySQL에 연결하기 위한 JDBC Driver를 프로그램 안으로 로딩해야 한다.
        // 드라이버 로딩
        try {
            Class.forName(&quot;com.mysql.cj.jdbc.Driver&quot;);
            System.out.println(&quot;드라이버 로딩 성공&quot;);
            // 3. 드라이버 로딩이 성공하면 실제 데이터베이스에 접속해보자.
            // 계정 ID, PW, 접속하려는 데이터베이스에 대한 URL이 있어야 한다.
            // 데이터베이스에 대한 URL =&gt; JDBC URL 이라고도 한다.
            String myId = &quot;root&quot;;
            String myPW = &quot;jiyun9163!&quot;;
            String JDBC_URL = &quot;jdbc:mysql://localhost:3306/employees?characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;useSSL=false&amp;allowPublicKeyRetrieval=true&quot;;
            Connection con = DriverManager.getConnection(JDBC_URL, myId, myPW);
            System.out.println(&quot;데이터베이스 접속 성공&quot;);
            // 3. Connection 객체를 얻었으면 이제 SQL Query를 작성해서 전달해야 하는데
            // 이 SQL을 실어서 보낼 객체가 하나 필요하다.
            // 이 객체를 Statement라고 한다. 이 Statement는 크게 3가지 종류가 있다.
            // 제일 간단한 형태인 Statement
            // Stored Procedure을 호출할 수 있는 CallableStatement가 있다.
            // 이 중에서 우리는 PreparedStatement를 이용할 것이다.
            // 이름에서 의미하다시피, 이 Statement는 SQL Query를 가지고 있는 statement이다.
            String sql = &quot;select * from employees where gender=&#39;F&#39;&quot;;
            PreparedStatement pstmt = con.prepareStatement(sql);
            // 4. 이렇게 전달할 Statement를 만들었으면
            // 이제 실행하면 된다. =&gt; SQL Query를 실행할 수 있다.
            // 하지만 실행하려는 SQL이 Select 계열이면 =&gt; 결과 레코드 집합을 가져오는 거
            // 이때 사용하는 method는 executeQuery()를 이용한다.
            // 그러면 이때 return 값은 어떻게 받으면 되나요? =&gt; ResultSet으로 받는다.
            ResultSet rs = pstmt.executeQuery();

            // 5. ResultSet을 이용해서 데이터 추출(로직 처리)
            rs.next();
            String firstName = rs.getString(&quot;first_name&quot;);
            System.out.println(firstName); // Bezalel
            rs.next();
            firstName = rs.getString(&quot;first_name&quot;);
            System.out.println(firstName); // Anneke

            // 6. 사용된 자원의 반납
            // 사용한 여러 자원들을 close 시켜서 정상 종료를 해줘야 한다.
            // 사용한 자원들을 생성과 반대 순서로 close 처리 해줘야 한다.
            rs.close();
            pstmt.close();
            con.close();

        } catch (Exception e) {
            System.out.println(&quot;오류&quot;);
        }

    }
}</code></pre>
<h2 id="6-vo-do-entity-dto">6. VO, DO, Entity, DTO</h2>
<ul>
<li>DO(Domain Object) : 연관성이 있는 데이터 객체 1개를 지칭하는 용어</li>
<li>예를 들면 학사 관리 프로그램 → 학번, 이름, 학과, 나이, 학년, 학점, …</li>
<li>(1000, 홍길동, 철학, 20, 1, 3.5), (홍길동, 철학, 20, 1, 3.5)</li>
<li>VO(Value Object) : DO인데 값에 초점을 맞춘 객체</li>
<li>Entity : DO인데 반드시 primary key가 포함되어 있다.</li>
<li>DTO(Data Transfer Object) : DO인데 데이터 전달에 목적이 있다.</li>
<li>하지만 결과적으로 다 비슷하게 생겼고, 큰 차이를 두고 사용하지 않는다. 혼용해서 사용한다.</li>
<li>가장 대표적인 용어는 VO이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Network]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Network</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Network</guid>
            <pubDate>Fri, 12 Apr 2024 08:41:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1-network-개요">1. Network 개요</h2>
<h3 id="11-network-internet">1.1 Network, Internet</h3>
<ul>
<li>컴퓨터 network는 컴퓨터를 포함해서 컴퓨터 간에 데이터를 주고 받을 수 있는 통신 링크의 집합을 지칭한다.</li>
<li>Internet은 Network of Network의 의미.</li>
<li>Network를 전 세계적으로 확장시켜 놓은 통신 링크의 집합체를 지칭하는 용어.</li>
<li>따라서 <strong><code>Internet은 infrastructure</code></strong>를 지칭하는 용어</li>
<li>이런 Internet을 사용하기 위해 필요한 것은 해당 infrastructure 위에서 동작하는 프로그램이 있어야 한다.</li>
<li>이런 프로그램들을 통칭해서 service라고 한다.</li>
<li>Web Service, Email Service, 파일 전송 서비스</li>
<li>일반적으로 특정 기준으로 Network를 구분해서 표현하는데 가장 많이 사용하는 구분은 네트워크의 크기이다.</li>
<li><strong><code>LAN</code></strong>(Local Area Network), <strong><code>WAN</code></strong>(Wide Area Network), <strong><code>MAN</code></strong>(Matropolitan Area Network)</li>
</ul>
<h3 id="12-ip-address">1.2 IP Address</h3>
<ul>
<li>컴퓨터 네트워크에 각각 장치를 식별하기 위해 사용하는 논리적인 숫자값.</li>
<li>IP 주소는 32비트로 되어 있는 IPv4, 128비트로 되어있는 IPv6이 있다.</li>
<li>IPv4는 “.”으로 이루어진 4자리의 숫자로 구성 ⇒ 127.0.0.1</li>
<li>IPv6은 “:”으로 이루어진 8개의 16비트 숫자로 구성 ⇒ 2001:ab08:1267:…</li>
<li>이런 IP Address는 논리적인 주소이다. ⇒ 변경될 수 있다.</li>
<li>실제로 하나의 컴퓨터가 다른 컴퓨터를 찾아서 데이터를 전송할 때는 논리적인 주소만 가지고 데이터를 전달할 수 있을까?</li>
<li>사실 물리적인 주소값이 필요하다.</li>
<li>이런 물리적인 주소값을 MAC address라고 부르고 각 device마다 고유값을 가지고 있다.</li>
</ul>
<h3 id="13-protocol">1.3 Protocol</h3>
<ul>
<li>컴퓨터 통신도 protocol이 설정되어 있어야 가능하다.</li>
<li>protocol 안에는 데이터를 전송하고 수신하는 방법, 오류 처리 방법, 보안, 암호화 규칙 등이 포함되어 있다.</li>
</ul>
<h3 id="14-port">1.4 Port</h3>
<ul>
<li>IP address가 지칭하는 것은 정확히 말하면 NIC(network interface card)를 의미하고 조금 더 확장하자면 해당 NIC가 붙어있는 컴퓨터(쇳덩어리)를 의미한다.</li>
<li>당연히 IP address만을 가지고는 통신이 안된다.</li>
<li>왜냐하면 데이터 통신은 process(프로그램) 간에 이루어지는 것이기 때문이다.</li>
<li>그래서 어떤 프로그램과 데이터 통신을 할지 명시해야 하는데, 그때 해당 프로그램을 지칭하는 숫자를 대신 이용하게 된다. 이 숫자를 Port라고 한다.</li>
<li>즉, 데이터 통신을 하기 위해서는 Protocol, IP address, Port 이렇게 3가지 요소가 있어야 한다.</li>
<li><strong><code>Protocol</code></strong> :// <strong><code>IP address</code></strong> : <strong><code>Port</code></strong></li>
</ul>
<h3 id="15-network-프로그램이-너무-어렵다">1.5 Network 프로그램이 너무 어렵다.</h3>
<ul>
<li>Socket 개념 등장
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/a0a64b0e-8273-4871-9415-32cdfdac8613/image.png" alt=""></li>
</ul>
<h2 id="2-기본적인-절차">2. 기본적인 절차</h2>
<ul>
<li>Java Network는 기본적으로 CS 구조로 동작한다.</li>
<li>Client-Server 간에 데이터 통신을 기반으로 한다.</li>
<li>Client는 능동적으로 접속을 시도하는 program(process)</li>
<li>Server는 수동적으로 접속을 기다리고 있는 program(process)</li>
</ul>
<h3 id="서버-프로그램">서버 프로그램</h3>
<pre><code class="language-java">package javanetworkexam;

import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleServer {

    public static void main(String[] args) {
        // 1. ServerSocket 객체를 생성한다.
        //     ServerSocket을 생성할 때 client가 접속해서 들어올 
        //     Port번호를 명시해야 한다.
        //     0~65535 사이의 값을 사용해야 한다.
        //     0~1023 까지는 Well Known Port라고 해서 이미 용도가
        //     정해져 있기 때문에 그 이후 값을 이용해야 한다.
        //     하나의 컴퓨터에서 동작하는 프로그램이 사용하는 Port번호는
        //     Unique해야 한다.
        try {
            ServerSocket serverSocket = 
                    new ServerSocket(5555);
            System.out.println(&quot;서버소켓 객체 생성&quot;);

            Socket s = serverSocket.accept();  
            // 일단 대기(클라이언트가 접속할 때까지)
            System.out.println(&quot;accept()가 풀렸습니다.&quot;);

            // 이렇게 얻어진 socket에 대해서 Stream객체를 얻어낸다.
            PrintWriter out = new PrintWriter(s.getOutputStream());
            out.println(&quot;이것은 소리없는 아우성 - 서버가 전달했다.&quot;);
            // PrintWriter는 효율을 위해서 내부 buffer를 가지고 있다.
            // 명시적으로 flush를 이용해 데이터를 전달해야 한다.
            out.flush();


        } catch (Exception e) {

        }


    }
}</code></pre>
<h3 id="클라이언트-프로그램">클라이언트 프로그램</h3>
<pre><code class="language-java">package javanetworkexam;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

public class SimpleClient {

    public static void main(String[] args) {
        // 클라이언트는 능동적으로 서버 프로세서(ServerSocket)에
        // 접속을 시도한다. 당연히 IP와 PORT를 알려줘야 한다.
        // IP는 당연히 목적지의 IP를 주소를 넣어야 한다.
        // 지금은 Server 프로그램이 같은 컴퓨터에 있기 때문에
        // IP주소를 현재 사용하고 있는 컴퓨터를 지칭하는 특별한 IP주소를 이용한다.
        // 127.0.0.1 이라는 IP를 이용한다.(혹은 이 IP에 할당된 localhost)

        // 접속을 시도해서 만약 접속이 성공하면 진짜 객체가 생성된다.
        // 접속이 실패하면 null이 return 된다.
        try {
            Socket s = new Socket(&quot;localhost&quot;,5555);
            System.out.println(&quot;접속 성공&quot;);

            InputStreamReader isr = 
                    new InputStreamReader(s.getInputStream());

            BufferedReader br = new BufferedReader(isr);

            String msg = br.readLine();

            System.out.println(msg);
        } catch (Exception e) {

        }

    }
}</code></pre>
<h2 id="3-간단한-echo-program-구현">3. 간단한 Echo Program 구현</h2>
<ul>
<li>지금까지 배운 내용을 기반으로 간단한 Echo Program을 각자 구현해 보자.</li>
<li>사용된 FXML파일
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/59fb3ff7-0b16-4e4c-86fd-cf6fba7f5faf/image.png" alt=""></li>
<li>클라이언트용 FXML 파일<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
</code></pre></li>
</ul>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.text.Font?>


<BorderPane fx:controller="EchoClientController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1">
    <bottom>
        <FlowPane prefHeight="64.0" prefWidth="600.0" BorderPane.alignment="CENTER">
            <children>
                <TextField fx:id="userID" prefHeight="50.0" prefWidth="100.0">
                    <FlowPane.margin>
                        <Insets left="10.0" right="10.0" top="5.0" />
                    </FlowPane.margin>
                    <font>
                        <Font size="22.0" />
                    </font>
                </TextField>
                <TextField fx:id="userMsg" prefHeight="50.0" prefWidth="295.0">
                    <FlowPane.margin>
                        <Insets right="10.0" top="5.0" />
                    </FlowPane.margin>
                </TextField>
                <Button fx:id="sendMsg" mnemonicParsing="false" prefHeight="40.0" prefWidth="80.0" text="전송" />
                <Button fx:id="closeBtn" mnemonicParsing="false" prefHeight="40.0" prefWidth="80.0" text="종료">
                    <FlowPane.margin>
                        <Insets left="5.0" />
                    </FlowPane.margin>
                </Button>
            </children>
        </FlowPane>
    </bottom>
    <center>
        <TextArea fx:id="messageBox" prefHeight="308.0" prefWidth="600.0" BorderPane.alignment="CENTER">
            <BorderPane.margin>
                <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
            </BorderPane.margin>
        </TextArea>
    </center>
</BorderPane>
```
- 서버용 FXML 파일
```
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>


<BorderPane fx:controller="EchoServerController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="386.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1">
    <bottom>
        <Button fx:id="startBtn" mnemonicParsing="false" prefHeight="57.0" prefWidth="286.0" text="서버시작" BorderPane.alignment="CENTER">
            <BorderPane.margin>
                <Insets bottom="5.0" top="5.0" />
            </BorderPane.margin>
        </Button>
    </bottom>
    <center>
        <TextArea fx:id="messageBox" prefHeight="332.0" prefWidth="541.0" BorderPane.alignment="CENTER">
            <BorderPane.margin>
                <Insets bottom="5.0" left="20.0" right="20.0" top="20.0" />
            </BorderPane.margin>
        </TextArea>
    </center>
</BorderPane>
```


<h2 id="4-chatting-구현">4. Chatting 구현</h2>
<ul>
<li>Echo program을 확장해 방 1개짜리 Chatting program을 구현한다.</li>
<li>공용객체를 사용하는 부분을 추가해야 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] JavaFX]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-JavaFX</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-JavaFX</guid>
            <pubDate>Fri, 12 Apr 2024 08:34:27 GMT</pubDate>
            <description><![CDATA[<h2 id="1-javafx">1. JavaFX</h2>
<ul>
<li>Java에서 제공하는 표준 GUI library인 Swing을 대체하기 위해서 만들어진 library</li>
<li>당연히 표준 library는 아니다.</li>
<li>외부 library이고 다운로드 받아서 설치한 후 사용해야 한다.</li>
<li>특별한 용도로 사용되며 일반적으로 사용되는 library는 아니다.</li>
<li><a href="https://gluonhq.com/products/javafx/">https://gluonhq.com/products/javafx/</a></li>
<li>Properties → Java build Path → library → module path → add external jars</li>
<li>run as configuration</li>
<li>arguments → VM ~~</li>
<li>사용할 VM arguments</li>
<li>--module-path“C:\Program Files\Java\javafx-sdk-17.0.10\lib” --add-modules javafx.controls,javafx.fxml</li>
</ul>
<pre><code class="language-java">--module-path &quot;C:\Program Files\Java\javafx-sdk-17.0.10\lib&quot; --add-modules javafx.controls,javafx.fxml</code></pre>
<pre><code class="language-java">package javafxexam;

import javafx.event.EventHandler;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class JavaFXExample extends Application{

    @Override
    public void start(Stage primaryStage) throws Exception {
        // 화면구성

        // 1. Pane이라고 표현되는 layout을 만들어야 한다.
        // 여러종류의 Pane이 있는데 그 중 하나를 이용하면 된다.
        // Pane종류마다 버튼같은 component를 배치시키는 방법이 다르다.
        StackPane root = new StackPane();

        // 2. 화면에 보여줄 요소를 생성한다.
        Button btn = new Button();
        btn.setText(&quot;클릭&quot;);
        // 버튼이 클릭되면 무슨일을 할지 코드로 작성해야 한다.
        // 자바의 event model은 delegation model을 이용한다.
        // 이벤트처리를 위임한다는 의미로 delegation이라는 표현을 이용한다.
        // 버튼을 클릭하면 당연히 버튼이 event source가 된다.
        // event source는 이벤트가 발생한 객체를 지칭한다. =&gt; 버튼이 된다.
        // 그런데 이벤트가 발생했을때 이벤트의 처리(로직수행)를 event source가
        // 직접 처리하지 않고 별도의 객체를 이용하게 된다. =&gt; Listener객체라고 한다.
        // 당연히 해당 객체 안에는 이벤트를 처리하는 method가 있다.
        // 이 method를 흔히 handler라고 한다.
        // 마지막으로 event source에 listener를 부착시키는 과정이 필요하다.
        // 우리는 Action이라는 event를 사용하자.
        // Action이라는 event는 마우스 클릭, 입력상자에서 enter키 입력을
        // 지칭하는 event

        // 버튼(event source)에서 Action Event가 발생했을 때 처리하는
        // Event Handler객체를 만들어서 이벤트 처리를 하자.
        // 먼저 리스너객체를 만들어 보자.
        // 리스너객체도 당연히 종류가 있다.
        // 어떤 이벤트를 처리하느냐에 따라서 종류가 다르다.
//        btn.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
//            
//            @Override
//            public void handle(ActionEvent arg0) {
//                // TODO Auto-generated method stub
//                System.out.println(&quot;너무 힘들어요!&quot;);
//            }
//        });

        btn.setOnAction((e) -&gt; {
                // TODO Auto-generated method stub
                System.out.println(&quot;출력합니다.&quot;);
            }
        );

        // 3. Pane위에 표현할 Component를 위치시켜요!
        root.getChildren().add(btn);

        // 4. Scene을 생성해야 해요!
        Scene scene = new Scene(root, 300, 250);

        // 5. Stage에 Scene을 설정하면 되요!
        primaryStage.setTitle(&quot;첫 화면&quot;);
        primaryStage.setScene(scene);

        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] IO]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-IO</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-IO</guid>
            <pubDate>Fri, 12 Apr 2024 08:31:23 GMT</pubDate>
            <description><![CDATA[<h2 id="1-java-io">1. Java IO</h2>
<ul>
<li>Java 1.0부터 제공되는 자바의 기본적인 입출력 방식</li>
<li>Java IO는 입출력에 관련된 상당히 많은 클래스와 인터페이스를 제공하고, java.io package로 묶어서 제공한다.</li>
<li>Stream을 기반으로 처리한다.</li>
<li>기본적으로 Blocking I/O 방식을 이용한다. 입출력이 완료될 때까지 Thread가 block 된다.</li>
<li>대표적인 클래스로 InputStream, OutputStream, Reader, Writer 등이 있다.</li>
<li>참고로 Java NIO도 있다.<ul>
<li>Java 1.4에 처음 등장했다.</li>
<li>이름에서 의미하다시피 Non-Blocking IO를 지원한다. ⇒ 쉽게 말해 비동기 입출력할 수 있다.</li>
<li>Stream을 사용하지 않고, Channel과 Buffer을 이용한 처리를 한다.</li>
</ul>
</li>
</ul>
<h2 id="2-표준-입력과-표준-출력">2. 표준 입력과 표준 출력</h2>
<ul>
<li>표준 입력과 표준 출력(standard-in, standard-out)은 사용하는 기기마다 다르다.</li>
<li>우리는 PC를 이용하고 있기 때문에 표준 입력 ⇒ 키보드, 표준 출력 ⇒ 모니터로 설정되어 있다.</li>
<li>자바에서는 이 표준 입력과 표준 출력을 어떻게 표현할까?<ul>
<li>System.out ⇒ 표준 출력에 대한 Stream</li>
</ul>
</li>
<li>해당 객체(Stream)의 method를 이용해서 데이터를 출력할 수 있다.<ul>
<li><strong><code>System.out.println()</code></strong></li>
</ul>
</li>
<li>정리하면 Java는 우리에게 출력 Stream 객체를 하나 기본으로 제공하고 있다. 당연히 해당 객체를 만들기 위한 class가 존재한다. ⇒ java.io.PrintStream</li>
</ul>
<h2 id="3-stream">3. Stream</h2>
<h3 id="31-stream은-객체이다">3.1 Stream은 객체이다.</h3>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/c0c5fd47-a99f-4585-8638-c27b20d2064d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/50b265eb-b39d-464b-80a7-250d5ac3aa7e/image.png" alt=""></p>
<h3 id="32-stream은-방향성이-있다">3.2 Stream은 방향성이 있다.</h3>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/a2e535f0-8bc8-43de-b9f4-da30166c7c0a/image.png" alt=""></p>
<h3 id="33-stream은-fifo구조">3.3 Stream은 FIFO구조</h3>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/6d0fb159-97dd-406c-971f-39f150c43086/image.png" alt=""></p>
<h3 id="34-stream은-결합해서-사용할-수-있다">3.4 Stream은 결합해서 사용할 수 있다.</h3>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/bc26fb18-8742-4924-bb3d-f07bf94ba41c/image.png" alt=""></p>
<pre><code class="language-java">package test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class StreamTest {
    public static void main(String[] args) {

        // 키보드로 한 line을 입력 받아서 그대로 출력한다.
        // 당연히 입력 Stream과 출력 Stream이 필요하다.
        // 키보드로부터 입력을 받기 위한 Stream
        // 모니터에 출력하기 위한 출력 Stream
        // 표준 입력(키보드 입력) System.in -&gt; 불편함
        // 표준 출력(모니터 출력) System.out
        InputStreamReader isr = new InputStreamReader(System.in);
        // 아직도 불편하다. InputStreamReader은 문자 단위로 입력 받는다.
        // 우리는 한 line 단위로 입력을 받고 싶다. (문자열 단위로)
        BufferedReader br = new BufferedReader(isr);

        try {
            String msg = br.readLine();
            System.out.println(&quot;입력받은 데이터: &quot; + msg);
        } catch (Exception e) {

        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Thread의 동기화]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Thread%EC%9D%98-%EB%8F%99%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Thread%EC%9D%98-%EB%8F%99%EA%B8%B0%ED%99%94</guid>
            <pubDate>Mon, 08 Apr 2024 02:37:05 GMT</pubDate>
            <description><![CDATA[<h2 id="8-thread의-동기화">8. Thread의 동기화</h2>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/874c306f-2019-4604-8bb0-f080e595bd89/image.png" alt="">
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/7510f18b-268b-475d-bc56-40cf54aa1ef0/image.png" alt=""></p>
<ul>
<li>Monitor : Thread가 획득할 수 있는 자격</li>
<li>Thread → Runnable → 공용 객체<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>// 공유 자원 한 가지 정의
// Thread에 의해서 같이 사용되는 자원
// 즉, 공유 객체를 만들어서 사용한다.
// 공유 객체를 만들려면 당연히 class가 있어야 한다.
class Account {
    private int balance = 1000; // 잔액</p>
<pre><code>// 잔액 알아오는 method
public int getBalance() {
    return balance;
}

// 출금하는 method
// synchronized 키워드는 하나의 Thread가 이 메소드를 쓰면
// 다른 Thread는 block이 걸리면서 순차적으로 처리가 된다.
// Critical Section 임계 영역이 생긴다.
// 임계 영역을 설정해서 다수의 Thread가 동시에 사용할 수 없도록
// synchronized 키워드로 임계 영역을 설정한다.
// 당연히 순차 처리가 된다.
// 그러나 method에 이 키워드를 사용하는게 부담스럽다.
// 이 method 안에 모든 코드들이 동기화를 필요로 하는 것이 아니기 때문에
// 따라서 일반적으로 synchronized block을 이용한다.
public synchronized void withdraw(int money) {
    if (balance &gt; money) {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {

        }</code></pre><p>//            synchronized (this) { // 임계 영역을 줄여서 훨씬 효율적으로 synchronized를 사용한다.
//                balance -= money;
//            }
            balance -= money;
        }
    }</p>
<p>}</p>
<p>// Thread → Runnable → 공용 객체
class MySyncRunnable implements Runnable {</p>
<pre><code>Account acc = new Account(); // 공용 객체
@Override
public void run() {
    while(acc.getBalance() &gt; 0) {
        int money = (int)(Math.random() * 3 + 1) * 100;
        acc.withdraw(money);
        System.out.println(&quot;잔액은 &quot; + acc.getBalance());
    }
}</code></pre><p>}</p>
<p>public class ThreadSyncTest {
    public static void main(String[] args) {
        MySyncRunnable r = new MySyncRunnable();</p>
<pre><code>    // 같은 Runnable 객체를 다른 Thread가 사용
    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);

    t1.start();
    t2.start();
}</code></pre><p>}</p>
<pre><code>![](https://velog.velcdn.com/images/jiyoon9-velog/post/cedc90be-93d8-473c-9290-c1eff25affbe/image.png)
![](https://velog.velcdn.com/images/jiyoon9-velog/post/46bbe9d9-b217-40ba-aa07-86705810bb23/image.png)
```java
package test;

class Shared {

    // method 1개 만든다.
    // 해당 공유 객체는 여러 Thread에 의해서 같이 사용되는데
    // method를 호출할 때는 동기화시켜서 사용한다.
    public synchronized void printNum() {
        try {
            for (int i=0; i&lt;10; i++) {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + &quot;:&quot; + i);
                notify(); // 아까 전의 Thread를 깨운다.
                wait();
            }
        } catch (Exception e) {

        }
    }
}

class MyRunnable_10 implements Runnable {

    private Shared shared;

    public MyRunnable_10(Shared shared) {
        this.shared = shared;
    }

    @Override
    public void run() {
        shared.printNum();
    }
}

public class ThreadWaitNotiTest {
    public static void main(String[] args) {
        Shared obj = new Shared(); // 공유 객체

        Thread t1 = new Thread(new MyRunnable_10(obj));
        Thread t2 = new Thread(new MyRunnable_10(obj));

        t1.setName(&quot;첫 번째 Thread&quot;);
        t2.setName(&quot;두 번째 Thread&quot;);

        t1.start();
        t2.start();
    }
}</code></pre><ul>
<li>상태 전이도 전체적인 그림
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/672254b5-44ef-4392-b0f0-62199096684d/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Thread 우선 순위, Daemon Thread, Thread 실행 제어, sleep(), interrupt(), yield(), join()]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Thread-%EC%9A%B0%EC%84%A0-%EC%88%9C%EC%9C%84-Daemon-Thread-Thread-%EC%8B%A4%ED%96%89-%EC%A0%9C%EC%96%B4-sleep-interrupt</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Thread-%EC%9A%B0%EC%84%A0-%EC%88%9C%EC%9C%84-Daemon-Thread-Thread-%EC%8B%A4%ED%96%89-%EC%A0%9C%EC%96%B4-sleep-interrupt</guid>
            <pubDate>Fri, 05 Apr 2024 03:09:24 GMT</pubDate>
            <description><![CDATA[<h2 id="4-start--run">4. start() &amp; run()</h2>
<ul>
<li>실제 Thread가 수행해야 하는 코드는 run() method를 overriding해서 구현한다.</li>
<li>이 method를 우리가 직접 호출하는 게 아니라 start()라는 non-blocking method를 호출해서 Thread를 동작시킨다.</li>
</ul>
<h2 id="5-thread의-우선-순위priority">5. Thread의 우선 순위(priority)</h2>
<ul>
<li>Thread에는 우선 순위라는 게 있다. 기본적으로 5라는 값을 가진다.</li>
<li>1부터 10까지 범위 내에서 값을 설정해서 사용한다.</li>
<li>main thread는 우선 순위 5를 가진다.</li>
<li>Thread의 우선순위는 자기를 만든 Thread의 우선 순위를 물려 받아서 사용한다.</li>
<li>당연히 single core에서는 이 우선 순위가 Thread Scheduler에게 영향을 준다.</li>
<li>하지만 multi core에서는 이 값이 Thread 선택에 영향을 주지 않는다.</li>
<li>이 우선순위는 Thread가 일단 시작(start)하면 변경할 수 없다.</li>
<li>Thread 객체 상태에서 변경할 수 있다.</li>
</ul>
<pre><code class="language-java">package test;

public class ThreadPriorityTest {
    public static void main(String[] args) {

        // 추상 메소드를 가진 인터페이스이므로 객체를 생성할 수 없다.
        // 따라서 run() 메소드를 오버라이딩하면 쓸 수 있다.
        Thread t1 = new Thread(() -&gt; {
            for(int i=0; i&lt;10; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        });
        t1.setPriority(1);

        Thread t2 = new Thread(() -&gt; {
            for(int i=0; i&lt;10; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        });
        t2.setPriority(10);

        t1.start();
        t2.start();
    }
}</code></pre>
<h2 id="6-daemon-thread데몬-쓰레드">6. Daemon Thread(데몬 쓰레드)</h2>
<ul>
<li>우리가 사용하는 일반 Thread와는 다르게 보조적인 역할을 수행하는 Thread.</li>
<li>JVM의 garbage collector, 워드 프로세서의 auto save 기능 같은 것을 생각하자.</li>
<li>일반 Thread가 모두 종료되면 당연히 Daemon Thread도 존재의 의미가 없어지기 때문에 같이 종료된다.<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>public class DaemonThreadTest implements Runnable {</p>
<pre><code>static boolean autuSave = false;
public static void main(String[] args) {
    Thread t = new Thread(new DaemonThreadTest());
    t.setDaemon(true); // 내가 만든 Thread는 DaemaonThread로 사용할 것이다.

    t.start(); // 언젠가는 이 Thread가 동작하게 될 것이다.

    for (int i=0; i&lt;10; i++) {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {

        }
        System.out.println(&quot;i의 값은: &quot;+ i);
        if (i==5) {
            autuSave = true;
        }
    }

}

@Override
public void run() {
    while (true) {

        try {
            Thread.sleep(3000); // 3초가 지나면 or 중간에 누군가 방해하면 Interrupt를 걸면 깬다.
        } catch (Exception e) {
            System.out.println(&quot;오류 발생&quot;);
        }

        if (autuSave) { // 3초 중지 -&gt; 자동 저장 -&gt; 3초 중지 -&gt; 자동 저장
            System.out.println(&quot;자동 저장&quot;);
        }

    }
}</code></pre><p>}</p>
<pre><code>
## 7. Thread의 실행 제어

- 원래 Thread의 상태를 제어하는 쉬운 method가 있었다.
- stop(), suspend(), resume() 이다.
- 하지만 이런 method는 사용하기 편하지만 코드를 잘못 작성하면 dead-lock에 빠질 확률이 많다.
- 따라서 이 method들은 **`deprecated`** 되었다.
- 대신 실행 제어를 위한 다른 method를 제공한다.

### 7.1 sleep()

- sleep은 지정된 시간 동안 Thread를 멈추는 역할을 수행한다.
- sleep()에 의해서 일시 정지된 Thread는 지정된 시간이 다 되거나 혹은 interrupt()라는 method가 호출되면 이때 Exception이 발생하면서 잠에서 깬다.
- 따라서 예외 처리(try~catch) 구문이 강제로 사용된다.
- 다음과 같은 Thread의 상태 전이가 일어난다.
![](https://velog.velcdn.com/images/jiyoon9-velog/post/c621fbe2-9848-4b1c-8f53-b3eb8a87ca90/image.png)
```java
package test;

class Sleep_1 extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (Exception e) { }

        for (int i=0; i&lt;300; i++) {
            System.out.print(&quot;-&quot;);
        }
        System.out.println(&quot;&lt;&lt;Thread 1 종료&gt;&gt;&quot;);
    }
}

class Sleep_2 extends Thread {
    @Override
    public void run() {
        for (int i=0; i&lt;300; i++) {
            System.out.print(&quot;|&quot;);
        }
        System.out.println(&quot;&lt;&lt;Thread 2 종료&gt;&gt;&quot;);
    }
}

public class ThreadSleepTest {
    public static void main(String[] args) {
        Thread t1 = new Sleep_1();
        Thread t2 = new Sleep_2();

        t1.start();
        t2.start();

        try {
            // t1.sleep(2000); 이렇게는 사용하지 않는다.
            // t1을 지정해서 sleep 시킬 수 없다.
            Thread.sleep(2000); // main thread가 자게 된다.
            // sleep은 static method이고 현재 Thread를 sleep 시키는 method이다.
            // t1을 재우려면 t1의 run에 sleep이 있어야 한다.
        } catch (Exception e) { }

        System.out.println(&quot;&lt;&lt; main thread 종료 &gt;&gt;&quot;);
    }
}</code></pre><h3 id="72-interrupt-interrupted-isinterrupted">7.2 interrupt(), interrupted(), isInterrupted()</h3>
<ul>
<li>진행 중인 Thread를 작업이 다 끝나기 전에(run method의 수행이 끝나기 전에) 실행을 중지 시켜야 할 때도 있다.</li>
<li>예제에는 이 작업을 stop() method로 해결했다. 하지만 이제는 이렇게 못한다.</li>
<li>따라서 interrupt()라는 method를 대신 제공해서 이 작업을 수행할 수 있도록 해준다.</li>
<li>그런데 한 가지 주의해야 할 점이 있다.</li>
<li>interrupt()는 Thread에게 작업을 중지하라고 요청하는 것이며, stop()처럼 강제로 중지 시키지 않는다.</li>
<li>interrupt() method는 Thread가 내부적으로 가지고 있는 interrupted state를 변경하는 역할을 수행한다.</li>
<li>interrupted(), isInterrupted() 이 2개의 method는 Thread가 내부적으로 가지고 있는 interrupted state 값을 알아오는 것이다.</li>
<li>만약, 해당 Thread가 <strong><code>interrupt()</code></strong>가 호출되었으면 true가 리턴 되며, 그렇지 않으면 false가 리턴 된다.</li>
<li>한 가지 조심할 점은 <strong><code>interrupted()</code></strong> 이 method는 <strong>static</strong>으로 지정되어 있다.<ul>
<li>현재 수행 중인 Thread의 interrupted state를 알려준다.</li>
<li>그 상태를 알려준 다음에 무조건 값을 false로 변경한다.</li>
</ul>
</li>
<li>반면, <strong><code>isInterrupted()</code></strong>는 아주 심플하다.<ul>
<li><strong>instance</strong> method이다.</li>
<li>해당 Thread의 interrupted state를 알려주고 아무 일도 하지 않는다.</li>
<li>즉, 값을 변경하지 않는다.</li>
</ul>
</li>
<li>sleep()에 의해서 해당 Thread가 일시 정지 되어 있을 때 해당 Thread에 interrupt()를 호출해서 Interrupt Exception 발생하게 하고 해당 Thread를 Runnable 상태로 변경해준다.<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>import javax.swing.*;</p>
<p>class MyThread_3 extends Thread {
    @Override
    public void run() {
        int i = 10;</p>
<pre><code>    // isInterrupted() -&gt; interrupt면 true, 아니면 false 반환
    while (i != 0 &amp;&amp; !isInterrupted()) { // interrupt도 아니고 i가 10이면
        System.out.println(i--);
        for (long k=0; k&lt;25000000000L; k++); // 시간 지연
    }
    System.out.println(&quot;카운트가 종료되었습니다.&quot;);
}</code></pre><p>}</p>
<p>public class ThreadInterruptTest {
    public static void main(String[] args) {
        Thread t = new MyThread_3();
        t.start();</p>
<pre><code>    // 약간의 시간 지연을 위해 Swing을 이용한다.
    // swing에서 값을 입력하면 바로 while 문이 끝난다.
    String input = JOptionPane.showInputDialog(&quot;값을 입력하세요!&quot;);
    System.out.println(&quot;입력된 값은 &quot; + input + &quot; 입니다.&quot;);

    t.interrupt(); // isInterrupted() 메소드에 의해 while 문을 탈출한다.
}</code></pre><p>}</p>
<pre><code>- 위 코드는 잘 동작하긴 하지만, 사용하면 안 되는 코드가 들어있다.
- sleep을 이용해서 해결하여 코드를 다시 써보자.
- 한 가지 기억해야 하는 것은 sleep() 도중에 interrupt()가 호출되면 InterruptedException이 발생한다.
- 즉, catch문이 수행된다.
- 이 다음에 내부적으로 해당 Thread의 interrupted state가 false로 자동 초기화된다.
- 그래서 다시 interrupt()를 설정해야 한다.

```java
package test;

import javax.swing.*;

class MyThread_3 extends Thread {
    @Override
    public void run() {
        int i = 10;

        // isInterrupted() -&gt; interrupt면 true, 아니면 false 반환
        while (i != 0 &amp;&amp; !isInterrupted()) { // interrupt도 아니고 i가 10이면
            System.out.println(i--);

            try {
                Thread.sleep(4000); // 4초 자고 깨서 다시 while문 반복
                // sleep에서 깨면서 내부적으로 interrupt가 false가 된다.
            } catch (Exception e) { // Exception 발생하면 바로 while문으로 가며 interrupt가 발생하면서 while문이 끝난다.
                interrupt();
            }
        }
        System.out.println(&quot;카운트가 종료되었습니다.&quot;);
    }
}

public class ThreadInterruptTest {
    public static void main(String[] args) {
        Thread t = new MyThread_3();
        t.start();

        // 약간의 시간 지연을 위해 Swing을 이용한다.
        // swing에서 값을 입력하면 바로 while 문이 끝난다.
        // 즉, swing에서 값을 입력하면 interrupt가 발생한다.
        String input = JOptionPane.showInputDialog(&quot;값을 입력하세요!&quot;);
        System.out.println(&quot;입력된 값은 &quot; + input + &quot; 입니다.&quot;);

        t.interrupt(); // isInterrupted() 메소드에 의해 while 문을 탈출한다.
    }
}</code></pre><h3 id="73-yield">7.3 yield()</h3>
<ul>
<li>yield() method는 Thread 자신에게 주어진 실행 시간을 다음 차례의 Thread에게 양보하는 method이다.</li>
<li>프로그램의 응답 시간을 줄이기 위해 사용한다.</li>
<li>일반적으로 응답성을 높이는 목적으로 사용된다.</li>
<li>만약, yield()가 호출되면 자신은 Runnable 상태로 다시 들어가게 된다.
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/e3c3cffb-de64-4a0d-8eb9-07ef024426d0/image.png" alt=""></li>
<li>deprecated 된 suspend(), resume(), stop()을 한번 이용해 보자.</li>
</ul>
<pre><code class="language-java">package test;

class MyRunnable_4 implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println(Thread.currentThread().getName()); // 현재 Thread
            try {
                Thread.sleep(1000);
            } catch (Exception e) {

            }
        }
    }
}

public class ThreadYieldTest {
    public static void main(String[] args) {
        // Runnable 객체
        MyRunnable_4 r = new MyRunnable_4();

        Thread t1 = new Thread(r, &quot;*&quot;); // Thread 이름 지정
        Thread t2 = new Thread(r, &quot;**&quot;); // Thread 이름 지정
        Thread t3 = new Thread(r, &quot;***&quot;); // Thread 이름 지정

        t1.start();
        t2.start();
        t3.start();

        try {
            Thread.sleep(2000); // main thread가 sleep
            t1.suspend(); // t1을 일시 중지
            Thread.sleep(2000); // main thread가 sleep
            t2.suspend(); // t2을 일시 중지
            Thread.sleep(3000); // main thread가 sleep
            t1.resume();
            Thread.sleep(3000); // main thread가 sleep
            t1.stop();
            t2.stop();
            Thread.sleep(2000); // main thread가 sleep
            t3.stop();
        } catch (Exception e) {

        }
    }
}</code></pre>
<ul>
<li>위의 코드를 변수와 로직을 이용해서 똑같이 구현해 보자.</li>
</ul>
<pre><code class="language-java">package test;

class MyRunnable_4 implements Runnable {

    // 인스턴스 variable이므로 Thread가 이것을 공유할 수 없다.
    // 객체를 만들어서 각각 Thread와 맵핑한다.
    volatile boolean suspended = false;
    volatile boolean stoped = false;

    private Thread t;

    public void setThread(Thread t) {
        this.t = t;
    }

    @Override
    public void run() {

        while (!stoped) {
            if (!suspended) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {

                }
            } else {
                Thread.yield();
            }
        }
    }

    public void suspend() {
        suspended = true;
        // thread에 대해서 interrupt 걸면 된다.
        // thread에 대한 reference가 있어야 한다.
        t.interrupt();
    }

    public void resume() {
        suspended = false;
    }

    public void stop() {
        stoped = true;
    }
}

public class ThreadYieldTest {
    public static void main(String[] args) {
        // Runnable 객체
        MyRunnable_4 r1 = new MyRunnable_4();
        MyRunnable_4 r2 = new MyRunnable_4();
        MyRunnable_4 r3 = new MyRunnable_4();

        Thread t1 = new Thread(r1, &quot;*&quot;); // Thread 이름 지정
        Thread t2 = new Thread(r2, &quot;**&quot;); // Thread 이름 지정
        Thread t3 = new Thread(r3, &quot;***&quot;); // Thread 이름 지정

        r1.setThread(t1);
        r2.setThread(t2);
        r3.setThread(t3);

        t1.start();
        t2.start();
        t3.start();

        try {
            Thread.sleep(2000); // main thread가 sleep
            r1.suspend(); // t1을 일시 중지
            Thread.sleep(2000); // main thread가 sleep
            r2.suspend(); // t2을 일시 중지
            Thread.sleep(3000); // main thread가 sleep
            r1.resume();
            Thread.sleep(3000); // main thread가 sleep
            r1.stop();
            r2.stop();
            Thread.sleep(2000); // main thread가 sleep
            r3.stop();
        } catch (Exception e) {

        }
    }
}</code></pre>
<h3 id="74-join">7.4 join()</h3>
<ul>
<li>Thread가 자신이 하던 작업을 잠시 멈추고 다른 Thread를 지정된 시간 혹은 해당 Thread가 일을 다 마칠 때까지 Thread의 실행 시간을 확보하는 method</li>
<li>join()도 sleep()처럼 interrupt()에 의해서 대기 상태에서 벗어날 수 있다. try-cath 구문을 이용해야 한다.</li>
<li>기억해야 하는 점 중 하나는 sleep()은 static method이다. joint은 특정 Thread를 지칭해야 하기 때문에 static이 아니다.</li>
</ul>
<pre><code class="language-java">package test;

class MyThread_8 extends Thread {
    @Override
    public void run() {
        for(int i=0; i&lt;100; i++) {
            System.out.println(&quot;-&quot;);
        }
    }
}

class MyThread_9 extends Thread {
    @Override
    public void run() {
        for(int i=0; i&lt;100; i++) {
            System.out.println(&quot;|&quot;);
        }
    }
}

public class ThreadJoinTest {
    public static void main(String[] args) {
        MyThread_8 t1 = new MyThread_8();
        MyThread_9 t2 = new MyThread_9();

        t1.start();
        t2.start();

        try {
            t1.join(); // t1을 참여시키고, main thread를 일시 정지 시키고(대기), t1이 끝나면 main이 다시 실행
            t2.join();
        } catch (Exception e) {

        } // t1, t2 중 누가 어떻게 먼저 끝날지는 모르지만 적어도 main이 가장 늦게 끝날 것이다.
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Thread]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Thread</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Thread</guid>
            <pubDate>Thu, 04 Apr 2024 07:57:21 GMT</pubDate>
            <description><![CDATA[<h2 id="1-기본-용어">1. 기본 용어</h2>
<ul>
<li>많이 들어본 용어<ul>
<li><strong><code>process</code></strong> : 실행 중인 프로그램의 instance. 현재 실행 중인 프로그램을 지칭하는 용어<ul>
<li>process가 동작하려면 당연히 resource가 필요하다.</li>
<li>이 resource는 OS로 부터 할당 받는 메모리, CPU 시간, 디스크, 입출력 장치 등등</li>
</ul>
</li>
<li><strong><code>thread</code></strong> : 프로그램의 실행 흐름<ul>
<li>process는 하나 이상의 Thread로 구성된다.</li>
<li>Thread는 프로세스 내에서 실행되는 작은 실행 단위라고 할 수 있다.</li>
<li>Thread는 process의 resource를 공유한다. (메모리를 공유함) ⇒ process의 효율성을 향상시킨다.</li>
<li>만약, 둘 이상의 Thread를 가진 process라면 multi-thread process라고 한다.</li>
</ul>
</li>
<li><strong><code>multitasking</code></strong> : 시분할(time-slicing)기법을 이용해서 아주 짧은 시간동안 여러 process를 번갈아 가면서 수행시켜 마치 동시에 실행되는 것처럼 보이게 하는 기법</li>
<li><strong><code>multiprocessing</code></strong> : 서로 다른 core가 서로 다른 process를 시간적으로 동시에 실행시키는 개념</li>
<li><strong><code>multiprocessing (multithreading)</code></strong>
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/50bcc0c3-8931-4b7c-bc0e-078d9e193fb9/image.png" alt=""></li>
</ul>
</li>
<li><strong><code>Hyper-Threading</code></strong> : 1 core에 여러 Thread 담당</li>
</ul>
<h2 id="2-multithreading의-장-단점">2. Multithreading의 장, 단점</h2>
<ul>
<li>장점 : CPU와 resource를 효율적으로 사용함으로 process의 실행 효율을 높일 수 있다. 결국, 사용자에 대한 응답성을 확보할 수 있다.</li>
<li>단점 : resource를 공유하기 때문에 항상 동기화(Synchronization)에 신경을 써야 하고, 교착 상태(dead-lock) 상태에 빠질 수 있기 때문에 역시 이 부분도 신경을 써야 한다.</li>
</ul>
<h2 id="3-thread를-구현해-보자">3. Thread를 구현해 보자</h2>
<ul>
<li>Process 안에서 Thread는 실행시키는 단위</li>
<li>method ≠ Thread</li>
<li>Thread 별로 콜 스택을 따로 따로 가지고 있다.</li>
<li>Stack은 Thread마다 별도로 할당이 된다.</li>
<li>Thread가 다 종료되어야 전체 프로그램이 종료된다.</li>
<li>지금까지 작성했던 자바 프로그램은 사실 single thread process 였다.</li>
<li>main method를 호출해서 실행시키는 thread를 우리는 main thread라고 부른다.</li>
<li>프로그램 종료는 프로그램(process)안에서 생성한 모든 thread가 종료되어야 전체 process가 종료된다.</li>
<li>자바는 <strong><code>Thread</code></strong> 라는 class를 제공한다. 이 class를 이용해야만 Thread를 생성할 수 있다.</li>
</ul>
<h3 id="31-첫-번째-방법">3.1 첫 번째 방법</h3>
<ul>
<li>가장 쉬운 방법은 제공된 Thread class를 상속해서 사용자 정의 Thread class를 정의한 후, instance를 만들어서 사용하는 것이다.</li>
</ul>
<h3 id="32-두-번째-방법">3.2 두 번째 방법</h3>
<ul>
<li>Java가 제공해주는 Runnable이라는 interface를 구현해서 class를 만든 후, instance를 생성한다.</li>
<li>그런 다음 Thread의 생성자에 runnable 객체를 인자로 주어서 객체를 생성하면 Thread가 만들어진다.</li>
</ul>
<pre><code class="language-java">package test;

// 첫 번째 방법
class MyThread extends Thread { // Thread의 run()은 일반 메소드

    @Override
    public void run() {
        // Thread의 실행 코드
        System.out.println(&quot;여기는 첫 번째 Thread&quot;);
    }
}

// 두 번째 방법(이걸 더 많이 씀)
// 일반 추상 클래스는 객체를 만들지 않는다.
class MyRunnable implements Runnable { // Runnable의 run()은 추상 메소드
    // Thread의 실행 코드는 무조건 run() 안에 들어간다.
    @Override
    public void run() {
        // Thread의 실행 코드
        System.out.println(&quot;여기는 두 번째 Thread&quot;);
    }
}

public class ThreadTest {

    // main thread
    public static void main(String[] args) {
        MyThread t1 = new MyThread(); // Thread 생성
        t1.start(); // Thread 실행
        // start()는 non-blocking method
        // start()는 thread scheduler에게 thread를 실행시켜 달라고 요청하는 method
        // JVM이 thread scheduler를 가지고 있다.

        MyRunnable r = new MyRunnable(); // Runnable 객체
        Thread t2 = new Thread(r); // Thread 실행
        t2.start();
    }
}</code></pre>
<pre><code class="language-java">package test;

public class ThreadTest2 {

    // main thread
    public static void main(String[] args) {
        // interface는 추상 method가 있어서 객체(new Runnable())를 만들 수 없다.
        // 객체를 만들 수 없는 이유는 추상 method가 있기 때문이다.
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(&quot;너무 복잡하다.&quot;);
            }
        }).start(); // new Thread부터 .start() 전까지 Thread이다.

        new Thread(() -&gt; {
                System.out.println(&quot;너무 복잡하다...&quot;);
            }
        ).start();
    }
}</code></pre>
<ul>
<li>지금까지 동작을 그림(Thread의 상태 전이도)로 표현하면 아래와 같다.
  <img src="https://velog.velcdn.com/images/jiyoon9-velog/post/9f253ce6-864c-4516-be2b-df9c973fa9f6/image.png" alt=""></li>
</ul>
<pre><code class="language-java">package test;

class MyThread1 extends Thread {

    public MyThread1(String name) {
        // super(); 상위 클래스에서 인자가 없는 생성자
        super(name); // 상위 클래스에서 name 인자를 가진 생성자
    }

    @Override
    public void run() { // Thread 객체가 가지고 있는 run() 메소드
        for (int i=0; i&lt;9; i++) {
            System.out.println(this.getName()); // 결국 this는 Thread
        }
    }
}

class MyRunnable2 implements Runnable {
    @Override
    public void run() {
        for (int i=0; i&lt;9; i++) {
            System.out.println(Thread.currentThread().getName()); // 인스턴스가 없어도 쓸 수 있는 static(메소드 or 필드)
            // 글씨가 기울어져 있으면 static
        }
    }
}
public class ThreadTest3 {
    public static void main(String[] args) {

        MyThread1 t1 = new MyThread1(&quot;홍길동&quot;);
        MyRunnable2 r = new MyRunnable2();
        Thread t2 = new Thread(r);

        t1.start();
        t2.start();
        // Runnable(실행이 가능한) 상태로 Thread가 들어온다. Thread 큐로 들어온다.
        // Thread Scheduler가 Thread를 선택하고 Core가 붙어서 Running 상태로 만든다.
        // run이 끝나면 Thread가 Dead 상태가 된다.
        // 즉, 여러 가지 상태 전이가 일어난다.
        // 누가 먼저 실행 될지는 아무도 모른다.
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Exception]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Exception-uv2opuyf</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Exception-uv2opuyf</guid>
            <pubDate>Thu, 04 Apr 2024 07:25:51 GMT</pubDate>
            <description><![CDATA[<h2 id="1-exception">1. Exception</h2>
<ul>
<li>프로그램 실행 시 발생하는 다양한 형태의 오류</li>
<li>만약 오류가 발생하고 우리가 코드로 특별한 처리를 하지 않는다면 당연히 비정상 종료가 일어난다.</li>
<li>그런데 <strong><code>Exception Handling</code></strong>을 하게 되면 이런 상황에서 프로그램을 비정상 종료 시키지 않고 지속적으로 수행시킬 수 있다.</li>
<li>이런 Exception은 다양한 class들로 제공된다.</li>
<li>모든 Exception class들의 최 상위 class는 Exception class</li>
</ul>
<pre><code class="language-java">package test;

public class ExceptionTest {

    public static void main(String[] args) {

        System.out.println(&quot;예외 상황 발생시키기&quot;);
        int result = 10 / 0;  // Exception 발생
        // Exception이 발생하면 해당 Exception에 대한
        // 클래스를 찾아서 Exception 객체를 생성한다.
        // (java.lang.ArithmeticException)
        // 자동으로 생성된 이 객체를 프로그램적으로 처리를 안해주면
        // 프로그램 비정상 종료!
        // Exception Handling 해서 강제 종료를 하지 않는다.
        System.out.println(&quot;이거 수행될까?&quot;);

    }
}</code></pre>
<ul>
<li>기본적인 처리 코드는 다음과 같아요! ( try ~ catch 구문 )</li>
</ul>
<pre><code class="language-java">package test;

public class ExceptionTest {

    public static void main(String[] args) {

        System.out.println(&quot;예외 상황 발생시키기&quot;);
        try {
            int result = 10 / 0;  // Exception 발생    
        } catch(ArithmeticException e) {
            // 발생한 예외에 대한 처리 코드
            System.out.println(&quot;처리 완료&quot;);
        }
        System.out.println(&quot;이거 수행될까?&quot;);

    }
}</code></pre>
<ul>
<li>Exception(가장 상위 클래스)은 catch 구문 가장 첫 번째로 쓰면 안된다.<ul>
<li>다른 하위 Exception 클래스를 먼저 위에 써야 한다.</li>
</ul>
</li>
</ul>
<pre><code class="language-java">package test;

public class ExceptionTest {
    public static void main(String[] args) {
        System.out.println(&quot;예외 상황을 발생시켜보자.&quot;);
        try { // Exception e &lt;- 이것은 Exception의 상위 클래스
            // int result = 10 / 0; // Exception 발생
            ExceptionTest t = null;
            System.out.println(t.toString());
        } catch (ArithmeticException e) {
            // 발생한 예외에 대한 처리코드가 나온다.
            System.out.println(&quot;처리 완료&quot;);
        } catch (NullPointerException e) {
            System.out.println(&quot;NullPointer 처리 완료&quot;);
        } finally {
            System.out.println(&quot;finally는 무조건 수행&quot;);
        }

        // Exception이 발생하면 해당 Exception에 대한
        // 클래스를 찾아서 Exception 객체를 생성한다.
        // (java.lang.ArithmeticException)
        // 자동으로 생성된 이 객체를 프로그램적으로 처리를 안해주면
        // 프로그램 비정상 종료!
        // Exception Handling 해서 강제 종료를 하지 않는다.
        System.out.println(&quot;이 문장 출력되나요?&quot;); // 프로그램의 비정상 종료

    }
}
</code></pre>
<ul>
<li>추가적으로 예외 상황을 만들고 싶으면 어떻게 해야 할까?<ul>
<li>내가 예외 상황을 새롭게 정의하고 싶다면</li>
<li>그러면 당연히 Exception class를 상속해서 우리 class를 정의하면 된다.</li>
<li>is-a 관계에 의해 우리가 새로운 Exception을 정의할 수 있다.</li>
</ul>
</li>
<li><strong>사용자 정의 Exception</strong></li>
</ul>
<pre><code class="language-java">package test;

class MyException extends Exception {

}

public class ExceptionTest2 {
    public static void main(String[] args) {
        try {
            throw new MyException();
        } catch (Exception e) {
            System.out.println(&quot;사용자 정의 Exception 발생&quot;);
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] java.lang.Object class, String, Array, ArrayList, HashMap, HashSet]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-java.lang.Object-class-String-Array-ArrayList-HashMap-HashSet</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-java.lang.Object-class-String-Array-ArrayList-HashMap-HashSet</guid>
            <pubDate>Thu, 04 Apr 2024 07:22:35 GMT</pubDate>
            <description><![CDATA[<h2 id="1-javalangobject-class">1. java.lang.Object class</h2>
<ul>
<li>모든 class의 최상위 class</li>
<li>몇 가지 주요한 method를 제공한다.</li>
<li>여기서는 <strong><code>equals()</code></strong> 와 <strong><code>toString()</code></strong> 에 대해 알아보자.</li>
<li><strong><code>equals()</code></strong></li>
</ul>
<pre><code class="language-java">package test;

public class Student {

    // field
    private String name;
    private int age;

    // constructor
    public Student() {
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    // getter &amp; setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // method
    @Override
    public boolean equals(Object obj) {
        // 인자로 들어온 instance가 equals method를 가지고 있는
        // instance의 내용과 같으면 같은 객체로 판별하는 로직을 작성하면 된다.
        // 당연히 처음은 두 instance의 type을 똑같이 맞춰야 한다.
        Student target = (Student)obj;
        boolean result = false;
        if(this.getName() == target.getName() &amp;&amp; this.getAge() == target.getAge()) {
            result = true;
        }
        return result;
    }
}

class MyMain {
    public static void main(String[] args) {
        Student s1 = new Student(&quot;홍길동&quot;, 20);
        Student s2 = new Student(&quot;홍길동&quot;, 20);

        boolean result = s1 == s2; // 서로 인스턴스 값이 같은지?
        System.out.println(result); // false
        System.out.println(s1.equals(s2));
    }
}</code></pre>
<ul>
<li><strong><code>toString()</code></strong></li>
</ul>
<pre><code class="language-java">package test;

public class Student {

    // field
    private String name;
    private int age;

    // constructor
    public Student() {
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    // getter &amp; setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // method
    @Override
    public boolean equals(Object obj) {
        // 인자로 들어온 instance가 equals method를 가지고 있는
        // instance의 내용과 같으면 같은 객체로 판별하는 로직을 작성하면 된다.
        // 당연히 처음은 두 instance의 type을 똑같이 맞춰야 한다.
        Student target = (Student)obj;
        boolean result = false;
        if(this.getName() == target.getName() &amp;&amp; this.getAge() == target.getAge()) {
            result = true;
        }
        return result;
    }

    @Override
    public String toString() {
        return this.getName() + &quot; : &quot; + this.getAge();
    }
}

class MyMain {
    public static void main(String[] args) {
        Student s1 = new Student(&quot;홍길동&quot;, 20);

        System.out.println(s1);
        // toString() 오버라이딩 X -&gt; 메모리 주소값이 나온다. test.Student@4554617c
        // toString() 오버라이딩 O -&gt; 홍길동 : 20
    }
}</code></pre>
<h2 id="2-string-class">2. String class</h2>
<ul>
<li>Java는 primitive type으로 총 8개의 데이터 타입을 제공한다.</li>
<li>정수형 4개, 실수형 2개, 논리형 1개, 문자 1개<ul>
<li>자바는 문자는 존재하지만, 문자열은 존재 X</li>
<li>자바스크립트 및 파이썬은 문자열은 존재하지만, 문자는 X</li>
</ul>
</li>
<li>즉, 문자열은 기본 타입으로 제공되지 않으므로 reference type으로 제공된다. 즉, class로 제공된다.</li>
<li>따라서 사용하기 불편하다.</li>
</ul>
<pre><code class="language-java">String a = new String(&quot;불편불편!!&quot;);

// 너무 불편하다. 그래서 다음과 같이 사용한다.

String b = &quot;편해편해!!&quot;;
String c = &quot;편해편해!!&quot;;
String d = new  String(&quot;불편불편!!&quot;); 

b= &quot;아이편해&quot;;
// 문자열은 불변이기 때문에 값을 수정할 수 없다. 새로 만들어야 한다.</code></pre>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/b01dc513-7a68-4212-a8e1-e7d84610fa1c/image.png" alt=""></p>
<h2 id="3-array">3. Array</h2>
<ul>
<li>Java 배열</li>
<li>배열은 같은 data type을 여러 개 저장할 수 있는 집합형 자료구조</li>
<li>기호는 [ ] 사용</li>
<li>저장 순서 존재. index 개념 존재</li>
<li>배열은 instance이고, 특수한 형태로 생성을 한다.</li>
</ul>
<pre><code class="language-java">int a = 100;

int[] arr = new int[6];</code></pre>
<h2 id="4-arraylist-class">4. ArrayList class</h2>
<pre><code class="language-java">package test;

import java.util.ArrayList;
import java.util.List;

class MyStudent {

}

public class ArrayListTest {
    public static void main(String[] args) {

        // ArrayList 객체를 만들어서 사용하자.
        // List 계열은 객체면 type에 상관없이 다 저장 가능하다.
        // 다른 reference data type들을 저장할 수 있다.
        // 그런데 실제로 구현하다보면 거의 예외없이
        // 같은 데이터 타입을 이용해서 사용하게 된다. (마치 배열처럼)
        List list = new ArrayList();
        list.add(&quot;홍길동&quot;); // 문자열 (오버라이딩 되어있다.)
        list.add(new MyStudent()); // class (오버라이딩 X)
        list.add(100); // integer (오버라이딩 되어있다.)
        // 100은 int형태의 primitive type이다.
        // 따라서 ArrayList 안에 저장될 수 없다.
        // 자바에는 primitive type에 각각 대응되는 wrapper class가 존재
        // list.add(100); =&gt; list.add(new Integer(100));
        // boxing 이라는 표현을 사용한다.
//        for(int i=0; i&lt;10; i++) {
//
//        }
        for(Object obj : list) {
            System.out.println(obj.toString());
        }

        List&lt;String&gt; myList = new ArrayList&lt;String&gt;();
        myList.add(&quot;홍길동&quot;);
        myList.add(&quot;신사임당&quot;);

        for(String str : myList) { // generic을 쓰면 type이 명시되어 있어 편리하다.
            System.out.println(str);
        }
    }
}</code></pre>
<h2 id="5-hashmap-class">5. HashMap class</h2>
<ul>
<li>key와 value 쌍으로 이루어진 집합형 자료구조
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/612eb4a9-2503-439a-bd36-bf18b35ebd01/image.png" alt=""></li>
</ul>
<pre><code class="language-java">package test;

import java.util.HashMap;
import java.util.Map;

public class HashMapTest {
    public static void main(String[] args) {
        // 상위타입 Map = 실제 구현 클래스 하위타입 HashMap
        Map&lt;String, String&gt; map = new HashMap&lt;String, String&gt;();

        map.put(&quot;1&quot;, &quot;안녕하세요!&quot;);
        map.put(&quot;2&quot;, &quot;하이하이&quot;);

        System.out.println(map.get(&quot;2&quot;));
    }
}</code></pre>
<h2 id="6-hashset-class">6. HashSet class</h2>
<ul>
<li>set은 바구니 같은 자료구조</li>
<li>저장되는 순서는 없다.</li>
<li>set은 중복 허용 X</li>
</ul>
<pre><code class="language-java">package test;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetTest {
    public static void main(String[] args) {

        Set&lt;String&gt; set = new HashSet&lt;String&gt;();

        set.add(&quot;홍길동&quot;);
        set.add(&quot;신사임당&quot;);
        set.add(&quot;홍길동&quot;);

        // Iterator 생성
        Iterator&lt;String&gt; iter = set.iterator();
        while(iter.hasNext()) { // 다음 것이 있는지 체크하고 있으면 출력
            System.out.println(iter.next());
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] final, abstract 추상 클래스, interface 인터페이스]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-final-abstract-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4-interface-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-final-abstract-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4-interface-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Wed, 03 Apr 2024 01:13:01 GMT</pubDate>
            <description><![CDATA[<h2 id="13-final-keyword">13. final keyword</h2>
<ul>
<li>field 앞에 final이 올 경우 : 해당 field의 값을 변경할 수 없다. (상수로 사용)</li>
<li>method 앞에 final이 올 경우 : 하위 class에서 해당 method를 overriding 할 수 없다.</li>
<li>class 앞에 final이 올 경우 : 해당 class를 아예 상속할 수 없다.</li>
</ul>
<h2 id="14-abstract-class추상-클래스">14. abstract class(추상 클래스)</h2>
<ul>
<li>abstract method를 1개 이상을 보유하고 있는 class는 반드시 abstract class로 지정해야 한다.</li>
<li>가장 큰 특징은 아직 완성되지 않은 class이기 때문에 instance 생성이 안된다.</li>
<li>사용 방법 : 추상 클래스를 상속받는 하위 클래스를 만들어서 추상 method를 overriding해서 사용하면 된다.</li>
<li>재활용성의 폭이 넓혀진다.<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>// class 안에 추상 메소드가 있으면 추상 클래스다.
public abstract class TestA {
    // field
    private int age;
    private String name;</p>
<pre><code>// constructor
public TestA() {
}

// constructor overloading
public TestA(int age, String name) {
    super();
    this.age = age;
    this.name = name;
}

// method
public void myFunc() {
    // method를 정의했다.
}

// 추상 (abstract method)
public abstract void sayHello(); // method를 선언했다.</code></pre><p>}</p>
<p>class MySubClass extends TestA {
    @Override
    public void sayHello() {</p>
<pre><code>}</code></pre><p>}</p>
<pre><code>
## 15. interface(인터페이스)
- class와 유사함. class의 아주 특별한 형태
- interface는 class 대용으로 사용한다. (특수한 경우)
- interface 안에 method가 있을 수 있다. (추상 method만 나올 수 있다.)
- 그렇기 때문에 일반적으로 public abstract는 생략해서 구현한다.
- interface 안에 field도 나올 수 있다. (상수만 사용할 수 있다.)
- 특성 상 당연히 public static으로 잡혀야 하며, 상수로 만들어야 해서 final을 사용한다.
- 그래서 public static final은 생략이 가능하다.
- 하위 클래스에서 상위 클래스를 ~~ 한다.
    - 클래스 - 상속 / 인터페이스 - 구현
- 하위 class에서 interface를 구현해서 사용하면 된다.
- 하나의 인터페이스를 확장된 인터페이스를 만들려면 extends를 쓴다.
- 하나의 인터페이스를 구현하려면 implements를 쓴다.
- class의 확장과 다르게 interface는 다중 구현이 가능하다.
- is-a relation 관계가 당연히 성립한다.
```java
package test;

public interface MyInterface {

    // field
    int MY_NUM = 100;
    // public static final int MY_NUM = 100;
    // 모든 field에 public, static, final 이 다 붙어야 해서 생략 가능

    // method
    // public abstract void myFunc();
    void myFunc();
    // 인터페이스에는 모든 메소드에 abstract이 다 붙어야 해서 생략 가능
    // 즉, 추상 메소드만 넣을 수 있다.
    // method는 선언만 한다.
}

// MyClass1 부분과 MyInterface 부분이 같으면 extends
// MyClass1 부분과 MyInterface 부분이 다르면 implements
// 콤마찍고 인터페이스(MyInterface 부분) 여러 개 동시 구현 가능
class MyClass1 implements MyInterface {
    @Override
    public void myFunc() {
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 상속, IS-A 관계, 오버라이딩, this & super, this() & super()]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-%EC%83%81%EC%86%8D-IS-A-%EA%B4%80%EA%B3%84-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9-this-super-this-super</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-%EC%83%81%EC%86%8D-IS-A-%EA%B4%80%EA%B3%84-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9-this-super-this-super</guid>
            <pubDate>Tue, 02 Apr 2024 07:45:36 GMT</pubDate>
            <description><![CDATA[<h2 id="9-inheritance">9. Inheritance</h2>
<ul>
<li>상속은 부모 class가 가지고 있는 내용을 자식 class가 물려 받는 개념이다.</li>
<li>그래서 매번 class를 작성할 때 처음부터 작성하는 게 아니라 기존 클래스를 확장해서 작성하는 개념이다.</li>
<li>클래스의 계층 구조도 생긴다.</li>
<li>부모 클래스, parent class, upper class, <strong><code>super class</code></strong></li>
<li>자식 클래스, child class, <strong><code>sub class</code></strong></li>
</ul>
<h3 id="91-상속이-필요한-이유">9.1 상속이 필요한 이유</h3>
<p><img src="https://velog.velcdn.com/images/jiyoon9-velog/post/ea0dd41b-54ec-48a7-8244-dad7e2ebdf37/image.png" alt="">
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/74c3c3cb-7972-40e1-8fc9-7c724c0eb64a/image.png" alt=""></p>
<ul>
<li>코드로 상속 표현하기</li>
<li>keyword ⇒ extends 활용</li>
<li>Java는 단일 상속만 지원한다.</li>
<li>상속은 항상 좋을까?<ul>
<li>클래스 간 결합도가 증가한다.</li>
<li>상속은 class 간의 결합도를 증가시킨다. (tightly coupled)</li>
<li>그로 인해서 클래스의 재활용성을 낮추게 된다.</li>
</ul>
</li>
</ul>
<h3 id="92-is-a-relationshipis-a-관계-개념">9.2 is-a relationship(IS-A 관계) 개념</h3>
<ul>
<li>⇒ sub class is a super class</li>
<li>이 말의 의미는 sub class가 super class와 같으니까..</li>
<li>sub class를 써야 하는 자리에 super class를 사용할 수 있다.</li>
<li>포유류, 사람… 당연히 포유류가 상위 클래스 사람은 하위 클래스</li>
<li>사람 is a 포유류 (O)</li>
<li>포유류 is a 사람 (X)</li>
<li>다형성 : 같은 객체를 reference variable의 type을 변경시킴으로 인해 다른 형태로 객체를 사용하는 방법</li>
</ul>
<h2 id="10-method-overriding">10. (method) overriding</h2>
<ul>
<li>하위 클래스에서 상속받은 상위 클래스의 method를 재 정의해서 사용하는 방법</li>
<li>만약 field를 하위 클래스에서 재 정의해서 사용하게 되면 이는 shadow라고 표현한다. (잘 일어나지 않는다.)</li>
<li>부모 클래스<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>public class SuperClass { // extends java.lang.Object 최상위로 항상 상속</p>
<pre><code>int a = 100;
String b = &quot;여기는 super class&quot;;

public SuperClass() { // 항상 인자 없는 생성자를 만들어야 한다.
    super();
}

public void myFunc() {
    System.out.println(&quot;super&quot;);
}</code></pre><p>}</p>
<pre><code>- 자식 클래스

```java
package test;

public class SubClass extends SuperClass {

    // 추가적인 field와 method를 정의하면 된다.
    int a = 5000; // shadow
    int b = 500;

    public SubClass() {
        this(10); // int형을 가지고 있는 생성자를 호출
    }

    public SubClass(int k) {
        // 현재 class가 최상위 클래스인지 확인하고 아니면
        // 상위 클래스의 instance를 만드는 코드
        // SuperClass(); 이건 못 쓰고 대신 super을 쓴다.
        super(); // 상위 클래스를 찾아서 상위 클래스의 생성자를 호출하는 코드
    }

    @Override
    public void myFunc() {
        System.out.println(&quot;여기는 sub class 입니다.&quot;);
    }
}
</code></pre><pre><code class="language-java">package test;

public class Main {
    public static void main(String[] args) {

        // instance를 생성하자.
        SubClass sub = new SubClass();
        System.out.println(sub.a); // 5000
        sub.myFunc(); // 여기는 sub class 입니다.

    }
}</code></pre>
<ul>
<li>overriding에서 조심해야 할 점은 <strong><code>dynamic binding</code></strong>이 발생한다.<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>public class Main {
    public static void main(String[] args) {</p>
<pre><code>    // instance를 생성하자.
    // 동적 바인딩
    // 메소드는 오버라이딩되어 있으면 오버라이딩 된 것을 찾아 출력한다.
    SuperClass sub = new SubClass();
    System.out.println(sub.a); // 100
    sub.myFunc(); // 여기는 sub class 입니다.
}</code></pre><p>}</p>
<pre><code>
## 11. this, super, this(), super()
- this : 현재 사용하고 있는 객체에 대한 reference
- super : 현재 사용하고 있는 객체에 대한 reference (상위 타입의 객체를 지칭)
- super() : 상위 클래스의 생성자를 호출
- this() : 내가 가진 오버로딩된 해당 클래스의 다른(인자의 개수나 타입이 다른) 생성자를 호출

## 12. 연습문제
- 부모 클래스
```java
package test;

public class SuperClass2 {
    static int staticCall(String msg) {
        System.out.println(msg);
        return 0;
    }

    int a = staticCall(&quot;1번 문장&quot;);
    static int b = staticCall(&quot;2번 문장&quot;);

    public SuperClass2() {
        staticCall(&quot;3번 문장&quot;);
    }

    public SuperClass2(int i) {
        this();
        staticCall(&quot;4번 문장&quot;);
    }

    public void myFunc() {
        System.out.println(&quot;5번 문장&quot;);
    }
}</code></pre><ul>
<li>자식 클래스<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>public class Exam01_InheritanceOrder extends SuperClass2 {</p>
<pre><code>int c = staticCall(&quot;6번 문장&quot;);
static int d = staticCall(&quot;7번 문장&quot;);
// 상위 클래스의 static 먼저 출력, 다음으로 하위 클래스 static 출력

public Exam01_InheritanceOrder() {
    super(100);
    staticCall(&quot;8번 문장&quot;);
    super.myFunc();
}

@Override
public void myFunc() {
    System.out.println(&quot;9번 문장&quot;);
}

public static void main(String[] args) {
    System.out.println(&quot;10번 문장&quot;);
    SuperClass2 obj = new Exam01_InheritanceOrder();
    obj.myFunc();
}</code></pre><p>}</p>
<pre><code></code></pre><p>2번 문장
7번 문장
10번 문장
1번 문장
3번 문장
4번 문장
6번 문장
8번 문장
5번 문장
9번 문장
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 접근 제어자, 캡슐화, 정보 은닉, static block]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-%EC%A0%91%EA%B7%BC-%EC%A0%9C%EC%96%B4%EC%9E%90-%EC%BA%A1%EC%8A%90%ED%99%94-%EC%A0%95%EB%B3%B4-%EC%9D%80%EB%8B%89-static-block</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-%EC%A0%91%EA%B7%BC-%EC%A0%9C%EC%96%B4%EC%9E%90-%EC%BA%A1%EC%8A%90%ED%99%94-%EC%A0%95%EB%B3%B4-%EC%9D%80%EB%8B%89-static-block</guid>
            <pubDate>Tue, 02 Apr 2024 07:37:38 GMT</pubDate>
            <description><![CDATA[<h2 id="7-access-modifier-접근-제어자">7. Access Modifier (접근 제어자)</h2>
<ul>
<li>public<ul>
<li>이 키워드는 field, method, constructor, class 앞에 붙을 수 있다.</li>
<li>package에 상관없이 자유롭게 access할 수 있도록 해주는 접근 제어자</li>
<li>class가 public이라고 해서 변수를 마음대로 쓸 수 있는 것이 아니다.</li>
<li>변수 역시 public이어야 한다.</li>
</ul>
</li>
<li>default (키워드 아님, 직접 명시하지 않음)<ul>
<li>field, method, constructor, class에 선언할 수 있다.</li>
<li>같은 package의 다른 class에 의해 사용될 수 있다.</li>
<li>다른 package에서는 못 쓴다.</li>
</ul>
</li>
<li>private<ul>
<li>field, method, constructor에 선언할 수 있다.</li>
<li>해당 field, method, constructor를 같은 class내에서만 access 가능하도록 선언한다.</li>
<li>constructor 앞에 붙일 때는 싱글톤 패턴일 때 사용</li>
</ul>
</li>
</ul>
<h3 id="싱글톤-패턴">싱글톤 패턴</h3>
<pre><code class="language-java">public class Singleton {
    // 정적 참조 변수(싱글톤 객체를 담을 변수)
    private static Singleton instance;

    // private 생성자로 외부에서 인스턴스 생성을 막습니다.
    // private 생성자
    private Singleton() {
    }

    // 정적 메서드를 통해 단일 인스턴스를 반환합니다.
    // getInstance()
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}</code></pre>
<h3 id="71-encapsulation캡슐화">7.1 Encapsulation(캡슐화)</h3>
<ul>
<li>class는 객체가 가지고 있는 특징(값), 기능(함수)를 하나의 단위로 묶어놓은 개념이다.</li>
<li>class가 encapsultation한 결과이다.</li>
</ul>
<h3 id="72-information-hiding정보-은닉">7.2 Information Hiding(정보 은닉)</h3>
<ul>
<li>이런 class 안에는 값과 기능이 들어가 있다.</li>
<li>여기서는 값이 더 중요하다.</li>
<li>외부에서 이 값을 함부로 변경하는 것은 당연히 막아야 한다.</li>
<li>그래서 class 내부에서만 값을 수정할 수 있고, 외부에서 함부로 값을 변경할 수 없도록 데이터를 보호해야 하는데 이 개념을 Information Hiding(정보 은닉)이라고 한다.</li>
</ul>
<h3 id="73-구현-방법">7.3 구현 방법</h3>
<ul>
<li>Java 언어에서는 이 개념을 access modifier로 구현한다.</li>
<li>private를 이용해서 field를 선언한다. (특별한 이유가 없는 한)</li>
<li>method를 이용해서 해당 field를 제어하는 식으로 class를 design을 한다.</li>
<li>추가적으로 외부 class(instance)에서 private으로 설정된 값을 알아가거나 설정하기 위해 특수한 형태의 method를 이용하게 되는데 getter / setter 이라고 한다.</li>
</ul>
<h2 id="8-static-block">8. static block</h2>
<ul>
<li>class가 로드된 후 바로 수행되는 코드 block이고 main()보다 먼저 수행된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] JVM 메모리 구조, 오버로딩, 패키지]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-JVM-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9-%ED%8C%A8%ED%82%A4%EC%A7%80</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-JVM-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9-%ED%8C%A8%ED%82%A4%EC%A7%80</guid>
            <pubDate>Tue, 02 Apr 2024 07:34:26 GMT</pubDate>
            <description><![CDATA[<h2 id="4-jvm의-메모리-구조">4. JVM의 메모리 구조</h2>
<ul>
<li>register : 프로그램의 실행 포인터를 저장하고 관리한다. 신경 쓸 필요가 없다.</li>
<li>Runtime Constant Pool : 상수들을 위한 저장 공간. 역시 신경 쓸 필요가 없다.</li>
<li>Method Area<ul>
<li>클래스 자체에 대한 정보가 들어가 있는 공간.</li>
<li>당연히 클래스 안에 정의된 method에 대한 실행 코드도 여기 존재한다.</li>
<li>해당 클래스가 사용될 때 한번 동적으로 클래스에 대한 정보가 올라간다.</li>
<li>클래스가 처음 사용되는 시점 딱 1번 해당 정보가 메모리에 올라간다.</li>
</ul>
</li>
<li>Heap<ul>
<li>instance의 생성되는 메모리 공간.</li>
<li>instance variable의 공간이 생성된다.</li>
<li>또한, method의 실행 포인터를 들고 있다.</li>
</ul>
</li>
<li>Call Stack(일반적으로 stack이라고 함)<ul>
<li>스택은 메소드가 호출되면 stack 영역에 해당 메소드를 위한 공간이 생성된다.</li>
<li>지역 변수가 이 공간 안에 있다.</li>
<li>당연히 method의 수행이 끝나면 해당 영역은 pop되어서 없어지고 안에 있는 지역변수 역시 공간이 날라간다.</li>
</ul>
</li>
</ul>
<h3 id="41-코드-실행">4.1 코드 실행</h3>
<ul>
<li>코드 실행으로 어떻게 메모리에 정보가 들어가는지 알아보자.</li>
<li>코드 작성이 끝나면 컴파일하자.</li>
<li>javac.exe MyTest.java ⇒ 그 결과로 MyTest.class 파일이 생성된다.</li>
<li>java.exe MyTest ⇒ JVM이 bytecode를 읽어서 실행한다.
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/fcc1c1ca-919b-4a30-947a-11f75df0519e/image.png" alt=""></li>
<li>예제<pre><code class="language-java">package test;
</code></pre>
</li>
</ul>
<p>public class InstanceTest {
    static int a = staticCall(&quot;1번 출력&quot;);
    int b = staticCall(&quot;2번 출력&quot;);</p>
<pre><code>public static int staticCall(String msg) {
    System.out.println(msg);
    return 100;
}

public InstanceTest() {
    this.b = staticCall(&quot;3번 출력&quot;);
}

public static void main(String[] args) {
    System.out.println(&quot;4번 출력&quot;);
    int c = staticCall(&quot;5번 출력&quot;);
    InstanceTest d = new InstanceTest();
}</code></pre><p>}</p>
<pre><code></code></pre><p>1번 출력
4번 출력
5번 출력
2번 출력
3번 출력</p>
<p>```</p>
<ul>
<li>this는 현재 사용하고 있는 reference의 객체, 지금 만들어지는 그 객체를 말함.</li>
</ul>
<h2 id="5-method-overloading">5. method overloading</h2>
<h3 id="51-연산자-오버로딩">5.1 연산자 오버로딩</h3>
<ul>
<li><ul>
<li>→ 당연히 숫자를 더하는 기호다. (앞과 뒤에 숫자가 나와서 숫자를 더한다.)</li>
</ul>
</li>
<li>“문자열” + 10 → 문자열 연결하는 기호로 의미가 변한다.</li>
</ul>
<h3 id="52-오버로딩">5.2 오버로딩</h3>
<blockquote>
<p>💡 메소드의 이름은 같지만 만약 메소드의 인자의 개수나 인자의 type이 다른 경우 서로 다른 method로 구분되어서 사용할 수 있다.</p>
</blockquote>
<ul>
<li>생성자 오버로딩도 하고, 메소드 오버로딩도 된다.</li>
<li>이렇게 여러 개의 생성자를 사용하는 생성자 오버로딩은 각기 다른 방식으로 인스턴스를 초기화할 필요가 있기 때문이다.</li>
<li>따라서 하나의 클래스 안에는 여러 개의 생성자가 존재할 수 있다.</li>
</ul>
<h2 id="6-package와-import">6. package와 import</h2>
<h3 id="61-package">6.1 package</h3>
<ul>
<li>package는 클래스를 용도별로, 종류별로 묶어주는 논리적인 단위이다.</li>
<li>유지보수와 재활용성을 높이기 위해서 서로 관련 있는 클래스를 묶어서 관리한다.</li>
<li>당연히 물리적으로는 package 이름으로 되어 있는 폴더를 만들어서 그 안에 class를 저장한다.</li>
<li>만약 package 구문을 사용하지 않으면 클래스는 default package 라는 것으로 묶인다.</li>
<li>package는 계층 구조로 사용할 수 있다. 이 계층 구조를 표현할 때, “.” 를 이용한다.</li>
</ul>
<h3 id="62-import">6.2 import</h3>
<ul>
<li>import는 다른 package에 있는 class를 가져다가 사용하기 위해서 사용하는 구문이다.</li>
<li>자바 코드는 거의 예외 없이 package 구문이 나온다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 객체지향(클래스, 인스턴스, 생성자, 패키지)]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</guid>
            <pubDate>Tue, 02 Apr 2024 05:11:51 GMT</pubDate>
            <description><![CDATA[<h2 id="1-class">1. class</h2>
<ul>
<li>class를 간단히 정의하자면<ol>
<li>객체 모델링의 수단(전체적인 프로그램 설계 시)</li>
<li>instance를 생성하는 수단(프로그래밍 실행 관점)</li>
<li>ADT(자료구조 측면에서 프로그램을 바라볼 때)</li>
</ol>
</li>
</ul>
<h2 id="2-instance">2. instance</h2>
<ul>
<li>class에 정의된 field(변수), method(함수)를 사용하기 위해서 메모리에 공간을 확보한 것</li>
</ul>
<h2 id="3-constructor생성자">3. constructor(생성자)</h2>
<ul>
<li>class로 부터 instance를 생성하기 위해서 호출되는 것.</li>
<li>당연히 class 내부에 위치한다.</li>
<li>모든 class는 무조건 1개의 이상의 constructor를 가지고 있다.</li>
</ul>
<h3 id="31-생성자의-특징">3.1 생성자의 특징</h3>
<ul>
<li><p>constructor은 이름이 클래스의 이름과 같다.</p>
<ul>
<li><p>생성자(인스턴스의 초기화)</p>
<pre><code class="language-java">public class Car {
  private String color;
  private String model;

  // 기본 생성자
  public Car() {
      this.color = &quot;Red&quot;;
      this.model = &quot;Toyota&quot;;
  }

  // 매개변수를 받는 생성자
  public Car(String color, String model) {
      this.color = color;
      this.model = model;
  }

  // 기타 메서드
}</code></pre>
</li>
</ul>
</li>
<li><p>메소드는 아니다. (메소드는 해당 메소드가 만드는 리턴 타입이 명시가 되어야 한다.)</p>
<ul>
<li>리턴 타입</li>
</ul>
<ol>
<li><p><strong>기본형(primitive types)</strong>: <strong><code>int</code></strong>, <strong><code>double</code></strong>, <strong><code>boolean</code></strong> 등과 같은 기본 데이터 타입을 리턴할 수 있다.</p>
</li>
<li><p><strong>참조형(reference types)</strong>: 클래스, 인터페이스, 배열 등과 같은 참조형 데이터 타입을 리턴할 수 있다.</p>
</li>
<li><p><strong>void</strong>: 메서드가 아무런 값을 반환하지 않을 경우 <strong><code>void</code></strong>를 리턴 타입으로 지정한다. 이는 메서드가 작업을 완료한 후 어떠한 값도 반환하지 않음을 의미한다.</p>
<pre><code class="language-java">public int add(int a, int b) {
 return a + b;
}</code></pre>
<pre><code class="language-java">public void greet() {
 System.out.println(&quot;Hello!&quot;);
}</code></pre>
</li>
</ol>
</li>
<li><p>new 라는 키워드와 함께 호출되며 주로 하는 일은 instance의 초기화를 담당한다.</p>
</li>
</ul>
<h3 id="32-클래스와-패키지">3.2 클래스와 패키지</h3>
<ul>
<li>클래스를 묶어 놓은 논리적인 단위, 유사한 종류의 클래스를 꾸러미로 묶어 놓음, 클래스의 집합 → 패키지</li>
<li>패키지는 일반적으로 소문자로 이름을 정함</li>
<li>패키지는 계층구조를 가질 수 있다. 점(.)을 활용해서!</li>
<li>public이 붙은 class는 파일 이름 역시 해당 class의 이름으로 정해야 한다.</li>
<li>한 파일에는 public이 붙은 class는 하나만 존재해야 한다.</li>
<li>생성자를 안 쓰면 자동으로 생성자를 넣어주긴 한다.</li>
<li><strong><code>예제 1</code></strong><pre><code class="language-java">// package는 관련 있는 class들을 하나로 묶는 논리적인 단위이고
// 물리적으로는 폴더로 표현된다.
// 거의 예외없이 package는 사용을 한다.
</code></pre>
</li>
</ul>
<p>// 하나의 자바 파일에 public이 붙은 class는
// 두 개 이상 존재할 수 없다. (하나만 있어야 한다.)
// 만약, public class가 존재하면 파일명은 반드시
// public class 이름으로 설정해야 한다.</p>
<p>package test;</p>
<p>public class HelloWorld {</p>
<pre><code>// field들
int age;

// constructor들
// constructor는 이름이 클래스 이름과 같다.
// 모양은 method와 유사하다. (리턴 타입 존재 X)
// constructor는 instance의 초기화를 담당하는 일을 주로 한다.
public HelloWorld() {

}
// 만약 생성자를 직접적으로 명시하지 않으면
// javac compiler가 소스 코드를 bytecode로 컴파일 할 때
// default constructor를 자동으로 삽입한다.
// default constructor는 인자도 없고 하는 일도 없는 생성자다.
// default constructor는 반드시 작성하는 버릇을 들이자.
// 그러고 오버로딩해서 여러 생성자를 만들던가 한다.

// method들
public void sayHello() {

}

// 프로그램의 entry point 진입점
public static void main(String args[]) {
    System.out.println(&quot;안녕하세요~&quot;);

    // 인스턴스 만들기
    // 메모리 공간의 heap 영역에 대부분 인스턴스가 만들어진다.
    // java는 강타입 언어기 때문에 무조건 데이터 타입을 명시해 주어야 한다.
    // a는 reference variable이라고 부른다.
    // Heap 영역의 instance의 시작 주소를 가지고 있기 때문에 그렇다.
    HelloWorld a = new HelloWorld();
}</code></pre><p>}</p>
<pre><code>- **`예제 2`**
```java
package test;

public class MyTest {

    // static block
    // 클래스가 로드될 때 가장 먼저 수행된다.
    static {

    }

    // 필드들
    // a라는 변수에 100을 넣을 것이다.
    // 넣는 것에서 끝나는 것이 아니라, 클래스로부터 인스턴스를 만들어야 함.
    // 인스턴스가 있어야 사용할 수 있는 변수
    // 즉, instance variable이라고도 한다.
    // instance variable은 메모리 heap 영역에 만들어진다.
    public int a = 100;

    private static int b = 200; // java에는 전역 변수는 따로 없다.
    // class variable
    // static이 붙으면 Method Area에 올라간다.
    // heap에 instance가 없어도 사용할 수 있다.
    // instance에는 b가 저기 있다고 알려주는 참조 값이 있다.

    private int c = 300;

    // 생성자들
    public MyTest() {

    }

    MyTest(int k) {

    }

    // 메소드들

    public static void main(String args[]) {
        // 위에 있는 a라고 되어 있는 field를 사용하려면
        // 당연히 instance가 존재해야 한다.
        MyTest obj = new MyTest();

        // obj 라는 시작 주소값이 들어있는 참조 변수 = 객체
        // obj 라는 reference variable을 이용해서 Heap 영역에
        // 생성된 instance를 사용할 수 있다.
        // reference variable을 이용해서 instance를 사용할 때
        // 우리가 이용하는 연산자가 있다.
        // dot operator(.)
        System.out.println(&quot;a의 값은 : &quot; + obj.a);
        // import java.lang.*; 을 원래 추가해야하지만 javac 컴파일러가 자동으로 추가해준다.

        // 지역 변수는 메소드가 호출될 때 만들어지고
        // stack 영역에 공간이 잡히고
        // 메소드가 끝나면 pop되면서 사라지는 변수
        int k = 200; // 지역 변수(local variable)
        // 지역 변수는 stack 영역에 만들어진다.
    }

}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Data Type 데이터 타입]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-Data-Type-ui716s8t</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-Data-Type-ui716s8t</guid>
            <pubDate>Mon, 01 Apr 2024 08:32:19 GMT</pubDate>
            <description><![CDATA[<h2 id="1-변수variable">1. 변수(Variable)</h2>
<ul>
<li>프로그램을 잘 하려면 데이터를 잘 다뤄야 한다.</li>
<li>데이터를 효율적으로 사용하기 위해서는 자료구조를 잘 알아야 한다.</li>
<li>array, list, map, set, class</li>
<li>자바는 collection(list, map, set), 파이썬은 list, 자바스크립트는 array</li>
<li>시간적인 효율성을 추구하기 위해서는 알고리즘을 사용한다.</li>
<li>Java 언어는 강타입 언어다.</li>
<li>변수를 만들 때 타입을 지정해서 만든다.</li>
</ul>
<h2 id="2-식별자-명명-규칙">2. 식별자 명명 규칙</h2>
<ul>
<li>자바는 대소문자 구분을 한다.</li>
<li>식별자의 길이 제한이 없다.</li>
<li>당연히 예약어는 사용할 수 없다. (if, for, String, …)</li>
<li>숫자로 시작할 수 없다.</li>
<li>특수문자 사용할 수 있다.( $, _ )</li>
<li>클래스 이름은 첫 글자 항상 대문자로 시작하고 두 단어 이상으로 구성된 경우, 두 번째 단어의 첫 글자도 대문자로 시작한다. (PascalCase)</li>
<li>field명이나 method명은 첫 글자는 소문자로 시작하고, 두 단어 이상으로 구성된 경우 두 번째 단어의 첫 글자도 대문자로 시작한다. (camelCase)</li>
<li>상수의 이름은 모두 대문자로 하고, 두 단어 이상으로 구분된 경우 단어의 연결은 _를 이용한다. (snakeCase)</li>
</ul>
<h2 id="3-데이터-타입">3. 데이터 타입</h2>
<ul>
<li>자바의 데이터 타입은 크게 2가지이다.</li>
<li>primitive data type 원시 타입(기본형) - 실제 값이 들어감<ul>
<li>원시 타입으로 선언된 변수 안에는 실제 데이터가 저장된다.</li>
<li>정수형 4개, 실수형 2개, 문자형 1개, 논리형 1개</li>
<li>총 8개의 데이터 타입 제공</li>
<li>byte, short, int, long(정수형) - int 많이 씀(효율성 측면)</li>
<li>float, double(실수형) - double 많이 씀.</li>
<li>char(문자) - 1byte, 유니코드 문자 정수가 들어가서.. 변환됨, 즉, 연산이 가능함.</li>
<li>boolean(논리) - true, false</li>
</ul>
</li>
<li>reference data type 참조 타입(참조형) - 메모리 주소값이 들어감(정확히는 해시 코드값)<ul>
<li>참조 타입으로 지정된 변수 안에는 메모리에 대한 해쉬 코드 값이 저장된다.</li>
<li>instance에 대한 메모리 주소 값을 가지고 있다.</li>
<li>class를 reference data type이라고 한다.</li>
</ul>
</li>
</ul>
<h2 id="4-형변환type-casting">4. 형변환(Type Casting)</h2>
<ul>
<li>( )을 이용해서 형변환을 하면 된다.</li>
<li>double a = (double)10</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 특징, JVM, JDK, JRE, 객체지향, 클래스, 인스턴스]]></title>
            <link>https://velog.io/@jiyoon9-velog/Java-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@jiyoon9-velog/Java-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 01 Apr 2024 08:27:32 GMT</pubDate>
            <description><![CDATA[<h2 id="1-java의-특징">1. Java의 특징</h2>
<ul>
<li>JVM만 있으면 플랫폼과 상관없이 플랫폼에 독립적인 언어로써 돌아간다.</li>
<li>C 계열 언어보다는 배우기 쉽다.</li>
<li>메모리 관리를 하지 않아도 된다.<ul>
<li>가비지컬렉터 - 메모리 관리를 자동적으로 수행함. 사용되지 않는 것이 자동으로 반환된다. (메모리 프레쉬 기능)</li>
<li>코드 자체 로직에 대해 집중할 수 있다.</li>
</ul>
</li>
<li>멀티쓰레드를 Java 언어 차원에서 지원한다.</li>
<li>강타입언어(Strong Type 언어)</li>
</ul>
<h2 id="2-jvmjava-virtual-machine">2. JVM(Java Virtual Machine)</h2>
<ul>
<li>플랫폼에 종속적, 독립적인 형태</li>
<li>C로 구현되어 있다.</li>
<li>JVM ↔ Java 애플리케이션 ↔ JVM ↔ OS(Windows) ↔ 컴퓨터(하드웨어)</li>
<li>일반 애플리케이션 ↔ OS(Windows) ↔ 컴퓨터(하드웨어)</li>
<li>참고
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/0575195c-38f6-4258-bc4b-23c38e543beb/image.png" alt="">  </li>
<li>C보다 느리다.</li>
<li>예전에는 속도가 문제가 되었는데 지금은 JIT와 같은 기술이 발전되어서 속도 문제 거의 해결!<ul>
<li>JIT 컴파일(just-in-time compilation) 또는 동적 번역(dynamic translation)은 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법이다.</li>
</ul>
</li>
<li>머신마다 쓰는 기계어가 다르기 때문에.. 컴파일 과정을 거친다..</li>
<li>컴파일 하면 바이트 코드가 나온다. 그럼 JVM이 이걸 읽고 기계어로 변환하여 머신이 읽는다.</li>
</ul>
<h2 id="3-jdk-jre-jvm">3. JDK, JRE, JVM</h2>
<ul>
<li>JVM <strong>⊂</strong> JRE <strong>⊂</strong> JDK</li>
<li>JDK Java Development Kit (JDK안에 JRE가 들어간다.)<ul>
<li>Java를 사용하기 위한 필요한 모든 기능을 갖춘 Java용 SDK이다.</li>
<li>JRE 포함 컴파일러 javac와 jdb, javadoc 등의 도구도 있다.</li>
<li>즉, JDK는 프로그램을 생성하고 컴파일할 수 있다.</li>
</ul>
</li>
<li>JRE Java Runtime Environment (JRE안에 JVM이 들어간다.)<ul>
<li>JVM, Java Class Library (API), Java Command 및 기타 인프라를 포함한 컴파일된 Java 프로그램을 실행하는 데 필요한 패키지</li>
</ul>
</li>
<li>포함관계
<img src="https://velog.velcdn.com/images/jiyoon9-velog/post/7c3a4dea-c843-485c-9356-def4980094a2/image.png" alt=""></li>
<li>JDK 1.0부터 시작해서 버전업이 계속 되고 있다.</li>
<li>JDK 1.5 버전이 되었을 때 언어 자체가 한 단계 업그레이드가 됐다. → Java 5.0으로 명명</li>
<li>JDK 1.8은 당연히 Java 8이라고 부른다. (상당수가 Java 8을 기업에서 쓰고 있다.)<ul>
<li>Java 9부터 패키지의 상위 개념인 모듈 개념이 생긴다.</li>
<li>하위호환성 담보가 깨진다..</li>
<li>Java 11은 신규로 나온 곳이 많이 쓰고 있다고 함</li>
<li>수업은 Java 8로 진행한다.</li>
</ul>
</li>
<li>Java는 부분 유료<ul>
<li>기본 기능은 무료(GPL license) 여기에 오라클이 추가적으로 제공하는 글꼴, Java Web Start는 유료로 제공된다.</li>
</ul>
</li>
</ul>
<h2 id="4-객체지향의-기본적인-개념">4. 객체지향의 기본적인 개념</h2>
<ul>
<li>프로그래밍의 패러다임 변화부터 알아보자.</li>
<li>프로그래밍 방법론의 변화</li>
<li>함수형 프로그래밍 → 구조적 프로그래밍, 절차적 프로그래밍</li>
<li>객체지향 프로그래밍</li>
</ul>
<h3 id="41-절차적-프로그래밍">4.1 절차적 프로그래밍</h3>
<ul>
<li>절차적 프로그래밍의 특징<ul>
<li>프로그램을 기능별로 세분화해서 함수로 나눠서 프로그래밍을 하는 방식</li>
<li>프로그램을 기능 단위로 구현한다. 각 기능을 함수라는 실행 단위로 구현해서 그 함수를 모아 전체 프로그램을 완성</li>
<li>장점: 프로그램의 설계가 쉽다. → 개발이 쉽다. → 개발 기간이 단축된다. → 비용 절감</li>
<li>단점: 유지보수와 모듈(함수)의 재활용성이 떨어진다.</li>
<li>이 단점을 해결하기 위해 나온 프로그래밍 패러다임이 바로 객체지향 프로그래밍이다.</li>
</ul>
</li>
</ul>
<h3 id="42-객제지향-프로그래밍">4.2 객제지향 프로그래밍</h3>
<ul>
<li>객체지향 프로그래밍의 특징<ul>
<li>현실세계, 구성요소를 프로그래밍 적으로 표현한다.</li>
<li>각각의 객체로 표현하고 모델링한다.</li>
<li>구현하고자 하는 현실세계의 문제를 구성하고 있는 구성 요소를 파악하고 이 구성 요소를 프로그램적으로 모델링해서 해당 구성 요소들이 데이터를 주고 받는 형태를 프로그래밍하는 방법</li>
<li>장점: 프로그램의 유지보수와 재활용성에 장점이 있다.</li>
<li>단점: 설계와 구현이 상대적으로 어렵다.</li>
</ul>
</li>
<li>현실 세계의 문제를 구성하고 있는 구성 요소를 파악하는 작업을 해야 한다.<ul>
<li>Abstraction(추상화) 과정을 거쳐서 프로그램적으로 표현해야 하는 속성값, 행위로 표현한다.</li>
<li>클래스라는 단위로 속성값 - 변수, 행위 - 함수로 표현한다.</li>
<li>객체 모델링의 수단 - 클래스</li>
<li>속성값은 변수로, 행위는 함수로, 프로그램적으로 표현해야 한다.</li>
<li>이 2가지를 하나의 단위로 만들기 위해서 사용하는 개념이 바로 class.</li>
<li>그래서 class의 의미 중 하나는 바로 <strong><code>객체 모델링의 수단</code></strong></li>
<li>변수는 필드 field라고 부른다.</li>
<li>class 내부에는 변수에 해당하는 field, 함수에 해당하는 method가 존재한다.    </li>
</ul>
</li>
<li>인스턴스<ul>
<li>인스턴스화 Instanciation → 클래스로 표현한 것을 메모리 상에 할당을 해야 한다.</li>
<li>인스턴스: 메모리 공간</li>
<li>instance는 class 안에 정의된 변수(field)를 실제 메모리 영역에 공간을 확보한 것.</li>
<li>class는 <strong><code>instance를 만들어내기 위한 수단</code></strong></li>
<li>class도 하나의 데이터 타입 (ADT)</li>
<li>클래스는 추상 데이터 타입 Abstract Data Type ADT라고도 불린다.</li>
<li>class 안에 정의된 field를 이용해서 메모리 공간을 확보하고 해당 공간에 대한 데이터 타입은 당연히 class 명으로 설정해야 한다.</li>
<li>class는 하나의 데이터 타입.</li>
<li>즉, 우리가 임의로 만들 수 있는 데이터 타입이기 때문에 <strong><code>ADT(Abstract Data Type)</code></strong> 이라고도 불린다.</li>
<li>추상화의 결과로 나온 것이 결국 class이다.</li>
</ul>
</li>
<li>class란 무엇인가요?<ul>
<li>객체 모델링의 수단</li>
<li>인스턴스를 만들어내기 위한 수단</li>
<li>ADT</li>
</ul>
</li>
</ul>
<h2 id="5-java-program의-특징">5. Java program의 특징</h2>
<ul>
<li>우리가 자바 프로그램을 작성할 때<ul>
<li>원칙적으로 하나의 Java Source File에 하나의 class만 정의한다.<ul>
<li>재활용성 + 유지 보수 때문에!</li>
</ul>
</li>
</ul>
</li>
<li>소스 파일의 확장자는 .java를 사용</li>
<li>여러 개의 source file(여러 개의 class)가 모여서 하나의 Java application을 구성한다.</li>
<li>Java program의 entry point(진입점)는 main() method이다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>