<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>fogbow.juni.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 21 Dec 2022 03:27:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>fogbow.juni.log</title>
            <url>https://velog.velcdn.com/images/fogbow_juni/profile/c7a6902b-8a89-4dc6-a4bd-36d67f203200/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. fogbow.juni.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/fogbow_juni" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[SPRING] 스프링 레거시 프로젝트 오라클 클라우드 연동]]></title>
            <link>https://velog.io/@fogbow_juni/SPRING-%EB%A0%88%EA%B1%B0%EC%8B%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@fogbow_juni/SPRING-%EB%A0%88%EA%B1%B0%EC%8B%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%97%B0%EB%8F%99</guid>
            <pubDate>Wed, 21 Dec 2022 03:27:52 GMT</pubDate>
            <description><![CDATA[<p>또 애플실리콘칩(M1, M2)와 오라클 클라우드 그리고 스프링레거시와의 설정 잡기
저번처럼 ojdbc6으로는 클라우드 안되는 것 같고
ojdbc8로 클라우드 연동하려고 하는데
다른 ojdbc8.jar말고 다른 파일들이 필요했다!</p>
<p>그런데 이걸 생각 안하고 ojdbc6으로 그냥 오라클 클라우드에 접속하려니 당연히 오류가 남...</p>
<p>MVN Repository에서 dependency검색해서 pom.xml에 추가 해주니 잘 됨!</p>
<pre><code>        &lt;dependency&gt;
            &lt;groupId&gt;com.oracle.database.jdbc&lt;/groupId&gt;
            &lt;artifactId&gt;ojdbc8&lt;/artifactId&gt;
            &lt;version&gt;21.5.0.0&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;com.oracle.ojdbc&lt;/groupId&gt;
            &lt;artifactId&gt;oraclepki&lt;/artifactId&gt;
            &lt;version&gt;19.3.0.0&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;com.oracle.ojdbc&lt;/groupId&gt;
            &lt;artifactId&gt;osdt_cert&lt;/artifactId&gt;
            &lt;version&gt;19.3.0.0&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;com.oracle.database.security&lt;/groupId&gt;
            &lt;artifactId&gt;osdt_core&lt;/artifactId&gt;
            &lt;version&gt;19.3.0.0&lt;/version&gt;
        &lt;/dependency&gt;</code></pre><blockquote>
<p>  MVN Repository 링크!
 <a href="https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8/21.5.0.0">ojdbc8</a>
 <a href="https://mvnrepository.com/artifact/com.oracle.ojdbc/oraclepki/19.3.0.0">oraclepki</a>
 <a href="https://mvnrepository.com/artifact/com.oracle.ojdbc/osdt_cert/19.3.0.0">osdt_cert</a>
 <a href="https://mvnrepository.com/artifact/com.oracle.database.security/osdt_core/19.3.0.0">osdt_core</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥북 M1 STS3 설정 + 일상]]></title>
            <link>https://velog.io/@fogbow_juni/%EB%A7%A5%EB%B6%81-M1-STS3-%EC%84%A4%EC%A0%95-%EC%9D%BC%EC%83%81</link>
            <guid>https://velog.io/@fogbow_juni/%EB%A7%A5%EB%B6%81-M1-STS3-%EC%84%A4%EC%A0%95-%EC%9D%BC%EC%83%81</guid>
            <pubDate>Mon, 19 Dec 2022 14:36:26 GMT</pubDate>
            <description><![CDATA[<p>일단은 기록용으로...
11월초에 코로나걸리고 겨우쓰는 포스팅...
그동안 세미플젝도 서블릿 진도 다나가고(이거 회고도 해야함!) 포폴작업도 들어갔다.
드뎌 내일부터 레거시 스프링~~ 근데 STS3 설치하다가 또 안 됨 ㅋㅎㅎ..</p>
<p>아무튼 오류났는데 자바 버전 호환이겠거니...했는데 역시나
내 노트북은 맥북에어M2이다. 디비 설정도 그지같아 죽겠는데...
근데 사실 버전보다는 애플실리콘JDK를 뱉어내고 있었다.
그래서 인텔용JDK 11버전 다운 받아서 해결(STS3깔고 지우고 4깔고 지우고 이클립스 깔고 지우고 별 걸 다 함... 네시간 걸림)
zulu-11버전 사용해서 잡았다</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/3b7d097f-ca13-4b3c-bd04-8163379bfbd2/image.png" alt="">
자바 버전은 이거 사용했다!</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/d7b0becb-c7cf-4245-823b-c4cb5b59b981/image.png" alt="">
고뇌의 흔적들... 맨위에껀 되나? 해서 넣어본거고
두번째가 애플 실리콘용
밑에가 인텔용 JDK.. </p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/12e950e8-f12d-4881-ace2-aa4089414572/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/cd9effc8-5639-4d1f-8276-d7d6e9d0d558/image.png" alt=""></p>
<p>STS 컴파일러랑 JDK설정... JDK폴더만 지정해주는게 아니라 Contents/Home까지 지정해야지 JDK를 제대로 인식한다</p>
<p>나는정말 환경잡는게 싫다... 대학교에서도 회사다닐때도 학원에서도 항상 개발환경 잡는데에 애를 먹는다... 시작이 반이라는 게 그냥 나온 말이 아닌가부다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 예외처리 / 파일 입출력]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC-%ED%8C%8C%EC%9D%BC-%EC%9E%85%EC%B6%9C%EB%A0%A5</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC-%ED%8C%8C%EC%9D%BC-%EC%9E%85%EC%B6%9C%EB%A0%A5</guid>
            <pubDate>Mon, 31 Oct 2022 13:32:44 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!
자바의 정석 제 3판을 보고 공부한 것을 정리한 글입니다!</p>
</blockquote>
<h1 id="예외처리">예외처리</h1>
<blockquote>
<p>Exeception Handling, 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것</p>
</blockquote>
<p>자바에서는 실행 시 발생할 수 있는 오류(Exception과 Error)를 클래스로 정의해 두었다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/c9605d48-a79a-4b7d-90b5-32e1b1d5092a/image.png" alt="">
텍스트</p>
<h2 id="에러의-종류">에러의 종류</h2>
<p>프로그래밍을 할 때, 발생하는 에러의 종류는 세가지가 있다.</p>
<blockquote>
<p>컴파일 에러 : 컴파일 시에 발생하는 에러
런타임 에러 : 실행 시에 발생하는 에러
논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것</p>
</blockquote>
<p>런타임 에러를 방지하기 위해, 프로그램 실행 도중 발생할 수 있는 모든 경우의 수를 고려해야 하는데, 그것을 예외 처리라고 한다. 물론 예외 처리를 한다고 에러가 해결되는 것은 아니다. </p>
<h2 id="try-catch문">try-catch문</h2>
<p>그래서 개발자들은 <code>try-catch</code>문을 통하여 예외의 발생에 대한 코드를 작성하여 프로그램의 갑작스런 비정상 종료를 막고, 정상적인 실행상태를 유지하도록 하는 것이다. <code>try-catch</code>는 다음과 같이 사용한다.</p>
<pre><code class="language-java">try { 
    // 예외가 발생할 가능성이 있는 코드
} catch (Exception1 e1) {
    // Exception1이 발생했을 때 처리할 구문
} catch (Exception2 e2) {
    // Exception2가 발생했을 때 처리할 구문
}</code></pre>
<p><code>try</code>블럭에는 예외가 발생할 수 있는 코드를 적고, <code>catch</code>블럭 안에는 예외를 처리할 구문을 적어야 한다. 이 때, <code>catch</code>블럭이 여러개라면, 예외에 알맞는     <code>catch</code>블럭이 단 한 번 실행된다. </p>
<h1 id="파일-입출력">파일 입출력</h1>
<h2 id="입출력">입출력</h2>
<blockquote>
<p>컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고받는 것</p>
</blockquote>
<p>흔히 우리가 <code>System.out.println()</code>과 같은 메소드를 통해 키보드로 입력받는 것조차도 입력이다. 자바에서 입출력을 수행하려면 두 대상을 연결하고, 데이터를 전송할 수 있는 스트림이 필요하다. 스트림은 데이터를 운반하는 데 사용되는 연결통로이다.</p>
<h2 id="fileinputstream--fileoutputstream">FileInputStream / FileOutputStream</h2>
<blockquote>
<p>파일의 입출력을 하기 위한 스트림</p>
</blockquote>
<p>정말 간단하게 파일을 만들어주는 과정이다. 주로 <code>File</code>클래스를 가지고 작업하고, <code>java.io</code>패키지에 존재하고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[10월 5주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/10%EC%9B%94-5%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/10%EC%9B%94-5%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 30 Oct 2022 12:26:24 GMT</pubDate>
            <description><![CDATA[<h1 id="💜-좋았던-것liked">💜 좋았던 것(Liked)</h1>
<p>이번 주에는 무려 술을 세 번이나 먹었다. 을지로에서도 먹고, 학원 자리 바꿔서, 그동안 같이 앉았던 언니들이랑 저녁도 먹고, 어제 토요일에는 친구들이랑 동네에서 먹고! 그냥 많이 퍼마신 것 같다. 또 언제 먹겠냐만은, 다음주부터 세미 프로젝트(사실 이미 시작했다.) 들어가면 정말 바빠질 것 같아서 많이 놀았다! 그래서 회고도 지금 올린다.... 아무튼, 자리도 바꾸고, 새 사람들과 다시 또 열공모드가 되었다! </p>
<h1 id="📚-배운-것learned">📚 배운 것(Learned)</h1>
<p>자바 스크립트를 계속해서 배웠다. 이벤트 발생과, 정규 표현식에 대해 배웠는데... 사실 아직도 정규표현식은 너무 헷갈린다! 강사님은 잘 읽을 줄 알면 된다고 했는데, 읽는 게 너무 어려워요😥</p>
<h1 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h1>
<p>위에 말했듯 술 먹느라 공부를... 안 했다. 이번주 까지 자바스크립트 하기도 했고, 목요일 하루는 팀프로젝트 주제 정하고, 계속 회의하고, 당장 오늘만 해도 온라인 회의를 했다! 그래서 회고도 늦어졌고... 물론 핑계다. 스터디 준비는 아직 시작도 못했다... 주말에는 거의 집에만 있어서 목표 활동량도 못 채웠다.</p>
<h1 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h1>
<p>내일부터 진짜 팀프로젝트 시작! 같은 느낌이다. 목요일과 금요일은 뭐 할지 주제 정하고, 기능 정해뒀으니... 내일부터는 시간 날때마다 무언가 구현해야 할 것 같다. 그렇다고 복습도, 스터디도 소흘히 하면 안 될 것 같다! 아무튼, 내일부터는 조금 더 열심히 살아야겠다.
끝!🙄</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 다형성]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-%EB%8B%A4%ED%98%95%EC%84%B1</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-%EB%8B%A4%ED%98%95%EC%84%B1</guid>
            <pubDate>Mon, 24 Oct 2022 13:24:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!
자바의 정석 제 3판을 보고 공부한 것을 정리한 글입니다!</p>
</blockquote>
<h1 id="🎛-다형성">🎛 다형성</h1>
<blockquote>
<p>다형성(多形性, polymorphism; 폴리모피즘)은 그 프로그래밍 언어의 자료형 체계의 성질을 나타내는 것</p>
</blockquote>
<p>다형성을 위키백과에 검색했을 때, 나온 다형성의 뜻이다. 사실 이렇게만 보면 이게 무슨 소리지, 하게 된다. 한국인 답게 한자를 하나하나 까보면, 많을 다(多), 모양 형(形), 성품 성(性)으로 쓴다. 쉽게 말해서 다양한 형상을 가진 성질이라고 이해하면 될 것 같다. </p>
<h2 id="자바에서의-다형성">자바에서의 다형성</h2>
<p>그렇다면 자바에서의 다형성은 무엇일까? <strong>자바에서 다형성은 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 구현</strong>하였다. 즉, 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다. 즉 자바에서는 상속을 통해 주로 다형성을 구현하곤 한다. 상속에 대한 내용은 <a href="https://velog.io/@fogbow_juni/JAVA-%EC%83%81%EC%86%8D%EA%B3%BC-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%98%95%EB%B3%80%ED%99%98">여기</a>에 정리해 두었었다.</p>
<p>그런데 나는 꼭 상속만이 다형성이라고 생각하지는 않는다. 위에 한자를 해석했듯, 다양한 형상을 가진 성질인데, 우리가 주로 사용하는 오버로딩, 오버라이딩 또한 다형성의 일부라고 생각한다. 오버로딩과 오버라이딩 둘 다 같은 이름의 메소드를 쓰지만, 수행되는 기능이 다르기 때문이다. </p>
<h1 id="️-오버로딩함수-중복">‼️ 오버로딩(함수 중복)</h1>
<blockquote>
<p>오버로딩(overloading)은 한 클래스 내에 같은 이름의 메소드를 여러개 정의하는 것</p>
</blockquote>
<p>또한 오버로딩을 성립시키기 위해서는 <strong>메소드 이름이 같아야 하고, 매개변수의 개수 또는 타입이 달라야 한다.</strong></p>
<p>우리가 가장 흔히 볼 수 있는 오버로딩의 예시로는 바로 <code>println()</code>메소드가 있다. <code>println()</code>메소드에 내가 출력을 원하는 변수를 매개변수로 아무거나 넣어도 다 출력이 된다. 이런 경우, 매개변수의 타입이 달라져 오버로딩이 성립되었다. 실제로 <code>PrintStream.class</code>에 <code>println()</code>이 매개변수만 다르고, 여러개 정의되어 있는 것을 볼 수 있다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/051e7813-c9f0-4d39-bbdb-fb2d6df4435f/image.png" alt=""></p>
<p>또 우리가 흔히 볼 수 있는 오버로딩은, 바로 클래스에 선언한 생성자이다. 생성자도 일종의 메소드로, 우리가 매개변수의 개수만 다르게 두어, 오버로딩을 통해 필요한 생성자를 적재적소에 맞게 사용한다. </p>
<pre><code class="language-java">public class Member {
    private String name;
    private int age;

    public Member() {        // 매개변수의 개수가 달라 오버로딩이 일어났다.
        super();
    }

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

    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;
    }

    @Override
    public String toString() {
        return &quot;Member [name=&quot; + name + &quot;, age=&quot; + age + &quot;]&quot;;
    }

}
</code></pre>
<h2 id="왜쓸까">왜쓸까?</h2>
<p>궁극적으로 오버로딩을 쓰는 이유는 하나의 메소드 이름만 기억하면 되기 때문에 오류의 가능성을 많이 줄이고, 메소드 이름이 같다면 같은 기능을 하는 메소드라고 추론이 가능하다. 또한 메소드 이름짓기에 걸리는 시간을 줄일 수 있다. 아래와 같은 사진처럼, 생각 의외로 변수나 메소드 이름을 짓는 데에 많은 시간을 소비하곤 한다. 이 시간을 줄일 수 있다는 것은 커다란 장점이라고 생각한다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/cf1dc8ee-e61e-4210-b05b-4ae38dfb9621/image.png" alt=""></p>
<h1 id="📐-오버라이딩함수-재정의">📐 오버라이딩(함수 재정의)</h1>
<blockquote>
<p>부모 클래스로부터 상속받은 메소드의 내용을 변경하는 것</p>
</blockquote>
<p>보통 상속받은 메소드를 그대로 쓰는 경우도 있지만, 자식 클래스가 자신에게 맞게 변경하는 경우, 부모 클래스의 메소드를 오버라이딩 하여 사용한다. 메소드 오버라이딩의 조건은, <strong>이름이 같아야 하고 매개변수가 같아야하고, 반환타입이 같아야 한다.</strong></p>
<p>아래 코드는 <code>Parent.java</code>를 상속받는 <code>Child.java</code>의 코드이다. </p>
<pre><code class="language-java">// Parent.java
public class Parent {

    private int x;
    private int y;

    public Parent() {}

    public Parent(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public String display() {
        return &quot;x : &quot; + x + &quot;, y : &quot; + y;
    }

}</code></pre>
<pre><code class="language-java">// Child.java
public class Child extends Parent {
    private int z;

    public Child() {}

    public Child(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }

    public int getZ() {
        return z;
    }

    public void setZ(int z) {
        this.z = z;
    }

    public String display() {    // 부모의 display()를 오버라이딩
        return super.display() + &quot;, z : &quot; + z;
    }
}
</code></pre>
<pre><code class="language-java">// Run.java
public class Run {

    public static void main(String[] args) {

        Child c = new Child();

        c.setX(10);
        c.setY(20);
        c.setZ(30);

        System.out.println(c.display());

    }

}</code></pre>
<p>먼저 <code>Parent.java</code>안에 <code>display()</code>라는 메소드를 정의했고, <code>Child.java</code>를 만들 때 <code>dispaly()</code>라는 메소드를 오버라이딩하여 다시 정의했다. 이 때, <code>display()</code>메소드를 구현할 때에는, 부모의 <code>display()</code>메소드를 호출하고, 그 뒤에 온전히 자신의 것인 z를 출력하기 위한 출력문을 덫붙였다. 그 후 메인 메소드에서 자식 클래스인 객체 c를 생성하고, <code>setter</code>를 통하여 값을 저장한 뒤, c의 <code>dispaly()</code>메소드를 호출하면, x, y, z의 값이 모두 다 출력되는 것을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/c153e5f9-6a86-4485-876c-b26032cea648/image.png" alt=""></p>
<p>이 코드에서는 <code>display()</code>로 메소드를 만들었지만, 우리가 흔히 사용하는 <code>toString()</code>메소드 또한 최상의 클래스인 <code>Object.class</code>에 정의되어 있는 메소드를 오버라이딩 되어 사용하는 것이다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/5adff807-257e-45ff-be61-2063718bf93e/image.png" alt=""></p>
<h1 id="🔖-마치며">🔖 마치며</h1>
<p>두번째 스터디 주제인 다형성에 대해 정리했다! 다형성은 말 그대로 이름은 같고, 다른 기능을 하는 것으로 알고 있었는데, 책에는 상속에 이어서 upcasting, downcasting만 범위에 있었고, 내가 다형성이 가장 잘 보이는 예시라 생각하는 오버로딩과 오버라이딩에 대한 내용은 없어서 따로 추가했다. 말이 한자여서 어렵지, 사실 우리는 자바를 배우면서 꽤나 많은 다형성을 적용해 코딩해왔다는 걸 알 수 있었다! 아무튼 간략하게 내용을 정리해봤는데, 주로 헷갈리는 오버로딩과 오버라이딩에 대하여 다시 정리할 수 있었다.
끝!😖</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[10월 4주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/10%EC%9B%94-4%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/10%EC%9B%94-4%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 21 Oct 2022 08:29:15 GMT</pubDate>
            <description><![CDATA[<h1 id="💜-좋았던-것liked">💜 좋았던 것(Liked)</h1>
<p>드디어 10월 4주차! 진짜 이번달 유독 빠르게 지나가는 것 같다... 이번 주부터 HTML을 초스피드로 나가기 시작했다! 그래서 과제로 깡 HTML로 화.꾸(화면 꾸미기)가 나왔다. 뭐 할지 고민하다가 역시 어덕행덕이라고... <img src="https://velog.velcdn.com/images/fogbow_juni/post/19d5b0e4-e8ed-4eb2-ba1f-a4cbd6479386/image.png" alt="">
또 덕질로 해버렸다. 근데 이 간단한 페이지 만드는 것도 진짜 정말 힘들었다. 뭐만 하면 배치가 다 깨져버리고 새삼 모든 퍼블리셔들께 존경의 박수를 속으로 보냈다.</p>
<p>그리고 드디어 스터디 첫모임 말고 첫공부!! 주말에 포스팅 해뒀던 객체배열(포스팅은 <a href="https://velog.io/@fogbow_juni/JAVA-%EA%B0%9D%EC%B2%B4-%EB%B0%B0%EC%97%B4">여기!</a>)에 대해서 토론형식으로 진행했다. 그러다 보니 내가 알고 있는 걸 설명하면서 다시 정리할 수 있었고, 몰랐던 부분도 스터디원분들의 설명을 들으면서 다시 정리할 수 있었다!
무엇보다 좋았던 건 실시간으로 되는 코드 안 되는 코드 다 찔러 보면서 nullPointException이 뭐하면 뜨는지, 왜 해당 메소드를 썼는지 같이 공부할 수 있어서 정말 좋았다. 게다가 저번주 금요일에 학원 회식으로 다들 친해져서... 화기애애하게 공부할 수 있어서 정말 좋았다! 진짜! </p>
<h1 id="📚-배운-것learned">📚 배운 것(Learned)</h1>
<p>HTML이랑 CSS, JavaScript쪼금! 국비 과정이 풀스텍 과정이여서 이 내용들도 다루고 넘어간다고 하더라. JS는 다음주 까지 이어진다고 했다. 사실 또 회사다닐 때 어쩌다보니 풀스텍을 하긴 했었는데 정말 야매로... 했던 것이라 이번 기회에 역시 기초를 좀 잡고 가야할 것 같다!</p>
<h1 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h1>
<p>복습, 그리고 잠.... 왜인지 이번주는 게임도 많이 안 했는데, 그렇다고 공부도 안 했다. 그냥 집에 오면 밥먹고 소파에 널부러져서 핸드폰만 봤다. 차라리 일찍 자던가 공부를 하던가 했어야 했는데... 그리고 이상하게 피곤하고 졸렸다. 수면시간은 그래도 유지하는데, 커피를 많이 마셔도 졸렸다. 공부도 게임도 안 할 거면 아예 일찍 자야겠다!</p>
<h1 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h1>
<p>무언가 이제 슬슬 세미프로젝트도 할 것 같고, 포트폴리오를 준비해야 할 것 같다. 그러기엔 프론트와 퍼블리셔 실력이 영 꽝이여서... 심심하면 사이트 하나 잡고 클론코딩이라도 해봐야 할 것 같다. 아니면 리액트나 뷰js같은 프레임워크라도 같이 공부하면 좋을 것 같다! 아무래도 과정중에는 바닐라 자바스크립트만 다루니까... 아무튼 다음주에는 조금 더 공부를 하면 좋을 것 같다.
끝!😌</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 객체 배열]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-%EA%B0%9D%EC%B2%B4-%EB%B0%B0%EC%97%B4</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-%EA%B0%9D%EC%B2%B4-%EB%B0%B0%EC%97%B4</guid>
            <pubDate>Sun, 16 Oct 2022 03:25:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<h1 id="배열">배열</h1>
<p>객체 배열을 하기 전, 배열에 대한 개념정리가 필요할 것 같아서 간단하게 요약정리를 해보았다! 우선 배열의 정의는 다음과 같다.</p>
<blockquote>
<p>같은 타입(자료형)의 여러 변수를 하나로 묶는 <strong>참조 변수</strong>, 실제 값이 아닌 <strong>배열의 시작주소</strong>가 저장된다.</p>
</blockquote>
<p>여기서 주목해야 할 점은 배열은 참조 변수라는 점인데, 우리가 크기가 5짜리인<code>int</code>형 배열을 만들 때 다음과 같이 만든다.</p>
<pre><code class="language-java">int[] array = new int[5];</code></pre>
<p>그럼 여기서 만든 <code>array</code>가 참조변수가 되고, 이 변수를 출력해보면 주소값이 출력되는 걸 볼 수 있다. </p>
<pre><code class="language-java">System.out.println(array);</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/e57ef2a7-240c-408b-a0d6-ab8b078bee42/image.png" alt=""></p>
<p>실제 값을 출력하려면, 아래와 같이 각각의 인덱스를 통해 출력해야 한다. </p>
<pre><code class="language-java">for (int i = 0; i &lt; array.length; i++) {
    System.out.println(&quot;array[&quot; + i + &quot;] = &quot; + array[i]);
}</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/9af1448a-8eb1-49ba-843d-a18d39e53336/image.png" alt=""></p>
<p>또한 초기화를 진행하지 않아도 0으로 자동으로 초기화가 되는 것을 알 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/2ffbaf57-7d0f-468e-a787-89a1eebe5d1e/image.png" alt=""></p>
<p>배열 변수는 배열의 시작주소를 저장하기 때문에, 배열을 복사할 때 </p>
<pre><code class="language-java">int[] array2 = array</code></pre>
<p>와 같이 진행했다면, 그저 참조하는 주소값만 복사해오기 때문에 얕은 복사가 일어나, 원본 배열에서 수정을 하면 복사한 배열에서도 수정이 일어나는(그 반대도!) 얕은 복사가 일어난다. 이를 방지하기 위해서는 깊은 복사를 이용해야하는데, 관련 글은 <a href="https://velog.io/@fogbow_juni/JAVA-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC">여기에 정리해 두었다!</a></p>
<h1 id="객체-배열">객체 배열</h1>
<blockquote>
<p>같은 클래스로 만들어진 객체들을 하나로 묶는 것</p>
</blockquote>
<p>말 그대로이다. 배열이 같은 자료형을 하나로 묶었다면, 객체 배열은 같은 클래스로 만들어진 객체들을 하나로 묶는 것이다. 쉽게 생각하면 자료형대신 클래스를 자료형으로 보고 만들면 된다. 객체 배열의 생성은 다음과 같다. Member이라는 클래스가 있다고 가정하고, 이 클래스로 배열을 만들기 위해서는</p>
<pre><code class="language-java">Member[] m = new Member[3];</code></pre>
<p>이렇게 하면 된다.</p>
<p>일반 배열과 마찬가지로 그냥 객체 배열을 출력하면, 주솟값만 출력되고, 객체 배열 안의 데이터들을 보고 싶으면 인덱스에 접근해야 데이터를 볼 수 있다.</p>
<pre><code class="language-java">        Member[] m = new Member[3];

        System.out.println(m);

        for(int i=0; i&lt;m.length; i++) {
            System.out.println(m[1]);
        }</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/5d254fba-4fd0-4def-bc02-3fdd30f3366b/image.png" alt=""></p>
<p>또한 초기화를 진행하지 않아도, null로 자동으로 초기화 됨을 알 수 있다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/89110a32-7334-4b11-a027-438413d6f710/image.png" alt=""></p>
<h1 id="마치며">마치며</h1>
<p>첫 스터디 자료를 만들면서 개념을 다시 짚고 넘어가서 더 잘 들어오는 것 같았다. 물론 나중에는 객체배열이 귀찮아서 <code>Arraylist</code>와 같은 컬랙션으로만 썼는데, 책도 사고 스터디 준비하면서 메모리 주소를 어떻게 참고하고, 어떻게 사용하는지 다시 한 번 정리할 수 있어서 좋았다!
끝!😉</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[10월 3주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/10%EC%9B%94-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/10%EC%9B%94-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 14 Oct 2022 07:56:40 GMT</pubDate>
            <description><![CDATA[<h1 id="💜-좋았던-것liked">💜 좋았던 것(Liked)</h1>
<p>길고 어렵고 짜증났던 JDBC가 끝났다! 또 폭풍처럼 진도를 나갔는데... 이틀동안 옆자리분들과 미니 팀플을 했다! 그것도 만 하루동안! 근데 진짜 미니 프로젝트라 부담없이 진행했다! 조원분들도 부담없이 진행하셨으면 하는 바람이다... 나만 너무 부담없이 하면 미안해지니까!
아무튼 또 테이블 설계부터 구조까지 전부~ 우리가 다 했다! 대충 맛집리스트를 만들고, 관리자는 맛집리스트에 추가하거나 리뷰를 관리할 수 있고, 일반 사용자는 맛집을 검색하거나 리뷰를 작성할 수 있는 프로그램이었다!
<img src="https://velog.velcdn.com/images/fogbow_juni/post/7208e95e-acca-411f-889e-385dbf6add42/image.png" alt=""></p>
<p>(나름 회의하면서 설계를 했고)</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/d394c25d-cca1-4413-b5d3-61c0ad41b060/image.png" alt="">
(팀원분이 테이블 명세를 깔끔하게 정리해 주셨다!!!)</p>
<p>세명이서 우다다다 만들어서, 테이블 하나씩 잡고 <code>CREATE</code>하였다. 그 다음 View단을 같이 설계하면서 필요한 메소드들이나 그 메소드가 하는 기능, 필요한 쿼리문을 같이 정했고, 각각 메소드를 나누어서 구현했다!</p>
<p>그런데 아직 학원에서 깃을 안 배워서... 각각 만든 프로젝트 파일을 하나로 합치는 데에 좀 힘들었다. 다시 한 번 깃의 소중함을 느낀다... (그래도 2트만에 수동 머지완료!)
<img src="https://velog.velcdn.com/images/fogbow_juni/post/789241cc-6b30-45c5-b75e-ac1c00c00565/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/769fa9fe-6835-425e-9b5c-4bf397fe9f7b/image.png" alt="">
이런 것을 만들었다! 나름 로그인도 구분도 하려고 했다. 로그인 자체는 login객체를 하나 만들어서 그 객체를 끌고 다녔지만... 비슷하게 구현해봤다는 데에 의의를 두었다!
그리고 이제 보니 1번의 주소가 이상한데... 
<img src="https://velog.velcdn.com/images/fogbow_juni/post/76d8725f-80b8-4895-83ae-be6a73accb3f/image.png" alt="">
그냥 데이터를 잘못 넣었던 것이다. 휴~</p>
<h1 id="📚-배운-것learned">📚 배운 것(Learned)</h1>
<p>JDBC를 좀 더 깔끔하게 쓰는 법을 배웠다. 그동안 SQL을 만들려면 문자열에문자열을붙이고또붙이고또붙이고... 이제 안 그래도 된다! <code>PreparedStatement</code>를 이용하면 된다. <code>PreparedStatement</code>는 <a href="https://velog.io/@fogbow_juni/JAVA-JDBC-PreparedStatement">여기</a>에 포스팅 해두었습니다!
그 다음엔 템플릿으로 만들고 빼는 방법을 배웠다. 블로그에는 간결하게 정리하느라 빼놨지만, 실제 배울 때에는 MVC패턴을 지켜가면서 했다! 그러다보니 중복되는 부분들이 너무 많았다. 예를들어 <code>Connection</code>객체를 만든다던지... 그런 것들을 템플릿으로 빼서 만들었다. 그러니 코드가 너무 깔끔~
<img src="https://c.tenor.com/n7K8ebAE71UAAAAC/%EC%B5%9C%EA%B3%A0%EB%86%8D%EB%8B%B4%EA%B3%B0-%EB%94%B0%EB%B4%89%EB%86%8D%EB%8B%B4%EA%B3%B0.gif" alt="">
그 다음은 <code>driver.properties</code>와 <code>mapper.xml</code>에 대해 배웠다. 보안강화는 물론이고, 쿼리문을 수정한 뒤 다시 빌드를 안 해도 된다는 점이 너무 좋았다! <code>JDBC Properties</code>는 <a href="https://velog.io/@fogbow_juni/JAVA-JDBC-Properties">여기</a>에 포스팅 해두었습니다!</p>
<h1 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h1>
<p>이번 주에는 나름 갓생을 살았다! 
<img src="https://velog.velcdn.com/images/fogbow_juni/post/4e67c4a2-6021-477c-87e9-a18d89852e64/image.png" alt=""></p>
<p>게임 엄청 줄이고... 평일 약속이나 스터디 후에 집가서 또 공부를 했다. 나름! 나 자신 나름 갓생이다! 그러니까 이번 주는 부족했던 것이 없다고 해도 되겠지? <img src="https://velog.velcdn.com/images/fogbow_juni/post/38447974-f47b-410a-a0be-76f82dbc2ee5/image.png" alt=""> 움직이기 목표달성 매달도 따고(애플워치 산지 1년만에.......) 아무튼 갓생을 살았다고 생각한다. 이런 주도 있어야지!</p>
<h1 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h1>
<p>주말에 아크를 찾아 떠나고 싶지만 ... 다음주 화요일에 스터디가 있다! 그래서 그거 준비하고 주말 잘 보냈으면 좋겠다. 물론! 안 쉴 건 아니다! 또 힘들어서 번아웃 오면 그것도 문제니까! 불금 잘 즐기고, 토요일 공부 하고, 게임도 다 즐겨서 한 주를 잘 마무리 하면 되겠다.
그리고 다음주도 엄청 춥다! 이제 추워질 일만 남았겠지? 몸관리 계속 이대로 유지하거나 더 좋아지고 싶다. <em><del>그래야 연말에 공연가고 놀지</del></em> 주말에도 워치 링 채우기 꾸준히 하면 좋겠다! 맨날 주말에는... 누워있느라 링 채우기가 힘들다. 아무튼, 주말 잘 마무리하고 다음주도 열심히 살면 좋겠다!
끝!😏</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] JDBC Properties]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-JDBC-Properties</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-JDBC-Properties</guid>
            <pubDate>Fri, 14 Oct 2022 07:30:57 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<h1 id="📄-properties">📄 Properties</h1>
<blockquote>
<p>Properties는 Map계열 중 하나의 자료구조이며, key값과 value값을 세트로 저장한다. 또한 key값과 value의 값을 String형으로 다룬다. </p>
</blockquote>
<p>사실 Collection에 관련해서 포스팅을 할 때 잠깐 다루긴 했었다.(<a href="https://velog.io/@fogbow_juni/JAVA-Collection">여기!</a>) 그런데 너무 대충 다루고 갔었다... 그땐 몰랐지, Properties가 꽤나 중요한 것이라는 걸...
<img src="https://velog.velcdn.com/images/fogbow_juni/post/0e6e1662-a4fe-4692-b0d9-7c8a778ed07c/image.png" alt=""></p>
<h2 id="왜쓸까">왜쓸까?</h2>
<p>우선 <code>Properties</code>는 주로 외부설정파일을 읽어오거나, 파일형태로 출력하고자 할 때 쓴다. 여기서 외부설정파일을 사용한다는 점에 주목하고 싶다. 외부파일로 설정하면 프로젝트를 재시작 할 필요가 없다는 아주 큰 장점이 있다! 보통 쿼리문을 XML파일로 만들어 사용하는데, 쿼리문 정렬 순서를 바꾼다거나 하면 xml파일만 수정하기 때문에 재시작이 필요없어진다. 로컬에서 돌리는 프로젝트가 아니라 실제 상용에서 돌리면 점검시간 같은 게 필요없어진다.</p>
<h1 id="📃-driverproperties">📃 driver.properties</h1>
<h2 id="사용방법">사용방법</h2>
<pre><code>#driver.properties
password=JDBC
url=jdbc\:oracle\:thin\:@localhost\:1521\:xe
driver=oracle.jdbc.OracleDriver
username=JDBC</code></pre><p>이런식으로 <code>driver.properties</code> 파일을 만들어주었다. 이 파일 안에는 드라이버와 관련된 데이터들을 설정하였다.</p>
<p>그 다음, <code>Connection</code>객체를 만들 때, <code>Properties</code>객체를 통해 생성해 주었다. 먼저 <code>Properties</code>의 <code>load()</code>메소드를 통해, 파일을 불러와주고, <code>Properties</code>안에 있는 <code>key</code>를 불러와 주면 된다. </p>
<pre><code class="language-java">    Properties prop = new Properties();
    try {
            prop.load(new FileInputStream(&quot;resources/driver.properties&quot;));

            Class.forName(prop.getProperty(&quot;driver&quot;));
            conn = DriverManager.getConnection(prop.getProperty(&quot;url&quot;),
                                               prop.getProperty(&quot;username&quot;),
                                               prop.getProperty(&quot;password&quot;));


        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }</code></pre>
<h1 id="📜-mapperxml">📜 mapper.xml</h1>
<p><code>Mapper</code>는 주로 쿼리문을 안에 적어두고 사용한다. 위에도 말했지만, 간단히 쿼리문만 수정할 때, 이 파일 안의 쿼리문을 고쳐주고, 재시작 할 필요가 없다는 엄청난 장점이 있다!</p>
<h2 id="사용방법-1">사용방법</h2>
<p><code>Properties</code>객체에 <code>loadFromXML()</code> 메소드를 통해 파일을 불러온다. 이때 주의할 점은 <code>loadFromXML()</code>메소드를 사용해야 한다는 점이다.</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
&lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
&lt;properties&gt;
&lt;comment&gt;mapper.xml&lt;/comment&gt;
    &lt;entry key=&quot;selectAllName&quot;&gt;
        SELECT 
            TNAME 
        FROM 
            TEST
    &lt;/entry&gt;
&lt;/properties&gt;</code></pre><p><code>mapper.xml</code>을 위와같이 만들어 준 후, </p>
<pre><code class="language-java">prop.loadFromXML(new FileInputStream(&quot;resources/mapper.xml&quot;));</code></pre>
<p><code>Properties</code>객체의 <code>loadFromXML()</code>메소드를 통해 파일을 읽어왔다.</p>
<pre><code class="language-java">String sql = prop.getProperty(&quot;selectAllName&quot;);</code></pre>
<p>그 후, 실행할 쿼리문(sql)에 <code>getProperty()</code>메소드를 통하여, 키값을 호출해 준다. </p>
<h2 id="전체-코드">전체 코드</h2>
<pre><code class="language-java">        Connection conn = null;
        Properties prop = new Properties();

        PreparedStatement pstmt = null;
        ResultSet rset = null;

        try {
            prop.load(new FileInputStream(&quot;resources/driver.properties&quot;));

            Class.forName(prop.getProperty(&quot;driver&quot;));
            conn = DriverManager.getConnection(prop.getProperty(&quot;url&quot;),
                                               prop.getProperty(&quot;username&quot;),
                                               prop.getProperty(&quot;password&quot;));

            prop.loadFromXML(new FileInputStream(&quot;resources/mapper.xml&quot;));

            String sql = prop.getProperty(&quot;selectAllName&quot;);
            pstmt = conn.prepareStatement(sql);
            rset = pstmt.executeQuery();

            while(rset.next()) {
                System.out.println(rset.getString(&quot;TNAME&quot;));
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }</code></pre>
<h2 id="실행-결과">실행 결과</h2>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/1b8a5a05-519d-498f-9f6e-3e9740a0fe0f/image.png" alt="">
DB에서 확인해본 <code>Resultset</code>과,
<img src="https://velog.velcdn.com/images/fogbow_juni/post/42936bc8-a94e-49ae-a961-506f8024faca/image.png" alt="">
콘솔에서 확인해 본 <code>Resultset</code>이 같음을 확인할 수 있다!(성공적으로 작동된다~)</p>
<h1 id="🔖-마치며">🔖 마치며</h1>
<p>귀찮게 따로 파일로 빼야해? 하겠지만, 이렇게 빼두면 코드 중복을 정말 줄일 수도 있다! 그리고... 쿼리문 같은 경우에 수정 하고 프로젝트 빌드를 다시 안 해도 된다는 장점이 있다는 걸 이제 알았다... 그동안 쿼리문 하나 고치고 빌드하고 또하나 고치고 또 빌드하고... 정말 징글징글 했다.
또 이렇게 파일로 빼면 장점이 하나 더 있다! 원격 저장소에 올릴 때(깃헙같은 곳) DB접속 정보가 적혀있는 driver.properties 파일을 빼고 올리면 나름 보안을 유지할 수 있다는 장점이 있다! 물론 지금은 로컬DB로 올렸기 때문에 막 올려도 상관 없지만... 팀별로 프로젝트를 할 때 이 방법을 쓰면 정말 좋을 것 같다. 아니 꼭 써야겠다.
끝!😁</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] JDBC PreparedStatement]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-JDBC-PreparedStatement</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-JDBC-PreparedStatement</guid>
            <pubDate>Wed, 12 Oct 2022 05:05:00 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<blockquote>
<p>ojdbc6버전과 JDK 1.8버전, 윈도우 환경에서 작성된 코드들입니다!</p>
</blockquote>
<h1 id="🔧-preparedstatement">🔧 PreparedStatement</h1>
<p><code>PreparedStatement</code>은 <code>Statement</code>클래스를 상속받았다. <code>Statement</code>보다 기능이 향상 되었고, <code>Statement</code>보다 코드의 가독성이 상승된다!
<img src="https://velog.velcdn.com/images/fogbow_juni/post/3c1465c8-3095-4e3c-a638-cab9d4d59278/image.png" alt="">
<code>extends</code>키워드를 통해 Statement코드를 상속받는다!</p>
<h1 id="❓-사용방법">❓ 사용방법</h1>
<p>사용방법은 간단하다. <code>Statement</code>객체 대신 <code>PrepareStatement</code>객체를 생성하고, 미완성된 SQL문을 먼저 전달한다. 그 후 실행하기 전에 완성된 형태로 만든 후 실행만 한다. 미완성된 SQL문은 사용자가 입력한 값들을 등록할 수 있는 공간을 <code>?(위치홀더)</code>로 확보한다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/43989eff-b933-4aa6-bc12-24fc2f54aed1/image.png" alt=""></p>
<h2 id="미완성된-sql문">미완성된 SQL문</h2>
<p>미완성된 SQL문은 뭐고, 위치홀더는 대체 무엇인가?</p>
<p>바로 전 포스팅에서도 JDBC를 사용할 때, </p>
<pre><code class="language-java">String sql = &quot;INSERT INTO TEST VALUES (33, &#39;쥬니&#39;, 22/10/12)&quot;;</code></pre>
<p>와 같이 사용했다. 이게 짧은 구문이면 상관없는데, 만약 값을 많이 넣어야하고, 그걸 객체에서 꺼내오면 String형으로 선언된 sql이 많이 지저분해 보이고, 가독성도 떨어질 것이다. 아래 코드는 그 예시이다.</p>
<pre><code class="language-java">String sql =
        &quot;INSERT INTO MEMBER VALUES(SEQ_USERNO.NEXTVAL, &quot; 
                                                        + &quot;&#39;&quot; + m.getUserId()     + &quot;&#39;, &quot; 
                                                        + &quot;&#39;&quot; + m.getUserPwd()     + &quot;&#39;, &quot; 
                                                        + &quot;&#39;&quot; + m.getUserName() + &quot;&#39;, &quot; 
                                                        + &quot;&#39;&quot; + m.getGender()     + &quot;&#39;, &quot;
                                                              + m.getAge()        + &quot;, &quot;
                                                        + &quot;&#39;&quot; + m.getEmail()     + &quot;&#39;, &quot;
                                                        + &quot;&#39;&quot; + m.getPhone()     + &quot;&#39;, &quot;
                                                        + &quot;&#39;&quot; + m.getAddress()     + &quot;&#39;, &quot;
                                                        + &quot;&#39;&quot; + m.getHobby()     + &quot;&#39;, SYSDATE)&quot;;</code></pre>
<p>위와 같이 <code>getter</code>를 쓰기 전에 앞뒤로 홑 따옴표를 붙어야하고, 그걸 다 문자열로 합쳐서 하나의 완성된 sql문을 만들어야 한다. 가독성도 가독성이고, 귀찮다! 쿼리에서 오타가 나버리면, 안경 벗고 모니터에 얼굴 가까이하고 코드를 한참 들여다 보아야 한다.</p>
<p>그래서 <code>PreparedStatement</code>를 사용할 때는 아래와 같은 <strong>미완성된</strong> SQL문을 사용한다.</p>
<pre><code class="language-java">String sql = &quot;INSERT INTO TEST VALUES(?, ?, SYSDATE)&quot;;</code></pre>
<h2 id="위치홀더">위치홀더</h2>
<p>위의 쿼리와는 다른 점이, 우리가 <code>getter</code>로 값을 가져올 필요 없이 <code>?</code>로 적어두었다. 즉 미완성된 SQL문이 된다는 것이다.
그럼 이 미완성된 SQL문은 언제 완성시키는 것일까? 바로 <code>PreparedStaement</code>객체 생성 후 미완성된 SQL문의 위치홀더를 <code>set</code>메소드로 채워준다.</p>
<pre><code class="language-java">pstmt = conn.prepareStatement(sql);     // PreparedStatement 객체 생성

pstmt.setInt(1, 100);     // 미완성된 SQL문을 완성시켜 준다
pstmt.setString(2, &quot;무홍&quot;);

result = pstmt.executeUpdate();     // 그리고 매개변수 없는 execute메소드 호출
</code></pre>
<p>이때 인자값이 두개가 사용되는데, 첫번째 인자는 위치홀더의 위치이고(앞에서부터 시작하고 1, 2, 3, ...으로 정해진다.) 뒤에는 우리가 삽입할 데이터이다. <code>setInt()</code>, <code>setString()</code>, <code>setDate()</code>등이 있으며, 데이터베이스의 컬럼의 자료형에 알맞는 메소드를 호출하면 된다.
또한 <code>setString</code>을 할 때에는, 앞 뒤에 자동으로 홑 따옴표를 붙여 보내기 때문에 우리가 하나하나 홑 따옴표를 안 붙이고 사용해도 되는 것이다.
마지막으로 <code>Statemet</code>와는 다르게 매개변수가 없는 <code>execute()</code>메소드를 호출하면 된다.</p>
<h2 id="전체코드">전체코드</h2>
<pre><code class="language-java">        int result = 0;

        Connection conn = null;
        PreparedStatement pstmt = null;

        String sql = &quot;INSERT INTO TEST VALUES (?, ?, SYSDATE)&quot;;

        try {
            Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
            conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:xe&quot;, &quot;JDBC&quot;, &quot;JDBC&quot;);

            pstmt = conn.prepareStatement(sql);     // PreparedStatement 객체 생성

            pstmt.setInt(1, 100);     // 미완성된 SQL문을 완성시켜 준다
            pstmt.setString(2, &quot;무홍&quot;);

            result = pstmt.executeUpdate();     // 그리고 매개변수 없는 execute메소드 호출

            if(result &gt; 0) {
                conn.commit();
            } else {
                conn.rollback();
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                pstmt.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }</code></pre>
<h1 id="🃏-와일드카드에서-사용하는-방법">🃏 와일드카드에서 사용하는 방법</h1>
<p>우리가 와일드카드를 사용해서 특정 키워드가 포함되게 SELECT를 하려고 한다. 그럼 쿼리문을 아래와 같이 작성할 것이고,</p>
<pre><code class="language-sql">SELECT * FROM TEST WHERE TNAME LIKE &#39;%쥬니%&#39;;</code></pre>
<p>이를 위치홀더를 통해 아래와 같이 String형으로 선언한 뒤, 실행을 한다.</p>
<pre><code class="language-java">String sql = &quot;SELECT * FROM TEST WHERE TNAME LIKE &#39;%?%&#39;&quot;;</code></pre>
<p>그럼 놀랍게도 &quot;부적합한 열 인덱스&quot; 오류가 난다!
<img src="https://velog.velcdn.com/images/fogbow_juni/post/ff6e2562-3ad5-4eba-b373-a0825aa6fb3f/image.png" alt="">
<img src="https://velog.velcdn.com/images/fogbow_juni/post/31a39160-ac4b-46af-b396-bf45bea8ff00/image.png" alt="">
분명 위치홀더로 지정하고, <code>setString()</code>메소드로 위치홀더를 잘 채워준 것 같은데... 그 이유는 다음에 있다. 위에 말했듯 <code>setString()</code>메소드는 앞뒤로 홑 따옴표를 붙이기 때문에, 만약 위와같은 쿼리문에서 <code>setString(1, &quot;쥬니&quot;);</code>를 했다면, 쿼리문은 </p>
<pre><code class="language-sql">SELECT * FROM TEST WHERE TNAME LIKE &#39;%&#39;쥬니&#39;%&#39;;</code></pre>
<p>가 되어버리기 때문에 오류가 발생한다.</p>
<p>이에 대한 해결방법은 두가지가 있다.</p>
<h2 id="해결방법">해결방법</h2>
<h3 id="연결연산자-사용">연결연산자 사용</h3>
<p>오라클에서 지원해주는 연결연산자 <code>||</code>을 사용하는 방법이 있다. 이를 사용하면 쿼리문을 작성하면 아래와 같다.</p>
<pre><code class="language-java">String sql = &quot;SELECT * FROM TEST WHERE TNAME LIKE &#39;%&#39;||?||&#39;%&#39;&quot;;</code></pre>
<p>이렇게 되면, 위치홀더를 지정할 때 <code>setString(1, &quot;쥬니&quot;);</code>를 해주면 값이 정상적으로 들어간다.</p>
<h3 id="setstring에서-가공하기">setString()에서 가공하기</h3>
<p>또다른 방법으로는 <code>setString()</code>에서 가공하는 방법이다. 다시 말하지만, 위치홀더는 문자열 앞뒤로 홑 따옴표를 붙여 보내준다고 했다. 그럼 쿼리를 아래와 같이 쓰고,</p>
<pre><code class="language-java">String sql = &quot;SELECT * FROM TEST WHERE TNAME LIKE ?&quot;;</code></pre>
<p>위치홀더에서 아래와 같이 가공을 해주면 된다.</p>
<pre><code class="language-java">pstmt.setString(1, &quot;%쥬니%&quot;);</code></pre>
<h2 id="전체코드-1">전체코드</h2>
<pre><code class="language-java">        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rset = null;

        // String sql = &quot;SELECT * FROM TEST WHERE TNAME LIKE &#39;%&#39;||?||&#39;%&#39;&quot;;
        String sql = &quot;SELECT * FROM TEST WHERE TNAME LIKE ?&quot;;
        try {
            Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
            conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:xe&quot;, &quot;JDBC&quot;, &quot;JDBC&quot;);

            pstmt = conn.prepareStatement(sql); 

            // pstmt.setString(1, &quot;쥬니&quot;);    
            pstmt.setString(1, &quot;%쥬니%&quot;);

            rset = pstmt.executeQuery();

            while(rset.next()) {
                System.out.println(rset.getInt(&quot;TNO&quot;));
                System.out.println(rset.getString(&quot;TNAME&quot;));
                System.out.println(rset.getDate(&quot;TDATE&quot;));
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                pstmt.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }</code></pre>
<h1 id="🔖-마치며">🔖 마치며</h1>
<p>뭔가 전에 <code>Statement</code>를 사용했던 때에는 쿼리가 정말 너무 더럽고 보기도 불편했는데 <code>PreparedStatement</code>를 사용하니 가독성이 올라갈 수 있었다! 그런데, 단점아닌 단점이라면 내가 작성한 쿼리문을 볼 수 없다는 것이다... 그래도 가독성이 올라갔다는 데에 큰 점수를 줄 것 같다! 
개인적으로 와일드카드에서 사용할 때에는 2번방법이 편한 것 같다. 쿼리 깔끔하게 보는 게 제일이라고 생각한다!(진짜 개인적인 생각이다.)
끝!😗</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Oracle] 애플 실리콘 오라클 클라우드 및 JDBC 연동]]></title>
            <link>https://velog.io/@fogbow_juni/Oracle-%EC%95%A0%ED%94%8C-%EC%8B%A4%EB%A6%AC%EC%BD%98-%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%B0%8F-JDBC-%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@fogbow_juni/Oracle-%EC%95%A0%ED%94%8C-%EC%8B%A4%EB%A6%AC%EC%BD%98-%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%B0%8F-JDBC-%EC%97%B0%EB%8F%99</guid>
            <pubDate>Fri, 07 Oct 2022 08:33:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗️이 글은 오라클 클라우드와 애플 실리콘(맥북에어m2)을 4박5일동안 맞장뜨게한 썰형식이며.. 똑같이 따라하셔도 안 될 수도 있습니다....</p>
</blockquote>
<h1 id="서론">서론</h1>
<p>국비 교육 하면서 JDBC를 연동 할 때 오라클을 사용했다. 그런데 애플 실리콘과 Oracle호환이 안 되는 건 알고 있었고, Docker를 통해서 로컬로 오라클 데이터베이스를 연동할 수 있어서 애플 실리콘에서도 오라클을 쓸 수 있다고 들었다. 그래서 안심하고 집에와서 도커를 설치하고 어찌저찌     DBeaver로 <code>SELECT</code> 까지 잘 날려보았다. 그러나 문제가 생겼다... 우선 타임존이 안 맞았고, Docker    를 처음 접해보아서 컨테이너가 뭔지, 어떻게 켜는지 조차 몰랐다. 그래도 <a href="https://shanepark.tistory.com/400">이 분의 글</a>에 정말 자세히 설명이 되어있다! 
그래서 오라클 클라우드를 데이터베이스로 쓰기로 했는데, 또 가입에서 막혔다. 오라클 계정은 예전부터 있었는데, 통합 로그인을 지원 안 해주는 건지, 내가 못하는 건지... 
새로 가입하려니까 가입에서 한 다섯번 튕긴 것 같다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/57e8b931-ec87-45ab-b312-fad7d16a80e8/image.jpg" alt="">
수많은 가입 시도의 흔적들...
너무 화나서 이때 노트북 끄고 핸드폰으로 구글링좀 해봤는데, 체크카드는 안 된다는 이야기가 있어서 절망했다. 나는 회사 다닐 때도 신용카드 발급을 안 했는데... 그렇게 절망하고 있다가 학원 쉬는시간에 다시 생각나서 가입했는데 됐다!
<img src="https://velog.velcdn.com/images/fogbow_juni/post/efd9b0fe-d297-45f6-98c4-d85354d497dc/image.png" alt="">
진짜 어이가 없어서 헛웃음이 나왔다.
그 후 오라클 클라우드 데이터 생성과 SQLDeveloper등의 설정은 <a href="https://velog.io/@zinhoxxl/Apple-Silicon-M1-%EC%9C%BC%EB%A1%9C-oracleeclipse-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-1">이 분의 글</a>을 참고하여서 진행했다. 그리고 JDBC를 학원에서 했던 것처럼 연결하려했는데... 오류가 났다. <del>(근데 또 재현해보려니 안 된다)</del></p>
<h1 id="프로젝트-자바-버전-수정">프로젝트 자바 버전 수정</h1>
<p>먼저 자바 버전은 11버전을 받아서 사용했다. <a href="azul.com/downloads/?version=java-11-lts&amp;os=macos&amp;architecture=arm-64-bit&amp;package=jdk">여기서 받았다!</a>
<img src="https://velog.velcdn.com/images/fogbow_juni/post/0972d890-40f1-4079-bcf3-ab2b19eff154/image.png" alt="">
zip버전을 받은 다음 <code>/Library/Java/JavaVirtualMachines</code>에 풀어주었다. 기존에 쓰던 자바 버전이랑 다르기 때문에 프로젝트에서 자바 경로를 따로 잡아주었다.
프로젝트에 자바 경로를 설정하는 방법은 Properties -&gt; Java Buil Path -&gt; JRE System Library 누른 후 -&gt; Edit -&gt; 창이 뜨면 두번째 있는 Alternate JER에서 설정하여 주었다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/6eb28f59-b401-474b-b144-53c117dd6221/image.png" alt=""></p>
<h1 id="oracle-jdbc-다운">Oracle JDBC 다운</h1>
<p>그 다음은 JDBC jar 파일을 받는 것이다. <a href="https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html">https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html</a> 여기서 받는데, 주의할 점이 있다!
나는 8버전을 다운받았는데, 다운 받을 때 꼭
<img src="https://velog.velcdn.com/images/fogbow_juni/post/b83514de-570c-4395-a3dc-5a134afb0a57/image.png" alt="">
저기 맨 아래에 있는 <strong>버전-full.tar.gz</strong>를 받아야 한다!!!!!!!
압축을 풀면 jar파일이 많을 텐데, 우리가 <code>ojdbc8.jar</code>와 함께 <img src="https://velog.velcdn.com/images/fogbow_juni/post/cf650f41-748e-4f6d-a075-02db1554e28a/image.png" alt="">
사진에 표시된 <code>oraclepki.jar</code> <code>osdt_cert.jar</code> <code>osdt_core.jar</code>을 <strong>build path에 꼭 같이 추가해주자!!!!!!!!!</strong>
물론 지금은 재현이 안 되지만... 이것 때문에 두시간 반을 머리싸매고 고민했다. 임포트 하지 않으면 오류가 발생할 것이다!<img src="https://velog.velcdn.com/images/fogbow_juni/post/289786ff-9268-4c86-ba04-cc3e7fb5c891/image.png" alt="">
build path에 잘 추가했다.</p>
<h1 id="connection-객체-생성">Connection 객체 생성</h1>
<p>오라클 클라우드를 하면 <code>Connection</code>객체를 설정해 줄 때, url을 조금 다르게 설정해야 한다. <code>jdbc:oracle:thin:@클라우드 전자지갑 이름_high?TNS_ADMIN=클라우드 전자지갑 압축 해제한 경로</code>
나는 아래와 같이 <code>Connection</code>객체를 생성해 주었다.</p>
<pre><code class="language-java">conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@khacademyDB_high?TNS_ADMIN=/Users/Wallet_khacademyDB&quot;, &quot;JDBC_TEST&quot;, &quot;FOGBOWjuni0313&quot;);</code></pre>
<p>그 다음, 아래의 예제 코드를 실행하면...</p>
<pre><code class="language-java">package com.juni.test;

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

public class test2 {

    public static void main(String[] args) {
        int result = 0;
        Connection conn = null;
        Statement stmt = null;

        String sql = &quot;INSERT INTO TEST VALUES(52, &#39;쥬니쥬니&#39;, SYSDATE)&quot;;

        try {

            Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
            System.out.println(&quot;driver 등록 성공!!&quot;);

            conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@khacademyDB_high?TNS_ADMIN=/Users/Wallet_khacademyDB&quot;, &quot;JDBC_TEST&quot;, &quot;FOGBOWjuni0313&quot;);
            System.out.println(&quot;Connection 객체 생성!&quot;);

            stmt = conn.createStatement();
            System.out.println(&quot;Statement 객체 생성!&quot;);

            result = stmt.executeUpdate(sql);

            if (result &gt; 0) { // 성공했을 경우 commit
                conn.commit();
            } else { // 실패했을 경우 rollback
                conn.rollback();
            }
        } catch (ClassNotFoundException e) {
                e.printStackTrace();
        } catch (SQLException e) {
                e.printStackTrace();
        } finally {
                try {
                    stmt.close();
                    conn.close();
                } catch (SQLException e) {
                        e.printStackTrace();
                }

        }

        if (result &gt; 0) { 
            System.out.println(&quot;insert 성공&quot;);
        } else { 
            System.out.println(&quot;insert 실패&quot;);
        }
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/394e5dcc-cd25-4eac-97cd-f7b5dae269ce/image.png" alt="">
insert는 잘 되는데 오류가 뜬다! 이게 거슬린다면 <code>Connection</code>객체 생성 후 아래의 코드를 추가해주자.</p>
<pre><code class="language-java">conn.setAutoCommit(false); </code></pre>
<p>그 후에는 위의 오류가 발생하지 않는 걸 확인할 수 있다!</p>
<h1 id="마치며">마치며</h1>
<p>진짜 하면서 쌍욕을 얼마나 한 지 모르겠다... 내가 제일 싫어하는 개발환경 잡기인데 하나 해결하면 다음 거 안 되고, 또 해결하면 그다음 거 안 되고... 개발은 환경설정이 전부라는 걸 다시 느끼게끔 해주었다. 또 AutoCommit같은 경우에는 ojdbc버전에 따라서 달라지는 것 같았다!
많은 사람들이 내 글을 보고 참고하라는 게 아니라, 혹시라도 미래에 또 환경설정할 일이 있다면 내가 내 글을 보고 어떻게 했는지 기억을 더듬어보려고 작성하였다.
끝!😖</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[10월 2주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/10%EC%9B%94-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/10%EC%9B%94-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 07 Oct 2022 03:02:42 GMT</pubDate>
            <description><![CDATA[<h1 id="💜-좋았던-것liked">💜 좋았던 것(Liked)</h1>
<p>데이터베이스(오라클)을 배우고, 그걸 JAVA 프로젝트와 연동하는 것까지! JDBC를 배웠었다. 학부생 때는 이런 JDBC는 혼자 공부하지 않으면 안 배우고 넘어가는 점이었는데, 몰랐던 부분을 배우게 되어서 좋았다! 하면서 생각이 났는데, 회사에서는 xml형식으로 쿼리문을 넘겼었는데... 생각해보니까 방학 프로젝트로 자바로 간단한 게임 만들면서 DB를 썼었는데, 그게 JDBC였던 것 같다! 4년전이라 기억이 가물가물하지만.... 오라클은 아니고 MySQL로 DB연동해서 랭킹 시스템을 구현했던 것 같다. </p>
<h1 id="📚-배운-것learned">📚 배운 것(Learned)</h1>
<p>DDL, DML, DCL, TCL을 배웠다. 트랜잭션에 COMMIT하고, ROLLBACK하는 법까지 배우게 되었다. 근데... 회사에서는 딱히 COMMIT을 안 했던 것 같은데, 이것도 버전과 문제가 있을까? 노트북에 JDBC연동을 하면서 테스트를 해봤는데, 학원에서는 6버전을, 노트북에는 8버전을 깔았다. 그런데 6버전에선 DML구문 후 수동으로 COMMIT을 해줬었는데, 8버전에선 오토COMMIT이 되었다. 그래서 메소드로 이 기능을 꺼줬다. 흠... 🤔
JDBC에 대해 배웠다! 기초 코드에 대한 블로그 글은 <a href="https://velog.io/@fogbow_juni/JAVA-Oracle-JDBC">여기</a>에 정리해 두었습니다!</p>
<h1 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h1>
<p>쿼리문... 회사 다닐때는 그냥 급급하게 썼고 정말 쓰레기같은 서브쿼리문도 많이 봤고 무조건 LEFT JOIN만 한가득... 그래서 그때 그냥 구글링해서 썼었다. 근데 SQL을 배우면서 개념을 다시 정리한 것까지는 좋았으나 이미 머릿속에 잘못된 개념들이 많이 잡혀있어서 이걸 바꾸는게 조금 힘들었다. 그래서 공부도 그모양....
그리고 또 맥북에서 오라클 JDBC쓰려고 끙끙댔다. 이건 따로 포스팅 하겠지만... 오라클이 애플 실리콘을 지원을 안 해준다! 그래서 처음엔 도커를 써서 로컬로 DB로 만드려 했으나... 도커 써본적도 없고, 설정도 자꾸 안 되어서(Timezone라던가...) 그냥 오라클 클라우드로 하려 했다. 근데 가입에서 튕기고, 진짜 힘들었지만 설정은 완료했다! 근데 계속 이것만 붙잡고 있으니 복습할 시간이 부족했다. 오라클과 맞장뜬 썰은 <a href="https://velog.io/@fogbow_juni/Oracle-%EC%95%A0%ED%94%8C-%EC%8B%A4%EB%A6%AC%EC%BD%98-%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%B0%8F-JDBC-%EC%97%B0%EB%8F%99">여기!</a></p>
<h1 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h1>
<p>날씨가 갑자기 추워졌다... 저번에 아픈 이후로 몸관리 좀 신경써서 하려 한다! 또 SQL개념 정리가 다시 필요한 것 같다. 수업시간에 좀 많이 졸아서 대충 들은 것도 있지만... 이건 정말로 반성하고 있다! 사실 카페인이 너무 안 받아서 새벽 세시까지 잠을 못 자는데, 그냥 이제는 알커피 타 마시고 있다. 그래도 잠은 잘 자니까!
JDBC 공부가 좀 더 필요한 것 같다. 아직 샘플 코드가 없으면 기억이 가물가물~.... 동작 순서를 좀 깊게 파고 들 필요가 있을 것 같다.
끝!😏</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] Oracle JDBC ]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-Oracle-JDBC</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-Oracle-JDBC</guid>
            <pubDate>Thu, 06 Oct 2022 12:16:50 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<blockquote>
<p>Java DataBase Connectivity :  자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API</p>
</blockquote>
<h1 id="📦-oracle에-계정-및-테이블-추가">📦 Oracle에 계정 및 테이블 추가</h1>
<p>eclipse에서 JDBC를 사용하기 전에, 로컬 Oracle 데이터 베이스에 JDBC계정과 TEST테이블을 추가하였다.</p>
<pre><code class="language-sql">CREATE USER JDBC IDENTIFIED BY JDBC;
GRANT CONNECT, RESOURCE TO JDBC;

CREATE TABLE TEST (
    TNO NUMBER,
    TNAME VARCHAR2(20),
    TDATE DATE
);</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/783985d8-4188-4b4f-98eb-7ee99d9152eb/image.png" alt="">
테이블이 잘 만들어졌고,
<img src="https://velog.velcdn.com/images/fogbow_juni/post/802ca42e-33a6-4deb-b424-c8fd2825bbed/image.png" alt="">
데이터도 잘 넣어 두었다.</p>
<h1 id="🔧-jdbc-라이브러리-추가">🔧 JDBC 라이브러리 추가</h1>
<p>먼저 JDBC를 사용하기 전에 프로젝트 파일에 JDBC 라이브러리를 추가하여 주었다. 오라클 JDBC를 사용하였고, 이를 eclipse의 build path에 추가하여 주었다.
Project -&gt; Properties -&gt; Java Build Path -&gt; Libraries -&gt; Add External JARs 에서 ojdbc6.jar가 있는 경로를 찾아, 해당 파일을 추가하여 주었다!
<img src="https://velog.velcdn.com/images/fogbow_juni/post/b8b9e5a4-20b4-4125-a466-d951eba32603/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/a2466f7b-a17b-4141-a268-b508c471539a/image.png" alt="">
프로젝트 폴더의 <code>.classpath</code>을 확인해 보면 5번째 줄과 같이 라이브러리 추가가 잘 된 것을 확인할 수 있다!</p>
<h1 id="🧾-jdbc-사용">🧾 JDBC 사용</h1>
<p>JAVA 프로젝트에서  JDBC 사용을 하려면 다음과 같은 처리를 해주어야 한다.</p>
<blockquote>
</blockquote>
<ol start="0">
<li>필요한 변수 생성</li>
<li>JDBC Driver 등록</li>
<li>Connection 생성</li>
<li>Statement 생성</li>
<li>SQL문을 전달하면서 실행</li>
<li>결과를 받아서 VO객체에 담거나, 트랜잭션 처리</li>
<li>다 쓴 JDBC용 객체들의 자원 반납</li>
</ol>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/6240f4e4-2e63-42d1-87b7-4d09f775a911/image.png" alt="">
뭐가 이렇게 많은지... 코드로 보면서 정리해 보자.</p>
<h2 id="0-필요한-변수-생성">0. 필요한 변수 생성</h2>
<p>먼저 SELECT 구문을 생성하기 위해서 Connection과, Statement, SELECT 구문의 결과를 받을 ResultSet 객체를 생성한 뒤, 사용할 sql구문을 문자열로 선언하여 주었다.</p>
<pre><code class="language-java">Connection conn = null;
Statement stmt = null;
ResultSet rset = null;

String sql = &quot;SELECT * FROM TEST&quot;;</code></pre>
<blockquote>
<p><code>Connection</code> 객체 : DB의 연결정보를 담고있는 객체 
<code>Statement</code> 객체 : 해당 DB에 SQL문을 전달하고 실행한 후 결과를 받아내는 객체
<code>ResultSet</code> 객체 : 만일 실행한 SQL문이 SELECT문일 경우 조회된 결과들이 담겨있는 객체</p>
</blockquote>
<h2 id="1-jdbc-driver-등록">1. JDBC Driver 등록</h2>
<p>JDBC Driver를 <code>Class.forName()</code>를 통해 등록하여 준다. 이때 <code>try-catch</code>문이 없으면 컴파일 오류가 나기 때문에 <code>try-catch</code>문 안에 선언하여 준다. </p>
<pre><code class="language-java">try{
    Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}</code></pre>
<h2 id="2-connection-생성">2. Connection 생성</h2>
<p>JDBC Driver를 등록하였으면 Connection을 생성하여준다. 우리는 conn이라는 객체를 생성해두었는데, 이 안에 Connection을 생성하여 줄 것이다. 이 또한 <code>try-catch</code>문이 없으면 컴파일 오류가 발생하기 때문에, 위에 쓴 <code>try</code>문에 Connection 코드를, <code>catch</code>문에 <code>SQLException</code> 처리를 해준다.</p>
<pre><code class="language-java">try{
    conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:xe&quot;, &quot;JDBC&quot;, &quot;JDBC&quot;);        // 접속할 DB의 url, id, password를 입력하여 준다.
} catch (SQLException e) {
    e.printStackTrace();
}</code></pre>
<h2 id="3-statement-생성">3. Statement 생성</h2>
<p>Connection 생성이 완료되었다면, Statement를 생성해준다. <code>try</code>문 안에서 conn생성하는 줄 아래에 선언해주면 된다.</p>
<pre><code class="language-java">stmt = conn.createStatement();</code></pre>
<h2 id="4-sql문을-전달하면서-실행">4. SQL문을 전달하면서 실행</h2>
<p>SELECT절의 결과는 ResultSet이다. 위에서 우리는 ResultSet 객체를 생성해뒀으니, 해당 객체에 결과를 받아주면 된다. <code>executeQuery()</code>메소드의 반환형은 ResultSet이다.</p>
<pre><code class="language-java">rset = stmt.executeQuery(sql);</code></pre>
<h2 id="5-결과를-받아서-vo객체에-담거나-트랜잭션-처리">5. 결과를 받아서 VO객체에 담거나, 트랜잭션 처리</h2>
<p>SELECT문의 경우 결과를 받아서 출력하거나, VO객체에 담는다. 트랜잭션 처리는 후술할 예정이지만 SELECT를 제외한 DML문에서 처리해줘야 한다. (INSERT, UPDATE, DELETE)
해당 예제에서는 단순히 ResultSet을 콘솔창에 출력해 주었다.</p>
<pre><code class="language-java">while(rset.next()) {
    int tNo = rset.getInt(&quot;TNO&quot;);
    String tName = rset.getString(&quot;TNAME&quot;);
    Date tDate = rset.getDate(&quot;TDATE&quot;);

    System.out.println(tNo +  &quot;, &quot; + tName + &quot;, &quot; + tDate);

}</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/9c17b318-68ff-4784-b83b-ed82dc7106a9/image.png" alt="">
DB에 있는 데이터들이 잘 SELECT되어 콘솔창에 출력되었다!</p>
<p>출력하기 위해서 반복문 안에 <code>next()</code>메소드를 사용하였는데, 이 메소드는 ResultSet의 커서를 하나씩 아래로 이동시켜주는 역할을 한다. 또한 해당 행이 존재하면 <code>true</code>를, 없다면 <code>false</code>를 반환하여 준다. 따라서 ResultSet의 끝까지 반복하면서 데이터들을 출력하였다.</p>
<h2 id="6-다-쓴-jdbc용-객체들의-자원-반납">6. 다 쓴 JDBC용 객체들의 자원 반납</h2>
<p>가장 중요하다!!! <code>Scanner</code>클래스를 다 사용하였다면 <code>close()</code>메소드를 사용한 것 처럼, JDBC도 자원 반납을 해주어야 한다. 자원반납을 해주는 위치는 <code>finally</code>문에서 하면 된다. 또한 <code>close()</code>메소드를 사용하기 위해서는 <code>try-catch</code>문이 필요하고, <strong>생성의 역순으로 자원반납을 해주어야 한다!</strong></p>
<pre><code class="language-java">finally {
        try {
            rset.close();
            stmt.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }</code></pre>
<h2 id="jdbc-select-전체-코드">JDBC SELECT 전체 코드</h2>
<p>JDBC를 통해 SELECT하는 전체 코드는 다음과 같다.</p>
<pre><code class="language-java">          Connection conn = null;
        Statement stmt = null;
        ResultSet rset = null;

        String sql = &quot;SELECT * FROM TEST&quot;;

        try {
            Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
            conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:xe&quot;, &quot;JDBC&quot;, &quot;JDBC&quot;);
            stmt = conn.createStatement();
            rset = stmt.executeQuery(sql);

            while(rset.next()) {

                int tNo = rset.getInt(&quot;TNO&quot;);
                String tName = rset.getString(&quot;TNAME&quot;);
                Date tDate = rset.getDate(&quot;TDATE&quot;);

                System.out.println(tNo +  &quot;, &quot; + tName + &quot;, &quot; + tDate);

            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }  finally {
            try {
                rset.close();
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }</code></pre>
<h2 id="5_2-트랜잭션-처리">5_2. 트랜잭션 처리</h2>
<p>만약 내가 사용할 쿼리가 INSERT, UPDATE, DELETE라면 조금 다르게 처리해주어야 한다. 실행할 쿼리가 다음과 같다면, 트랜잭션 처리를 해주어야 한다.</p>
<pre><code class="language-java">String sql = &quot;INSERT INTO TEST VALUES(50, &#39;쥬니쥬니&#39;, SYSDATE)&quot;;</code></pre>
<p>해당 구문은 INSERT문이기 때문에 Statement의 <code>executeUpdate()</code>메소드를 사용해야 하며, 반환형은 <code>int</code>형이다. 이것은 DML을 오라클에서 실행하면 n행이 실행되었다고 나오는데, 여기서 n이 반환값이 된다고 보면 된다.</p>
<pre><code class="language-java">int result = stmt.executeUpdate(sql);</code></pre>
<p>이렇게 DML문을 사용하였으면 트랜잭션 처리를 해주어야 한다. result의 값이 0보다 크면 쿼리문이 실행된 것이고, 그렇지 않다면(물론 실행되어서 0행이 실행되었습니다. 하고 뜨겠지만...) 쿼리문이 제대로 실행되지 않은 것이다. 따라서 조건문으로 간단히 트랜잭션을 처리하여 준다.</p>
<pre><code class="language-java">if( result &gt; 0 ) {
    conn.commit();
} else {
    conn.rollback();
}</code></pre>
<p>나머지 부분들은 SELECT와 마찬가지로 작성해주면 된다.</p>
<h2 id="jdbc-insert-전체-코드">JDBC INSERT 전체 코드</h2>
<pre><code class="language-java">int result = 0;
Connection conn = null;
Statement stmt = null;

String sql = &quot;INSERT INTO TEST VALUES(50, &#39;쥬니쥬니&#39;, SYSDATE)&quot;;

try {

    Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
    System.out.println(&quot;driver 등록 성공!!&quot;);

    conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:xe&quot;, &quot;JDBC&quot;, &quot;JDBC&quot;);
    System.out.println(&quot;Connection 객체 생성!&quot;);


    stmt = conn.createStatement();
    System.out.println(&quot;Statement 객체 생성!&quot;);

    result = stmt.executeUpdate(sql);

    if (result &gt; 0) { // 성공했을 경우 commit
        conn.commit();
    } else { // 실패했을 경우 rollback
        conn.rollback();
    }
} catch (ClassNotFoundException e) {
        e.printStackTrace();
} catch (SQLException e) {
        e.printStackTrace();
} finally {
        try {
            stmt.close();
            conn.close();
        } catch (SQLException e) {
                e.printStackTrace();
        }

}

if (result &gt; 0) { 
    System.out.println(&quot;insert 성공&quot;);
} else { 
    System.out.println(&quot;insert 실패&quot;);
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/01c62178-b5c5-4ff1-9b40-b49cf2f754db/image.png" alt="">
콘솔에 다음과 같이 나오고,
<img src="https://velog.velcdn.com/images/fogbow_juni/post/8a56a975-695b-4243-8b8d-f4c0040cdd4d/image.png" alt="">
DB에 잘 등록된 걸 확인할 수 있다!</p>
<h1 id="📖-마치며">📖 마치며</h1>
<p>포스팅이 늦어진 계기... 그것은 맥북에어(M2)와 오라클의 싸움에서 제가 새우등이 터져 피눈물을 흘렸기 때문입니다... 회고에서도 쓸 거지만 도커는 도대체 어떻게 쓰는 것이며 오라클 클라우드는 왜 나의 회원가입을 입구컷 했던 것일까...
더이상 포스팅을 지체할 수 없어서 윈도우 환경에서 했던 걸 포스팅 했습니다! JDBC... 회사에서는 이런 방법 말고 xml파일로 만들어 쿼리문을 날리곤 했는데, 뭔가 기초부터 다시 탄탄히 배우니까 지식의 깊이가 깊어져감을 느꼈습니다. 또한, 이제 본격적으로 MVC패턴에 맞추어 프로젝트를 만들고 하는 게 좋았습니다! 여기에 적응해는 저를 발견 할 수 있었습니다
아무튼 그럼 다시 오라클과 맥북에어의 싸움을 붙이러...
끝! 😉</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[9월 5주차 ~ 10월 1주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/9%EC%9B%94-5%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/9%EC%9B%94-5%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 30 Sep 2022 01:00:12 GMT</pubDate>
            <description><![CDATA[<h1 id="💜-좋았던-것liked">💜 좋았던 것(Liked)</h1>
<p>이번주는 뭔가 폭풍같았던 주였다... 학원에서 시험을 두개나 보고...
자바진짜최종최종의끝.java을 했다! 설계라고 하기에도 뭐하지만 MVC모델로 진짜 완전 소규모의 프로젝트 파일을 만들어봤다! 
<img src="https://velog.velcdn.com/images/fogbow_juni/post/36a359bb-3692-47a7-b7be-3674df103b12/image.png" alt="">(설계를 고민한 흔적이라면 흔적이겠지)</p>
<p>자판기랑 애견호텔을 만들어봤는데, 둘 다 파일입출력 쓰고, <code>ArrayList</code>로 구현했다. 진짜 자바 복습이라 생각하고 배운 내용을 좀 많이 써서 만들어보았다! 특히 콜렉션 쓰는 데에 익숙해진 것 같다.
오라클을 시작했다! 서브쿼리까지 진도가 나갔는데, 뭔가 회사 다닐때의 서브쿼리안에서브쿼리안에서브쿼리안에서브쿼리안에서브쿼리절이 생각나는 것 같았다... 근데 그때는 MySQL로 진행했었고(학원에서 ANSI 구문도 다뤘다.), 학원에서는 오라클 문법을 다루는데 JOIN 같은 경우 차이가 나서 또 모르는 걸 배웠다!</p>
<h1 id="📚-배운-것learned">📚 배운 것(Learned)</h1>
<p>오라클 설치부터 서브쿼리까지! 또 몰랐던 건 쿼리의 실행 순서를 배웠다. 사실 학교시절 DB는 1학기만 듣고... 2학기에는 손절했었다. 걍 평생 <code>SELECT</code> <code>INSERT</code> <code>UPDATE</code>정도만 할 줄 알았지. 그땐 그랬지.... 그래서 회사에서도 좀 고민했고, 작년은 정말 자바보다 쿼리문이랑 로그 파일을 엄청 많이 보았다. 좀 학교에서 잘 했더라면 어떨까 싶었지만, 아무튼, 회사에서 급급하게 하느라 동작 원리도 모르고 가져다 쓰는 것도 많았다. <del>그리고 떠오르는 쓰레기같은 서브쿼리문</del> 
아무튼 이렇게 얄팍하게 잡혀있던 개념들을 다시 한 번 되집고 갈 수 있어서 좋았다.</p>
<h1 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h1>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/94062730-f092-407b-a8ef-70a9763b68ce/image.png" alt=""></p>
<p>나도 내가 이렇게 아플 줄 몰랐다.... 그리고 인간의 몸은 왜이렇게 나약한가를 또 느꼈다. 화요일 오후시간부터 이상하게 피곤하고, 힘들어서 나는 내가 커피를 안 마셔서 그런가 싶었는데 그게 아녔다. 집에 가면서 진짜 추워서 몸이 으슬거렸고, 너무 지친 나머지 어머니께 마중까지 부탁하는 지경에 이르는데...! 
집에와서 저녁도 거르고 코부터 찔렀는데, 음성이었다. 근데... 열이 너무 많이났다. 처음에는 뜨거운물로 씻어서 그런가 싶었는데, 떨어지긴 무슨 열이 더 올랐다. 
<img src="https://velog.velcdn.com/images/fogbow_juni/post/94ac0617-cabf-42cd-870b-3f260848f703/image.png" alt="">
여기서 더 오를 줄도 몰랐다... 진짜 너무 힘든데 열이 너무 많이 나서 코시국에 응급실도 입구컷 당할 것 같고, 그나마 다행인건 얼음팩 끼고 한참있다 좀 떨어져서 자고 일어나서 다음날 아침에 병원에 갈 정도는 되었다. 힘들었지만!</p>
<p>병원가서 신속항원검사부터 했다. 그런데...
<img src="https://velog.velcdn.com/images/fogbow_juni/post/c2adb18f-adf0-4c6c-9f51-8e8f5b161ca6/image.png" alt="">
음성이다. 그 모든 일이 있었음에도, 여전히 음성이다. 가족 다 걸릴 때 혼자만 안 걸려서 이번에는 기필코정말왔구나 싶었는데... 급성 편도염으로 목이 많이 부어서 열이 많이 났다고 한다. 
분명 저번주 회고에서 환절기 몸관리 잘 하고자 했는데, 그걸 못지키다니... 아니 나도 아파서 정말 당황스러웠다.</p>
<h1 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h1>
<p>아이폰 미리알림. 이걸 이제 처음 써봤다. 거추장스러운 걸 싫어해서 폰 바꾸면 순정 어플 필요한 걸 싹다 지우는 편인데, 그걸 얼마나 했지? 아무튼 이걸로 아침에 나가기 전에 비타민D먹기를 등록해두니 안 까먹고 좋았다! 앞으로도 안 까먹고 챙기면 좋겠다.
근데, 비타민D를 챙기니 감기약이고 이명약이고 까먹었다. 병원 다녀와서 이명검사도 했는데, 약을 꾸준히 먹으면 괜찮다고는 한다. 근데 그걸 벌써 까먹고 안 챙겼다. 제발 약 좀 잘 챙겼으면 좋겠다!
그리고 여전히 복습 좀 꾸준히 하자. 사실 맥북 m1칩으로 오라클 도커 연동하다 빡쳐서 다 때려쳤는데, 그냥 데스크탑으로 하면 편할 것을... 어떻게 되었던 복습은 중요하고, 아프다고 좀 쉬었으니 주말에 복습 마저 하는 걸 바란다.
끝!😆</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[9월 4주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/9%EC%9B%94-4%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/9%EC%9B%94-4%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 23 Sep 2022 13:02:10 GMT</pubDate>
            <description><![CDATA[<h1 id="💜-좋았던-것liked">💜 좋았던 것(Liked)</h1>
<ul>
<li><p>벌써 국비교육을 다닌지 4주? 정도가 지났다! 후다닥 자바를 끝냈는데, 학부 시절에 배웠지만 기억이 안 나는 것들(특히 상속쪽)을 다시 환기 시킬 수 있어서 좋았다. 또한 학기말에 진도를 급하게 빼느라 대충 다뤘던 파일 입출력, Collection에 대해 다시 짚고 넘어갈 수 있어서 좋았다. 그 뿐만 아니라 내가 잘못 기억하고 있던 것들을 바로잡은 것 같아서 좋았다.</p>
</li>
<li><p>이번 주에는 또한 MVC패턴으로 그동안 배운거 정리해 보았다! 공부한 것들도 복습이 되고, 실제 MVC패턴과 가깝게 코딩해볼 수 있어서 좋았다.</p>
</li>
<li><p>(여기서부턴 일상 이야기)
<img src="https://velog.velcdn.com/images/fogbow_juni/post/4f631e92-c2aa-46b3-b313-1425935b4d4f/image.png" alt="">
학원이 종각~을지로 사이에 있다 보니... 먹을 것도 많고, 청계천도 너무 좋다! 학원 바로 옆에 우육탕면집이 생겼는데... 이틀 연속 가서 먹을 정도였다. 물론 투썸에서 하는 샐러드 프로그램을 신청했지만... 아무튼, 요즘 점심식사 후에 한바퀴 산책을 하는데, 날도 좋고 바람도 선선하고 진짜 가을 날씨여서 너무 좋았다.</p>
</li>
</ul>
<h1 id="📚-배운-것learned">📚 배운 것(Learned)</h1>
<ul>
<li>상속에 관하여! <a href="https://velog.io/@fogbow_juni/JAVA-%EC%83%81%EC%86%8D%EA%B3%BC-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%98%95%EB%B3%80%ED%99%98">링크</a></li>
<li>추상화 인터페이스에 관하여! <a href="https://velog.io/@fogbow_juni/JAVA-%EC%B6%94%EC%83%81%ED%99%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4">링크</a></li>
<li>JAVA API에 관하여! <a href="https://velog.io/@fogbow_juni/JAVA-JAVA-API">링크</a></li>
<li>콜렉션에 관하여! <a href="https://velog.io/@fogbow_juni/JAVA-Collection">링크</a></li>
<li>파일 입출력과 예외처리 try~catch<ul>
<li>예외처리 부분은 학교에서 대충 했고... 그냥 파일 입출력을 할 때 없으면 컴파일이 안 되도록 막혀있으니까 그냥 썼는데, 이거에 대한 개념을 다시 정리할 수 있었다.</li>
</ul>
</li>
</ul>
<h1 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h1>
<ul>
<li>항상 주석 다는게 너무너무 귀찮아서... 잘 안 다는 것 같다. 그런데 학원에서 대충 달아놓고 나중에 코드 다시 보고 복습하면서 블로그 포스팅 하려니 주석이 뭔소린지 모르겠다! 실무할 때 너무 많은 주석도 안 좋다고 들었는데(뭐든지 적당히) 적어도 배우는 입장에선 꼼꼼히 달아야겠다.</li>
<li>컬렉션 사용에 익숙해질 필요가 있다. 사실 실무 하면서도 ArrayList나 HashMap을 사용하긴 했었다. 하지만 개념이 얕은 상태에서 이것들을 사용하려 하니... 그냥 구글링 해서 대충 이렇게 쓰는가부다~ 하고 넘어갔었다. 그러나 지금은 컬렉션에 대해 배웠고, 앞으로 코딩할 때 이 컬렉션들을 사용해서 익숙해져야겠다.</li>
<li>좀 더 깔끔하게 코드 짤 필요가 있다! 엔터나 들여쓰기는 그렇다 치는데... 향상된 for문과 같은 가독성 좋은 코드로 짜는 게 부족했다.</li>
</ul>
<h1 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h1>
<ul>
<li>블로그 포스팅 꾸준히 하기! 이제 시작한지 딱 일주일이 된 것 같은데, 그래도 이번주에는 포스팅도 많이 하고, 이렇게 회고까지 쓰고 있다. 이걸 잘 버릇 들이면 좋겠다. 블로그 포스팅을 하면서 가장 좋은점은 복습이 된다는 점이니까!</li>
<li>날이 급격하게 추워졌다. 이불을 두개 덮고 자기 시작한 건 벌써 3주도 더 된 것 같다... 이런 시즌에는 필이 감기 걸리기 필순데, 몸조리 잘해야겠다!</li>
<li>제발 아침에 비타민 먹는 것좀 안 잊어먹었으면 좋겠다. 이거 안 먹으면 하루종일 너무너무 피곤하다. 지금도 사실 어무니가 피곤해 보인다고 하신다.</li>
<li>운동도 꾸준히!!! 진짜 못해도 매일 점심에 걸어다니는 건 꼭 해야겠다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/1ee9b1b7-78f9-44c8-aee8-24254df65f17/image.png" alt="">
(친구가 환절기 버전이라고 그려줬습니다😁)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] Collection]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-Collection</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-Collection</guid>
            <pubDate>Fri, 23 Sep 2022 12:45:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<h1 id="📚-collection">📚 Collection</h1>
<p>만약 콜렉션이 없다면 실무에서 개발하기 너무너무 어려울 것이다. 일일히 구현을 하나씩 전부 해줘야하고, 그 구현하는데 시간 다 까먹고... 
<img src="https://velog.velcdn.com/images/fogbow_juni/post/10946339-0bee-490e-8f77-533fa1c3f0b1/image.png" alt="">
그래서 자바에서는 콜렉션을 제공한다. 자바에서의 콜렉션은 자료구조를 내장하고 있는 프레임워크이다. 그래서 우리는 스택, 큐, 정렬등을 직접 구현 안 하고도 손쉽게 가져다 쓸 수 있다.</p>
<p>또한 배열은 하나의 타입의 데이터들만 저장 가능하고, 한 번 지정된 크기는 변경이 불가능하고, 배열 중간에 위치한 데이터를 추가하거나, 중간에 새로운 데이터를 삭제하려면 기존의 데이터를 뒤로 밀거나, 앞으로 당겨서 사용해야 하는 불편함이 있다.</p>
<p>반면 콜렉션을 이용하면 여러 타입의 데이터들을 한번에 저장 가능하고(물론 제네릭을 이용해 하나의 타입에 대해서만 데이터들을 저장 할 수 있다.), 크기에 제약이 없으며, 중간에 값을 추가하거나 삭제할 때 데이터를 이동할 필요없이 메소드를 호출해서 사용이 가능하다는 장점이 있다.</p>
<p>그렇다고 무조건 배열을 지양하자, 하고자 하는 건 아니다. 방대한 데이터들을 저장만 하고 <strong>조회</strong>의 목적으로만 사용한다. 반면 컬렉션은 이런 방대한 데이터들을 <strong>추가</strong>, <strong>수정</strong>, <strong>삭제</strong>할 경우에 사용한다.</p>
<h2 id="list-계열">List 계열</h2>
<p>List계열은 담고자 하는 값(Value)만 저장하고, 저장 시 순서(Index)를 유지, 중복값을 허용한다. List 계열이 예시로는 ArrayList, LinkedList, Vector가 있다. 여기에서는 가장 많이 사용하는 ArrayList 사용법에 대해 알아볼 것이다.</p>
<h3 id="arraylist">ArrayList</h3>
<p>우선 표현법은 다음과 같다.</p>
<pre><code class="language-java">ArrayList list = new ArrayList(int size);</code></pre>
<p>여기서 <code>ArrayList</code>의 사이즈는 생략이 가능하다. 또한 만약 <code>ArrayList</code>의 사이즈를 3으로 지정하고, 만약 크기가 3을 벗어날 경우, 자동으로 크기가 늘어난다. 
또한, 하나의 데이터 타입이 아닌 여러 종류의 타입을 담을 수 있다. 아래에 예시로 Music.java라는 클래스를 만들고, 이 클래스를 통해 만든 객체와 다른 데이터를 <code>ArrayList</code>에 담아 보는 예제이다. 데이터를 추가할 때에는 <code>add()</code>메소드를 사용하면 된다.</p>
<pre><code class="language-java">// Music.java
public class Music {

    private String title;
    private String artist;

    public Music() {
        super();
    }

    public Music(String title, String artist) {

        super();
        this.title = title;
        this.artist = artist;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    @Override
    public String toString() {
        return &quot;Music [title=&quot; + title + &quot;, artist=&quot; + artist + &quot;]&quot;;
    }

}
</code></pre>
<pre><code class="language-java">//ArrayListRun.java
public class ArrayListRun {
    public static void main(String[] args){

    ArrayList list = new ArrayList(3);    // 크기가 3인 ArrayList형의 list 생성
    // add()메소드를 통해 list에 데이터 추가
    list.add(new Music(&quot;기억을 걷는 시간&quot;, &quot;넬&quot;));
    list.add(new Music(&quot;29&quot;, &quot;너드커넥션&quot;));
    list.add(new Music(&quot;알루미늄&quot;, &quot;브로큰발렌타인&quot;));
    System.out.println(list);
    }

}</code></pre>
<pre><code>[Music [title=기억을 걷는 시간, artist=넬], Music [title=29, artist=너드커넥션], Music [title=알루미늄, artist=브로큰발렌타인]]</code></pre><p><code>toString()</code>메소드가 오버라이딩 되어 잘 출력됨을 확인할 수 있다. 그러면 이 출력된 객체에서 첫번째에 저장된 노래제목 title만 뽑아내고 싶으면 어떻게 해야할까? 우선 <code>ArrayList</code>의 <code>get()</code>이라는 메소드가 있다. 이 메소드는 인덱스 번호를 매개변수로 하여, 해당 인덱스의 데이터를 반환하여 준다. 그러면 위의 코드에선 Music 타입의 객체 하나만 반환되니, 참조 연산자로 getTitle()을 하면 되겠지. 했지만...</p>
<pre><code class="language-java">System.out.println(list.get(0).getTitle());</code></pre>
<p>위와 같이 작성하면 빨간줄이 그어지며 오류가 난다. 오류 메세지에는 <code>The method getTitle() is undefined for the type Object</code>라고 적혀있다. Object클래스에 정의되지 않은 메소드를 사용하려 했기 때문에 오류가 났다. 그럼 간단하다. 모든 클래스는 Object클래스를 상속받고 있기 때문에, 다운캐스팅을 통해 강제 형변환을 해주면 될 것이다.</p>
<pre><code class="language-java">System.out.println(((Music)list.get(0)).getTitle());    // 연산자 우선순위에 주의하자. 괄호로 묶지 않으면 오류가 난다.</code></pre>
<p>여기서 하나의 의문점은, 분명 Music객체가 반환될텐데 Object객체로 반환되었다는 점이다. 이것은 우리가 처음 list를 만들 때 제네릭으로 만들지 않아서이다. 해당 관련 내용은 아래 Generic에서 서술할 것이다.</p>
<p>이외에도 다양한 메소드가 이미 구현되어 있다. 리스트의 부분만 추출해서 새로운 리스트를 만들어 반환하는 <code>subList()</code>, 리스트가 비어있는지 확인해주는 <code>isEmpty()</code>, 현재 리스트의 사이즈를 반환해주는 <code>size()</code>등이 있다.</p>
<h2 id="set-계열">Set 계열</h2>
<p>Set계열은 저장하고자 하는 값만 저장하고, 저장 시 <strong>Index개념을 무시</strong>하며(저장 순서를 보장해주지 않는다.), <strong>중복값을 허용하지 않는다.</strong> Set계열의 대표적인 자료구조인 HashSet에 대해 알아보고자 한다.</p>
<h3 id="hashset">HashSet</h3>
<p>HashSet의 표현은 아래와 같이 한다.</p>
<pre><code class="language-java">HashSet 객체이름 = new HashSet();
// HashSet&lt;String&gt; hs = new HashSet&lt;String&gt;(); 당연히 제네릭으로 선언해도 된다.</code></pre>
<p>또한 HashSet의 사용은 ArrayList와 비슷하게 사용한다. Hash에 데이터를 추가하기 위해서 <code>add()</code>메소드를 사용한다.</p>
<pre><code class="language-java">HashSet&lt;String&gt; hs = new HashSet&lt;String&gt;();
hs.add(&quot;문자열 입니다.&quot;);
hs.add(&quot;중복 데이터 입력&quot;);
hs.add(&quot;중복 데이터 입력&quot;);

System.out.println(hs);</code></pre>
<p>위에 서술한 것 처럼 중복값을 허용하지 않는다를 확인하기 위해서 중복값도 추가한 뒤 출력해 본다.</p>
<pre><code>[문자열 입니다., 중복 데이터 입력]</code></pre><p>&quot;중복 데이터 입력&quot;문자열은 중복된 데이터기 때문에 두번 추가되지 않고, 한 번만 추가되었다. 그렇다면 아래와 같이 객체를 추가하여 출력해보면 어떻게 될까?</p>
<pre><code class="language-java">HashSet&lt;Music&gt; musicSet = new HashSet&lt;Music&gt;();

musicSet.add(new Music(&quot;기억을 걷는 시간&quot;, &quot;넬&quot;));
musicSet.add(new Music(&quot;중복된 노래&quot;, &quot;중복된 가수&quot;));
musicSet.add(new Music(&quot;중복된 노래&quot;, &quot;중복된 가수&quot;));

System.out.println(musicSet);</code></pre>
<pre><code>[Music [title=중복된 노래, artist=중복된 가수], Music [title=기억을 걷는 시간, artist=넬], Music [title=중복된 노래, artist=중복된 가수]]
// 저장 순서는 보장되지 않았다.    </code></pre><p><img src="https://velog.velcdn.com/images/fogbow_juni/post/6b1aca63-f57e-4696-a13b-292f075c8ee7/image.png" alt=""></p>
<p>분명 위의 설명 대로라면, 같은 값을 가진 데이터가 들어가면 안 될 텐데... 중복값이 놀랍게도 들어갔다! 그 이유는 다음에 있다.</p>
<p>HashSet은 값이 추가될 때마다 <code>equals()</code>와 <code>hashCode()</code>로 비교 후 두 개의 결과가 모두 true일 경우에만 동일 객체로 취급한다.
따라서 같은 값을 가진 객체더라도, 다른 주소를 참조하고 있기 때문에 false가 반환되어 HashSet이 다른 객체로 취급하기 때문에 중복값이 들어가는 것처럼 보인다. 먼저 이것들을 <code>equals()</code>와 <code>hashCode()</code> 메소드로 출력해 보았다.</p>
<pre><code class="language-java">Music m1 = new Music(&quot;중복된 노래&quot;, &quot;중복된 가수&quot;);
Music m2 = new Music(&quot;중복된 노래&quot;, &quot;중복된 가수&quot;);

System.out.println(m1.equals(m2));
System.out.println(m1.hashCode());
System.out.println(m2.hashCode());</code></pre>
<pre><code>false
118352462
1550089733</code></pre><p>이 두 메소드는 최상위 클래스 Object클래스에 정의되어 있다. 그러나 상식적으로, 같은 값을 입력했는데 주소가 달라 다른 객체로 판단이 되어 HashSet에 들어가면 조금 곤란한 일이 생길수도 있다.(중복을 허용하면 안 되는데 중복값이 들어간다거나...) 따라서 우리는 이 두 메소드를 <code>toString()</code>메소드처럼 오버라이딩 하여 사용되는 것이 권장된다.</p>
<pre><code class="language-java">@Override
public int hashCode() {
    final int prime = 31;        // 소수 중 적당히 큰 수인 31을 prime로 쓴다고 한다.
    int result = 1;
    result = prime * result + ((artist == null) ? 0 : artist.hashCode());
    result = prime * result + ((title == null) ? 0 : title.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Music other = (Music) obj;
    if (artist == null) {
        if (other.artist != null)
            return false;
    } else if (!artist.equals(other.artist))
        return false;
    if (title == null) {
        if (other.title != null)
            return false;
    } else if (!title.equals(other.title))
        return false;
    return true;
}</code></pre>
<p>다행이도 이클립스 기준 자동완성을 지원한다! 그럼 이 상태로 다시 <code>equals()</code>와 <code>hashCode()</code>를 출력해 보자.</p>
<pre><code>true
2038544073
2038544073</code></pre><p>오버라이딩하니 값이 출력 값이 바뀌었다! 따라서 오버라이딩 후에 이 두 객체를 HashSet에 추가하면 중복값으로 인식되어 하나만 들어가게 된다.</p>
<pre><code class="language-java">musicSet.clear();    // 먼저 hashSet을 초기화 해 주었다.

musicSet.add(m1);
musicSet.add(m2);</code></pre>
<pre><code>[Music [title=중복된 노래, artist=중복된 가수]]
</code></pre><h2 id="map-계열">Map 계열</h2>
<p>Map계열은 key와 value가 하나의 세트로 저장이 되는 자료구조이다. Map은 저장 시 순서 유지가 안 되고, 중복 key도 허용이 안 되지만, 중복 값은 허용이 된다. Map의 대표적인 예시로는 HashMap과 properties가 있다.</p>
<h3 id="hashmap">HashMap</h3>
<p>먼저 HashMap은 다음과 같이 사용한다.</p>
<pre><code class="language-java">HashMap&lt;key, value&gt; 이름 = new HashMap&lt;key, value&gt;();</code></pre>
<p>HashMap은 List, Set과는 다르게 <code>put()</code>을 통해 데이터를 추가한다.</p>
<pre><code class="language-java">// 먼저 Music 객체 3개를 만든 후
Music m1 = new Music(&quot;기억을 걷는 시간&quot;, &quot;넬&quot;);
Music m2 = new Music(&quot;29&quot;, &quot;너드커넥션&quot;);
Music m3 = new Music(&quot;알루미늄&quot;, &quot;브로큰발렌타인&quot;);

// HashMap을 만든 후        
HashMap&lt;String, Music&gt; hm = new HashMap&lt;String, Music&gt;();

// HashMap에 put()을 통해 Music객체 3개를 넣고
hm.put(&quot;1번&quot;, m1);
hm.put(&quot;2번&quot;, m2);
hm.put(&quot;3번&quot;, m3);

// key값은 다르게 넣고 같은 값을 넣은 후
hm.put(&quot;4번&quot;, m1);

// 출력하였다.
System.out.println(hm);</code></pre>
<pre><code>{4번=Music [title=기억을 걷는 시간, artist=넬], 3번=Music [title=알루미늄, artist=브로큰발렌타인], 2번=Music [title=29, artist=너드커넥션], 1번=Music [title=기억을 걷는 시간, artist=넬]}</code></pre><p>특히 4번 key에 같은 m1객체를 넣었는데도 제대로 동작이 되는 걸 알 수 있었다.</p>
<p>데이터를 가져오려면 <code>get(key)</code>를 하면 된다. 여기서 주목해야 할 점은, key값을 통해 데이터를 가져온다는 점이다.</p>
<pre><code class="language-java">System.out.println(hm.get(&quot;1번&quot;));</code></pre>
<pre><code>Music [title=기억을 걷는 시간, artist=넬]</code></pre><p>그런데 우리가 이 HashMap에 있는 데이터들에 순차적으로 접근하고 싶을 때는 어떻게 해야할까? 인덱스가 없기 때문에 for문을 쓸 수도 없는 노릇이다. 그 때, 우리는 <code>Iterator</code>을 사용하는 것이다. Map계열을 Set계열로 바꾼 뒤 출력하는 것인데, 이에 대한 사용법은 다음과 같다. 첫번째, key들의 값을 Set에 담는다. 두번째, 만들어진 Set의 데이터들을 Iterator에 담는다. 마지막으론 Iterator로부터 반복문을 이용해서 순차적으로 key와 value의 값을 출력한다.</p>
<pre><code class="language-java">Set&lt;String&gt; keyset = hm.keySet();
Iterator&lt;String&gt; itKey = keyset.iterator();

while(itKey.hasNext()) {
    String key = itKey.next();
    System.out.println(key + &quot;-&quot; + hm.get(key));
}</code></pre>
<pre><code>3번-Music [title=알루미늄, artist=브로큰발렌타인]
2번-Music [title=29, artist=너드커넥션]
1번-Music [title=기억을 걷는 시간, artist=넬]</code></pre><p>또 다른 방봅으로는 <code>entrySet()</code>을 이용하는 방법이다. 먼저 Map에 있는 key와 value세트를 Entry형식으로 Set에 담는다. 그다음 반복문을 통해 출력해 준다.</p>
<pre><code class="language-java">Set&lt;Entry&lt;String, Music&gt;&gt; entrySet = hm.entrySet();

for(Entry&lt;String, Music&gt; e : entrySet) {
    System.out.println(e.getKey() + &quot;-&quot; + e.getValue());
 }</code></pre>
<pre><code>3번-Music [title=알루미늄, artist=브로큰발렌타인]
2번-Music [title=29, artist=너드커넥션]
1번-Music [title=기억을 걷는 시간, artist=넬]</code></pre><h3 id="properties">Properties</h3>
<p>Properties는 Map계열 중 하나의 자료구조이며, key값과 value값을 세트로 저장한다. 또한 key값과 value의 값을 String형으로 다룬다. 표현법은 다음과 같다</p>
<pre><code class="language-java">Properties 이름 = new Properties();    //객체를 생성하듯 생성한다.</code></pre>
<p>예제는 다음과 같다.</p>
<pre><code class="language-java">Properties prop = new Properties();

// prop객체에 데이터 추가
prop.setProperty(&quot;List&quot;, &quot;ArrayList&quot;);
prop.setProperty(&quot;Set&quot;, &quot;HashSet&quot;);
prop.setProperty(&quot;Map&quot;, &quot;HashMap&quot;);

try {
    // store(OutputStream os, String Comments)
    // 파일을 기록할 때 쓰는 메소드
    // key = value 형태로 파일이 출력된다.
    prop.store(new FileOutputStream(&quot;song.properties&quot;), &quot;Properties Test&quot;);
    // try-catch문이 없으면 오류 발생!
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}</code></pre>
<p>이 후 프로젝트를 새로고침하면 song.properties 파일이 생성된 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/43d3b513-76d2-4cc7-9a48-e0ca394609c5/image.png" alt="">
파일이 생성되었고,
<img src="https://velog.velcdn.com/images/fogbow_juni/post/150af48a-1b60-4e49-9107-56f33af8587a/image.png" alt="">
해당 파일을 클릭하면 다음과 같은 값들이 저장된 것을 확인할 수 있다.</p>
<p>Properties의 용도는 파일 입출력을 하기 위함이다. 주로 파일로부터 읽어오는 용도로 많이 사용되고, properties확장자를 많이 사용한다. 프로젝트에서는 자주 변경되지 않는 설정 파일이나, 해당 프로그램이 기본적으로 가져야할 정보들을 담는 파일로 많이 사용된다.</p>
<h1 id="🛠-generic">🛠 Generic</h1>
<p>제네릭은 컬렉션 안에서 다룰 타입들을 미리 지정해주는 역할이다. 사실 우리가 위의 방법대로 컬렉션을 생성하면 노란 밑줄이 생길 것이다. 오류는 아니고, IDE에서 경고 메시지를 보내주는 건데...
<img src="https://velog.velcdn.com/images/fogbow_juni/post/0e5b1dfc-4529-413b-b6fc-853a1d0c411d/image.png" alt="">
이 이유는 컬렉션을 제네릭으로 생성하지 않아서이다. 제네릭을 사용하지 않았다면 컬렉션 객체 생성 시 다양한 타입이 담길 수 있다. 물론 이는 컬렉션의 장점이다. 다양한 데이터 타입을 담으려고 사용하는 이유도 있지만, 내 의도와는 다르게 다른 데이터 타입이 들어갈 수도 있다. 그래서 이를 막기 위해 컬렉션을 제네릭 타입으로 생성하는 것이다. 또한 위에서 이름을 하나 얻기 위해 <code>getTitle()</code>을 하였는데, 이를 하기 위해 다운캐스팅을 해주었다. 한 줄이야 쉽지만... 매번 이런다면 정말 귀찮을 것이다. 따라서 제네릭은 매번 형변환하는 절차를 없애기 위해서도 사용한다.</p>
<p>제네릭은 다음과 같이 사용한다.</p>
<pre><code class="language-java">ArrayList&lt;Music&gt; list = new ArrayList&lt;Music&gt;();</code></pre>
<p>이렇게 되면, 해당 컬렉션은 Music 타입으로만 사용 가능하다. 또한 이렇게 하면 위에 서술했듯이 다운캐스팅을 할 필요가 없어진다.</p>
<pre><code class="language-java">System.out.println(list.get(0).getTitle());        //형변환을 안 해도 오류가 안 난다!</code></pre>
<h1 id="✔-마치며">✔ 마치며</h1>
<p>학부생 시절 자료구조를 낑낑대며 C언어, 특히 포인터를 사용하면서 구현했던 기억이 많이 난다. 배열이고, 링크드리스트고, 스택이고, 큐고... 잠시 악몽이 떠올랐지만, 친절하게도 자바는 이러한 기능들을 콜렉션으로 구현해 두었다! 그러나 이걸 막 가져다 쓰는 건 중요하지 않다. 물론 어느 상황에 어느 자료구조를 사용하고, 어느 메소드를 이용하는 건 중요할 것이다. 하지만 내가 중요하게 생각하는 건 이 자료구조들이 어떤 원리로 동작하는지이다. 어떠한 구조로 저장되고, 어떻게 구현이 되는지 공부하면 좋을 것 같다는 생각이 들었다. 아마 지금 당장은 아니지만 나중에 있을 취업준비, 특히 코딩 테스트에서 유용하게 쓰일 것이다. 
끝!🤓</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] JAVA API]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-JAVA-API</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-JAVA-API</guid>
            <pubDate>Wed, 21 Sep 2022 12:54:20 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<h1 id="📃-java-api">📃 JAVA API</h1>
<blockquote>
<p>Application Programming Interface</p>
</blockquote>
<p>API의 뜻이다. 애플리케이션을 프로그래밍 하기 위한 인터페이스, 우리는 여기서 인터페이스라는 단어에 집중해야 한다. 자바에서도 이러한 API를 제공하여 주는데, 자바 API는 자바 프로그래밍 시 자주 사용되는 클래스 및 인터페이스들의 모음이다. 우리가 흔히 사용하는 <code>System</code>, <code>String</code>, <code>Math</code>, <code>Scanner</code> 등은 모두 자바에서 기본으로 제공해주는 JAVA API이다. 이 API는 우리가 java.lang.* 을 import하면 사용할 수 있다.(생략도 가능하다!) 이것은 우리가 JDK(Java Development Kit)를 설치하였기 때문에 사용할 수 있다.</p>
<h2 id="🧮-math">🧮 Math</h2>
<p>JAVA API중 대표적인 클래스 중 하나로 Math클래스가 있다. 이 클래스를 사용하기 위해 평소처럼 객체를 생성해 보자.</p>
<pre><code class="language-java">Math m = new Math();        // 오류가 난다.</code></pre>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/133555b7-e9fe-4b67-a164-0981bd599486/image.png" alt="">
오류가 났다. 분명 평소 객체처럼 만들었는데 무언가 이상하다. 오류가 난 부분에 마우스를 가져가 보면 <code>The constructor Math() is not visible</code> 라고 한다. Math()클래스의 생성자가 보이지 않는다는데....</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/3440db7d-e1d2-4d6d-856b-dcc770cc44e3/image.png" alt="">
Math 클래스를 까보면 생성자가 <code>private</code>로 되어있는 걸 볼 수 있다. 친절하게 인스턴스화 할 수 없다고 주석도 달려있다.</p>
<p>Math 클래스는 메소드 또한 전부 <code>static</code>이기 때문에 객체 생성할 필요가 없다. 이를 싱글톤 패턴(프로그램 실행과 동시에 메모리 영역에 올려놓고 사용하는 것)이라고 한다.</p>
<p>또한 Math클래스 안에는 메소드들이 오버로딩 되어 있기 때문에 매개변수로 <code>int</code>나 <code>double</code>을 주어도 메소드가 제대로 호출되고 실행되는 걸 볼 수 있다. 아래 예시는 절대값 구하는 메소드<code>Math.abs()</code>인데, 이 또한 Math 클래스 안에 오버로딩 되어 정의되어 있다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/81f4041d-c0cd-4176-8630-8c2965744230/image.png" alt=""></p>
<h2 id="📝-string">📝 String</h2>
<p>우리가 자바 프로그래밍을 하면서 아마 가장 많이 사용하는 클래스는 String 클래스가 아닐까 생각한다. String 클래스는 <strong>불변 클래스</strong>이다. 또한 이 클래스로 만들어진 객체는 주소값을 저장하고 있는 참조 자료형이다.</p>
<p>String클래스로 객체를 생성하는 방법에는 두가지가 있다.</p>
<pre><code>1. new 키워드로 생성자 호출
2. 대입연산자를 통해서 직접 값을 넣어서 생성 </code></pre><h3 id="new-키워드로-생성자-호출">new 키워드로 생성자 호출</h3>
<p>우리가 평소 객체를 만드는 것처럼 <code>new</code>키워드로 생성자를 호출했다. 다행히 위의 Math 클래스처럼 오류가 뜨지 않았다. 출력도 잘 된다!</p>
<pre><code class="language-java">String str1 = new String(&quot;hello&quot;);
String str2 = new String(&quot;hello&quot;);
System.out.println(str1);
System.out.println(str2);</code></pre>
<p>그렇다면 해당 주소들을 비교해보자. 객체는 heap영역에 생성되고, 객체 변수 이름은 stack영역에 생성되어 주소를 참조하는 것이니, 16진수의 주소값을 10진수의 주소값으로 출력해주는 <code>hashCode()</code>메소드를 통하면 아마 주소값이 다르게 나올 것이다. </p>
<pre><code class="language-java">System.out.println(str1.hashCode());
System.out.println(str2.hashCode());</code></pre>
<p>그러나 결과는 달랐다.</p>
<pre><code>69609650
69609650</code></pre><p><img src="https://velog.velcdn.com/images/fogbow_juni/post/133555b7-e9fe-4b67-a164-0981bd599486/image.png" alt="">
어라... 분명 주소가 다르게 나와야 하는데... 그 이유는 String클래스의 <code>hashCode()</code>메소드가 오버라이딩 되어 사용되기 때문이다. String클래스의 <code>hashCode()</code>메소드는 주소값을 변환주는 것이 아닌 실제 담긴 문자열을 기반으로 해시코드값을 만들어서 반환해준다.</p>
<p>그럼 실제 주소값을 알려면 어떻게 해야할까? 그럴 떄 사용하는 것이 <code>System.identityHashCode()</code>메소드이다. 이 메소드를 통하여 주소값을 출력해 보았다. 이 메소드는 실제 주소값의 해시코드를 출력해주는 메소드이다.</p>
<pre><code class="language-java">System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));</code></pre>
<pre><code>705927765
366712642</code></pre><p>이렇게 되면 주소값이 다르게 출력되는 것을 알 수 있다. 그러나 이렇게 객체를 만들어 String클래스를 사용하는 건 금기시 된다. 그 이유는 위에 서술하였듯, String클래스는 불변 클래스인데, 불변 클래스는 말 그대로 변할 수 없는 클래스라는 뜻이다. </p>
<h3 id="대입연산자를-통해서-직접-값을-넣어-생성하는-방법">대입연산자를 통해서 직접 값을 넣어 생성하는 방법</h3>
<pre><code class="language-java">String str1 = &quot;hello&quot;;
String str2 = &quot;hello&quot;;</code></pre>
<p>위와 같이 대입 연산자를 통하여 직접 값을 넣어(리터럴 값) 생성하면 된다. 그러면 str1과 str2의 주소값을 비교해 보자.</p>
<pre><code class="language-java">System.out.println(str1.hashCode());
System.out.println(str2.hashCode());</code></pre>
<pre><code>99162322
99162322</code></pre><p>주소가 똑같이 나왔다. 하지만 이 방법은 <code>new</code>연산자에서 발생한 주소가 같았던 현상이라고 생각할 수 있어 <code>System.identityHashCode()</code>메소드로 비교해 보자.</p>
<pre><code class="language-java">System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));</code></pre>
<pre><code>705927765
705927765</code></pre><p>놀랍게도 주소가 같은 걸 확인할 수 있다! 그 이유는 String클래스를 대입연산자를 통해 직접 초기화 하여 생성하면, StringPool영역에 올라간다.</p>
<h3 id="string-pool">String Pool</h3>
<p>String Pool이란 Heap영역 안에 있는 메모리 영역인데, 위에서 말했듯 리터럴 값을 대입하면 String Pool 영역에 올라가게 된다. 그림으로 설명하면 다음과 같다.
<img src="https://velog.velcdn.com/images/fogbow_juni/post/62b5fd2a-2571-462b-a482-c23eec0c5889/image.jpg" alt="">
String Pool에 &quot;hello&quot;라는 문자열의 공간이 할당되고, stack영역의 두 변수 str1, str2가 모두 String Pool에 있는 문자열의 주소를 참조하게 된다. 따라서 주소가 동일하게 나온다.</p>
<p>그렇다면 문자열 비교로 동등비교연산자(<code>==</code>)를 통해 비교해 보면 어떻게 될까?</p>
<pre><code class="language-java">System.out.println(&quot;문자열이 같나용? : &quot; + str1 == str2);</code></pre>
<p>결과는 다음과 같다.</p>
<pre><code>false</code></pre><p>분명 주소값이 같아서 <code>true</code>가 반환되어야 할텐데... 이상한 문자열이 나왔다. 이는 연산자 우선순위 때문이다. 문자열에서 <code>+</code>연산자는 다형성이 적용되어 문자열 끝에 문자열을 붙이도록 되어있다. 그래서 &quot;문자열이 같나용 ? &quot; + str1이 먼저 실행되고, 이 합쳐진 문자열을 str2와 비교를 하기 때문에, false가 출력 되었다. 이를 방지하기 막기 위해 연산자의 우선순위를 정해주면 제대로 출력이 된다.</p>
<pre><code class="language-java">System.out.println(&quot;문자열이 같나용? : &quot; + (str1 == str2));</code></pre>
<pre><code>문자열이 같나용? : true</code></pre><p>제대로 출력됨을 확인할 수 있다!</p>
<h2 id="🎁-wrapper">🎁 Wrapper</h2>
<p>마지막으로 소개할 건 Wrapper 클래스이다. 이 클래스는 기본자료형을 객체로 포장해주는 클래이다. Wrapper클래스는 기본 자료형을 객체로 취급해야 하는 경우, 메소드를 매개변수로 사용하여 기본 자료형이 아닌 객체타입만 요구할 때, 다형성을 적용시키고 싶을 때 사용한다고 한다.</p>
<pre><code class="language-java">String str1 = &quot;10&quot;;
String str2 = &quot;20.5&quot;;

System.out.println(str1 + str2);</code></pre>
<pre><code>1020.5</code></pre><p>먼저 위와 같이 String으로 선언 된 문자열 객체에 숫자를 문자열로 대입하면, 당연히 문자열 끝에 다른 문자열이 붙어져서 출력된다. 그러나 이때 Wrapper클래스를 이용하면 숫자처럼 취급이 가능하다!</p>
<pre><code class="language-java">int i = Integer.parseInt(str1);
double d = Double.parseDouble(str2);

System.out.println(i + d);</code></pre>
<pre><code>20.5</code></pre><p>Wrapper 클래스의 parse메소드를 통하여 숫자로 파싱해주었고, 파싱한 값들을 더하니 제대로 숫자끼리 더해져 출력이 되었다.</p>
<h1 id="✔-마치며">✔ 마치며</h1>
<p>우리가 자바 프로그래밍을 하면서 정말 흔히 사용하는 클래스들을 한 번 정리해 보았다. 기존에 내가 알고 있던 내용들과 다른 내용들이 있었는데, 특히 String의 클래스에서 문자열 다음의 비교는 false가 나오던 게, 주소값이라고 생각하고 있었다. 이걸 다시 한 번 짚고 넘어갈 수 있어서 좋았고, String Pool이라는 메모리 영역에 생긴다는 사실을 알았다. 평소에는 생각 없이 사용했는데, 어떻게 돌아가는지 원리를 알 수 있어서 좋았다.
끝!😉</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 추상화, 인터페이스]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-%EC%B6%94%EC%83%81%ED%99%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-%EC%B6%94%EC%83%81%ED%99%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Tue, 20 Sep 2022 08:25:55 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<h1 id="추상화">추상화</h1>
<blockquote>
<p>추상화(abstraction)는 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것을 말한다.
추상적이다.</p>
</blockquote>
<p>위키백과의 추상화(컴퓨터)의 설명은 다음과 같다. 자료, 모듈, 시스템... 어려운 단어는 다 뒤로 미루고, 우리는 <strong>핵심적인 개념 또는 기능을 간추려 내는 것</strong>, 이라는 문장에 집중해야 한다.</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/217937d1-5fc4-46d4-bdbd-c6f6494dc8ce/image.png" alt="">
<del>추상적이다.</del></p>
<h1 id="추상메소드-추상클래스">추상메소드, 추상클래스</h1>
<p>자바에서 추상화는 추상메소드와, 추상클래스를 통해 구현한다. </p>
<h2 id="추상메소드-선언">추상메소드 선언</h2>
<blockquote>
<p>method body가 존재하지 않는 미완성 메소드</p>
</blockquote>
<p>추상 메소드는<code>abstract</code>키워드를 써서 정의해야 한다.</p>
<pre><code class="language-java">public abstract void abstractMethod();</code></pre>
<p><code>접근제한자 abstract 반환형 메소드이름();</code>
이때 유의할 점은 클래스 안에서 메소드를 정의하려 할 때 중괄호를 쓰고, 그 안에 메소드를 구현하지만, 추상메소드의 경우에는 메소드 이름을 적고 세미콜론으로 바로 마무리한다.
또한 일반클래스에서 추상메소드 정의하려면 다음과 같은 오류 발생한다.
<code>The abstract method abstractMethod in type Parent can only be defined by an abstract class</code></p>
<h2 id="추상클래스-선언">추상클래스 선언</h2>
<p>위의 오류를 해결하는 방법은 추상메소드를 선언한 클래스를 추상클래스로 만드는 듯이다. 하나라도 추상메소드를 포함하고 있는 클래스는 반드시 추상클래스가 되어야 한다. 추상 클래스를 만드는 방법은 클래스 이름 앞에 <code>abstract</code> 키워드를 붙이면 된다.</p>
<pre><code class="language-java">public abstract class Parent(){}</code></pre>
<p>또한 추상클래스를 상속받으면 자식클래스는 반드시 미완성 된 추상메소드를 구현해 주어야 하거나 자식클래스도 추상클래스로 만들어 주어야 한다. 오버라이딩의 강제성이 생긴다는 이야기이다. 이 경우에는 부모클래스와 마찬가지로 접근지정자 뒤에<code>abstract</code> 키워드를 사용하면 된다. </p>
<p>마지막으로 추상클래스로는 객체 생성이 불가능하다. 클래스가 미완성 되어서 메모리에 올릴 수 없기 때문이다. 그러나 참조형 변수로는 사용 가능하다.</p>
<pre><code class="language-java">Parent p = new Parent(); // 오류가 발생한다.
</code></pre>
<h2 id="추상화는-왜-그리고-언제-쓸까">추상화는 왜, 그리고 언제 쓸까?</h2>
<p>표준화 된 틀을 만들 수 있기 때문에 통일성이 생긴다. 또한 꼭 필요한 기능을 추상메소드로 선언하면, 반드시 자식클래스에서 구현해 주어야 하기 때문에 놓치지 않고 구현이 가능하다.
추상화는 기술적으로 개발자가 판단했을 때 이 클래스는 객체 생성이 불가능해야한다 라고 생각이 들면 추상클래스로 가능하게 하고, 개념적으로 개발자가 판단했을 때 해당 클래스가 아직 구체적으로 덜 구현된 상태인 것 같을 때 추상클래스나 추상메소드로 구현하여 나중에 구현하도록 한다.</p>
<h1 id="인터페이스">인터페이스</h1>
<blockquote>
<p>인터페이스(interface)는 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면이다.</p>
</blockquote>
<p>장치 사이에서 정보나 신호를 주고 받는다, 라는 게 아마 자바에서의 인터페이스가 아닐까 싶다. 정확히는 상수필드와 추상메소드만으로 이루어진 추상클레스의 변형체라고 한다.
이 말을 쉽게 풀어쓰면, 인터페이스의 필드는 묵시적으로 상수필드<code>public static final</code> 이고, 인터페이스의 메소드는 묵시적으로 <code>public abstract</code> 이다. 인터페이스에서는 무조건 상수필드와 추상메소드밖에 정의가 불가능하므로 접근제한자가 생략 가능하다.</p>
<p>인터페이스의 선언은 다음과 같다.
<code>접근제한자 interface 인터페이스이름{}</code></p>
<pre><code class="language-java">public interface InterfaceClass {

    int num = 10; 

    public void method1();
    public void method2();

}</code></pre>
<p>또한 인터페이스의 구현을 위해선 <code>implememts</code> 키워드를 사용하여 구현하면 된다.</p>
<pre><code class="language-java">public class Child implements {

    public void method1() {
        // method1() 구현
    }

    public void method2() {
        // method2() 구현
    }
}</code></pre>
<h2 id="인터페이스는-왜-쓸까">인터페이스는 왜 쓸까?</h2>
<p>결론적으로 다중상속을 위함이다. 자바에서는 다중상속을 제한하고 있는데, 인터페이스로 선언한 클래스를 다른 클래스에서 구현할 때, 여러개의 인터페이스를 구현할 수 있다. 그러나 여러개를 상속받으면 다이아몬드 상속 문제가 생길 수 있기 때문에 인터페이스를 사용하여 다중 상속을 구현한다.</p>
<h1 id="마치며">마치며...</h1>
<p>추상화, 인터페이스 모두 다형성의 한 종류라고 생각한다. 하나를 선언해두고, 필요에 따라서 개발자가 입맛에 따라 커스텀하여 사용하면, 이름은 같지만 기능이 전혀 다를 수 있다. 학교 다닐 때는 이런 추상화나 인터페이스를 사용해본 경험이 많지 않았지만, 실무에서 특히 인터페이스를 통해 구현을 자주 했던 기억이 남아 정리해 보았다.
끝!😉</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 상속]]></title>
            <link>https://velog.io/@fogbow_juni/JAVA-%EC%83%81%EC%86%8D%EA%B3%BC-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%98%95%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@fogbow_juni/JAVA-%EC%83%81%EC%86%8D%EA%B3%BC-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%98%95%EB%B3%80%ED%99%98</guid>
            <pubDate>Tue, 20 Sep 2022 02:09:35 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!</p>
</blockquote>
<h1 id="객체지향의-3요소">객체지향의 3요소</h1>
<p>흔히 말하는 객체지향의 3요소, JAVA의 3요소라고 해야 하나.... 학교다닐 때부터 귀에 딱지가 앉을만큼 들었고, 학원에서도 또 듣는다! 그만큼 아주 중요하다는 뜻이다. 객체지향의 3요소는 <strong>캡슐화(Encapsulation), 다형성(Polymorphism), 상속(Inheritance)</strong> 이 있다. 오늘 이 포스트에서는 그 중에서도 상속에 대해 다뤄보고자 한다.</p>
<h1 id="상속inheritance">상속(Inheritance)</h1>
<p>먼저 상속을 사전에 검색해 보면 다음과 같이 나온다.</p>
<blockquote>
<ol>
<li>뒤를 이음.</li>
<li>법률 일정한 친족 관계가 있는 사람 사이에서, 한 사람이 사망한 후에 다른 사람에게 재산에 관한 권리와 의무의 일체를 이어 주거나, 다른 사람이 사망한 사람으로부터 그 권리와 의무의 일체를 이어받는 일.</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/91988eeb-8080-4003-ba9f-0bf476340476/image.png" alt=""></p>
<p>부모의 것을 이어받거나, 뒤를 잇는 것이라고 생각하면 편하다. 자바에서도 사전적 의미와 크게 다르지 않다. 부모 클래스를 상속받아 자식 클래스를 생성하면, 부모의 클래스를 <strong>확장</strong>하여 생성할 수 있다. +α가 되는 샘이다.</p>
<h2 id="상속은-왜-쓰는데">상속은 왜 쓰는데?</h2>
<p>그럼 이 기능은 왜 쓰는 것일까? 위에 말했듯 부모 클래스를 확장하여 자식 클래스를 생성할 수 있다. 중복되는 부분을 제거할 수 있고, 클래스의 재사용을 유용하게 한다. 또한 코드를 공통적으로 관리할 수 있어서 유지보수에 기여한다.</p>
<h2 id="사용법">사용법</h2>
<p>위에서 강조했던 확장이라는 단어를 기억하면 좋을 것 같다. 상속은 부모 클래스를 확장하여 자식 클래스를 정의하는 것이기 때문에, <code>extends</code>키워드를 사용한다. 아래 예시에 먼저 부모 클래스인 Parent.java를 정의하였다.</p>
<pre><code class="language-java">// Parent.java
public class Parent {

    private int x;
    private int y;

    public Parent() {}

    public Parent(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public String toString() {
        return &quot;Parent [x=&quot; + x + &quot;, y=&quot; + y + &quot;]&quot;;
    }

}</code></pre>
<p>다음은 자식 클래스인 Child.java를 정의하였다.</p>
<pre><code class="language-java">//Child.java
public class Child extends Parent {

    private int z;

    public Child() {}

    public Child(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }

    public int getZ() {
        return z;
    }

    public void setZ(int z) {
        this.z = z;
    }

    @Override
    public String toString() {
        return &quot;Child [z=&quot; + z + &quot;]&quot;;
    }

}</code></pre>
<p>즉, 상속을 정의할 때에는 다음과 같이 작성한다.</p>
<pre><code>public class 자식클래스명 extends 부모클래스명</code></pre><h1 id="클래스-형변환">클래스 형변환</h1>
<p>흔히 객체는 형변환이 안 된다고 한다. 그러나 상속 구조의 경우에는 클래스간의 형변환이 가능하다. 클래스 형변환에는 두가지가 있는데, 바로 업 캐스팅(Up Casting)과 다운 캐스팅(Down Casting)이 있다. 또한 이런 클래스 형변환은 다형성을 구현하는 것이라고 생각할 수 있다.</p>
<h2 id="up-casting">Up Casting</h2>
<blockquote>
<p>상속 관계에 있는 부모, 자식 클래스 간에 부모타입의 참조형 변수가 모든 자식 타입의 객체 주소를 받을 수 있음</p>
</blockquote>
<p>즉, 자식 타입 객체를 부모 타입 객체로 사용하려고 하면 별다른 연산자 없이 가능하다. </p>
<pre><code class="language-java">Child c = new Child(1, 2, 3);
Parent p = c;        // 업캐스팅

System.out.println(p.getX());
System.out.println(p.getY());
//System.out.println(p.getZ());    // undefined 오류 발생!!</code></pre>
<p>위의 코드는 Child클래스의 객체를 생성할 때, 매개변수로 1, 2, 3과 같이 주었다. 그러면 Child.java에 선언 된 정수형 숫자 3개를 매개변수로 받는 생성자가 호출되어 c라는 객체가 생성되었다. 그 다음, Parent p라는 객체를 선언할 때, 이 객체에 바로 윗줄에서 생성한 객체 c를 대입하였다. (정확히는 같은 주소를 참조하도록 함!) 그러면 업캐스팅이 일어났고, Parent.java에 선언된 getter 메소드를 사용할 수 있게 되는 것이다. 그러나 Parent.java에는 getZ() 메소드가 선언되어 있지 않아 undefined 오류가 발생하였다. </p>
<h2 id="down-casting">Down Casting</h2>
<p>위의 업 캐스팅과 정반대가 되는 것이 바로 다운 캐스팅이다. 다운 캐스팅의 의미는 다음과 같다.</p>
<blockquote>
<p>자식 객체의 주소를 받은 부모 참조형 변수를 가지고 자식의 멤버를 참조해야 할 경우, 부모 클래스 타입의 참조형 변수를 자식 클래스 타입으로 형 변환하는 것</p>
</blockquote>
<p>이 때 주의할 점은 다운 캐스팅을 할 때에는 반드시 Casting 연산자가 필요하다는 것이다.</p>
<pre><code class="language-java">Parent p = new Child(1, 2, 3);        // 다운 캐스팅
// System.out.println((Child)p.getZ());
System.out.println(((Child)p).getZ());</code></pre>
<p>이 때 주의할 점은, <code>((Child)p).getZ()</code>와 같이 사용하였다는 점인데, 연산자 우선순위에 의해 캐스팅 연산자가 참조 연산자보다 우선순위가 낮아 오류 발생하기 때문이다.</p>
<h1 id="instanceof-연산자">instanceof 연산자</h1>
<p><code>instanceof</code> 연산자는 현재 참조형 변수가 어떤 클래스 형의 객체 주소를 참조하고 있는지 확인할 때 사용한다. 클래스 타입이 맞으면 true, 아니라면 false를 반환한다.</p>
<pre><code class="language-java">Parent p = new Child(1, 2, 3);
System.out.println(p instanceof Child);
System.out.println(p instanceof Parent);</code></pre>
<p>위 두 출력값은 모두 true가 나오는데, 그 이유는 다운 캐스팅이 일어나서 Child, Parent 클래스를 모두 참조하기 때문이다.</p>
<h1 id="마치며">마치며...</h1>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/dd23595f-1c8a-4dd7-aec5-7476a699b699/image.png" alt="">
자바에서 너무나도 중요한 개념이고, 절차지향 언어에서 찾아볼 수 없었던 개념이기도 하다. 그래서 예전에 대학교 전공시간에서 배울 때에도 잘 이해가 안 되었었는데, 여전히 어려운 개념이어서 정리하게 되었다. 
개인적으로 객체지향의 3요소는 각각 딱 잘라서 이건 상속! 이건 다형성! 이건 캡슐화! 이렇게 나눌 수 없다고 생각한다. 만약 상속을 한 부모 클래스의 필드의 접근지정자가 <code>private</code>가 아닌 <code>protected</code>로 선언되었다고 하면, 자식 클래스에서 getter / setter가 아닌 필드 그 자체로 접근할 수 있다. 그런데 이건 캡슐화 중 하나라고도 한다. 또한 위에서 다룬 클래스의 형변환도 다형성의 예시 중 하나라고 할 수 있다. 따라서 &quot;객체지향&quot;을 공부할 때에는 3요소를 딱 나누어 공부하는 것이 아닌, 각각의 연관관계를 생각하며 공부해야 한다고 생각한다.</p>
<p>끝!😎</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[9월 1 ~ 3주차 회고]]></title>
            <link>https://velog.io/@fogbow_juni/9%EC%9B%94-1-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@fogbow_juni/9%EC%9B%94-1-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 16 Sep 2022 13:01:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>처음 쓰는 회고록이라 많이 미숙합니다...
    사실 이렇게 쓰는 지 맞는 것도 모르겠어요!🥲 
일단은 기록을 하기로 했습니다.</p>
</blockquote>
<h3 id="😍-좋았던-것liked">😍 좋았던 것(Liked)</h3>
<p>국비 학원을 등록했습니다. 개발자로 일하다가 퇴사를 한 거라 스스로 공부할 수도 있었지만... 생활패턴은 이미 백수생활에 적응했고, 스스로 공부하면 집중도 못할 것 같아서 등록했습니다.
학원 분위기도 좋고 강사님도 엄청 열정적시고, 다른 수강생분들도 정말 열심히 공부하셔서 자극이 많이 되었습니다.</p>
<h3 id="📚-배운-것learned">📚 배운 것(Learned)</h3>
<p>얕은 복사 / 깊은 복사, 참조 자료형과 메모리영역. 이 내용들은 3주동안(추석이 껴있었지만...) 학원에 다니면서 계속 강조되어 들었던 것들입니다. 해당 내용에 관해서는 <a href="https://velog.io/@fogbow_juni/JAVA-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC">이곳에</a> 정리해 두었습니다!</p>
<h3 id="💦-부족했던-것lacked">💦 부족했던 것(Lacked)</h3>
<p>당연히 숙제들이 있었습니다! 그런데 이 숙제를 할 때에는 문제를 푸는 것에 중점을 두는 게 아니라 왜 그렇게 실행되는지에 대해 생각이 부족했던 것 같았습니다. 또한 주석을 이용하며 스스로 코드리뷰를 진행하는 것도 좋다고 생각됩니다. 다음부터는 숙제할 때, 코드를 작성하고 주석을 달며 왜 그렇게 돌아가는지 머릿속으로 컴파일 하는 시간이 필요하다 생각합니다.</p>
<h3 id="🙏-바라는-것longed-for">🙏 바라는 것(Longed for)</h3>
<p>꾸준히 공부했던 걸 복습하는 습관이 필요하다고 생각합니다. 원래 다이어리를 쓰기도 했지만... 지금 이렇게 회고를 하는 것도, 배웠던 내용을 다시 복습하는 것도 습관화 해야할 것 같습니다.</p>
<p><img src="https://velog.velcdn.com/images/fogbow_juni/post/38f67564-75cc-49e5-b2c0-af4b16d7e339/image.png" alt=""></p>
<p>어쨌든 지금은 공부를 하는 입장이고, 이왕 공부하는 거 제대로 공부해서 꼭 취뽀하는 게 목표입니다! 😎</p>
]]></description>
        </item>
    </channel>
</rss>