<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ks_velog</title>
        <link>https://velog.io/</link>
        <description>안녕하세요, 박경서입니다.</description>
        <lastBuildDate>Tue, 13 Aug 2024 15:34:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ks_velog</title>
            <url>https://velog.velcdn.com/images/ch980113_/profile/ab5fa939-5d31-4779-b45c-01bf443a059a/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ks_velog. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ch980113_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[기술 면접 - java 1편]]></title>
            <link>https://velog.io/@ch980113_/%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-java-1%ED%8E%B8</link>
            <guid>https://velog.io/@ch980113_/%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-java-1%ED%8E%B8</guid>
            <pubDate>Tue, 13 Aug 2024 15:34:04 GMT</pubDate>
            <description><![CDATA[<h3 id="1-java-의-장단점에-대해-설명해주세요">1. Java 의 장단점에 대해 설명해주세요.</h3>
<ul>
<li>장점<ul>
<li>JVM에서 동작하기 때문에 운영체제에 독립적</li>
<li>객체지향 언어이기 때문에 이해하기 쉽다.</li>
<li>오픈소스로 사용할 수 있고 커뮤니티가 잘 발달되어 있다.</li>
<li>멀티쓰레드를 쉽게 구현할 수 있다.</li>
<li>가비지 컬렉터에 의해 메모리 관리를 자동으로 해준다.</li>
</ul>
</li>
<li>단점<ul>
<li>컴파일되고 번역하는 과정을 거치기 때문에 비교적 느리다.</li>
<li>가비지 컬렉터로 인해 메모리 공간 필요</li>
</ul>
</li>
</ul>
<hr>
<h3 id="2-java-의-데이터-타입에-대해-설명해주세요">2. Java 의 데이터 타입에 대해 설명해주세요.</h3>
<p>자바의 데이터 타입은 기본 데이터 타입과 참조 타입으로 나뉩니다. 기본 데이터 타입으로는 byte, short, int, long, float, double, boolean, char 가 있으며 Stack 영역에
저장됩니다. 참조 타입은 기본형은 제외한 모든 타입이며, Heap 영역에 저장됩니다.</p>
<ul>
<li>기본 데이터 타입(Primitive Data Type)<ul>
<li>정수형 : byte, short, int, long</li>
<li>실수형 : float, double</li>
<li>논리형 : boolean(ture/false)</li>
<li>문자형 : char</li>
<li>기본 타입의 크기가 작고 고정적이기 때문에 메모리의 Stack 영역에 저장된다.</li>
</ul>
</li>
<li>참조 타입(Reference Data Type)<ul>
<li>참조 타입 종류: class, array, interface, Enumeration</li>
<li>기본형을 제외하고는 모두 참조형</li>
<li>new 키워드를 이용하여 객체를 생성하여 데이터가 생성된 주소를 참조하는 타입이다.</li>
<li>String과 배열은 참조 타입과 달리 new 없이 생성이 가능하지만 기본 타입이 아닌 참조 타입이다.</li>
<li>참조 타입의 데이터의 크기가 가변적, 동적이기 때문에 동적으로 관리되는 Heap 영역에 저장된다.</li>
<li>더 이상 참조하는 변수가 없을 때 가비지 컬렉션에 의해 파괴된다.</li>
<li>참조 타입은 값이 저장된 곳의 주소를 저장하는 공간으로 객체의 주소를 저장한다. (Call-By-Value)</li>
</ul>
</li>
</ul>
<h3 id="3-wrapper-클래스와-boxing-unboxing-에-대해서-설명해주세요">3. Wrapper 클래스와 Boxing, Unboxing 에 대해서 설명해주세요.</h3>
<p>Wrapper 클래스는 프로그램에 따라 기본 데이터 타입을 객체로 취급해야 하는 경우, 기본 타입들의 데이터를 객체로 포장한 클래스입니다. 기본 타입의 데이터를 Wrapper 클래스의 값으로 변환하면 Boxing,
반대의 경우를 Unboxing이라고 합니다.</p>
<ul>
<li>Wrapper Class<ul>
<li>프로그램에 따라 기본 데이터 타입을 객체로 취급해야 하는 경우, 기본 타입들의 데이터를 객체로 포장한 클래스</li>
<li>java.lang 패키지에 존재</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>기본 타입</th>
<th>래퍼 클래스</th>
</tr>
</thead>
<tbody><tr>
<td><code>byte</code></td>
<td><code>Byte</code></td>
</tr>
<tr>
<td><code>short</code></td>
<td><code>Short</code></td>
</tr>
<tr>
<td><code>int</code></td>
<td><code>Integer</code></td>
</tr>
<tr>
<td><code>long</code></td>
<td><code>Long</code></td>
</tr>
<tr>
<td><code>float</code></td>
<td><code>Float</code></td>
</tr>
<tr>
<td><code>double</code></td>
<td><code>Double</code></td>
</tr>
<tr>
<td><code>char</code></td>
<td><code>Character</code></td>
</tr>
<tr>
<td><code>boolean</code></td>
<td><code>Boolean</code></td>
</tr>
</tbody></table>
<ul>
<li>Boxing<ul>
<li>기본 타입의 데이터를 Wapper 클래스의 인스턴스로 변환하는 과정</li>
</ul>
</li>
<li>Unboxing<ul>
<li>Wrapper 클래스의 인스턴스에 저장된 값을 기본 타입의 데이터로 꺼내는 과정</li>
</ul>
</li>
</ul>
<hr>
<h3 id="4-java는-call-by-value인가요-call-by-reference인가요">4. Java는 Call by Value인가요 Call by Reference인가요?</h3>
<p>자바는 Call by Value 를 따릅니다. 기본 자료형의 경우 해당 값이 복사되어 전달되고, 참조 자료형의 경우 힙 메모리의 참조값이 복사되어 전달됩니다.</p>
<ul>
<li><p>자바에서 파라미터는 항상 <code>값</code>으로 전달됩니다. (파라미터의 복사본이 메서드에 전달)</p>
</li>
<li><p>기본 자료형의 경우 값의 복사본이 전달됩니다.</p>
</li>
<li><p>참조 자료형의 경우 힙 메모리의 주소값이 복사되어 전달됩니다.</p>
<ul>
<li><p>아래 예시의 경우 User 의 메모리가 복사되어 전달된다. b 의 경우 새로운 주소를 할당하는데 메서드가 종료되면 원본 b 에는 반영되지 않는다.</p>
<pre><code class="language-java">class User {
public int age;

public User(int age) {
    this.age = age;
}
}
</code></pre>
</li>
</ul>
<p>public class ReferenceTypeTest {</p>
<pre><code>void test() {
    User a = new User(10);
    User b = new User(20);

    System.out.println(a); // age: 10
    System.out.println(b); // age: 20
    modify(a, b);

    System.out.println(a); // age: 11 
    System.out.println(b); // age: 20
}

private void modify(User a, User b) {
    a.age++;

    b = new User(30);
    b.age++;
}</code></pre><p>}</p>
<pre><code></code></pre></li>
</ul>
<hr>
<h3 id="5-java-의-접근제어자는-어떤-것이-있나요">5. Java 의 접근제어자는 어떤 것이 있나요?</h3>
<p>자바의 접근 제어자로는 제약 없이 접근 가능한 public, 동일 패키지 또는 상속 관계에서 접근 가능한 protected, 동일 패키지에서만 접근 가능한 package-private, 선언한 객체에서만 사용 가능한
private 이 있습니다.</p>
<table>
<thead>
<tr>
<th>접근 제어자</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>public</code></td>
<td><code>해당 객체를 사용하는 프로그램 어디에서나 접근 가능</code></td>
</tr>
<tr>
<td><code>protect</code></td>
<td><code>동일 패키지 또는 상속 관계의 객체에서 접근 가능</code></td>
</tr>
<tr>
<td><code>package-private</code></td>
<td><code>동일 패키지에서 접근 가능</code></td>
</tr>
<tr>
<td><code>private</code></td>
<td><code>해당 객체에서만 사용 가능</code></td>
</tr>
</tbody></table>
<hr>
<h3 id="6-클래스-객체-인스턴스를-비교해주세요">6. 클래스, 객체, 인스턴스를 비교해주세요.</h3>
<p>클래스는 객체를 만들어 내기 위한 틀로서 객체가 가질 수 있는 속성과 메서드를 정의하며, 이를 실체화한 것이 객체입니다. 인스턴스는 객체의 구체적인 사례입니다.</p>
<ul>
<li>클래스(Class)<ul>
<li>객체를 만들어 내기 위한 설계도 혹은 틀</li>
<li>연관되어 있는 변수와 메서드의 집합</li>
</ul>
</li>
<li>객체(Object)<ul>
<li>소프트웨어 세계에 구현할 대상</li>
<li>클래스에 선언된 모양 그대로 생성된 실체</li>
<li>&#39;클래스의 인스턴스(instance)&#39; 라고도 부른다.</li>
</ul>
</li>
<li>인스턴스(Instance)<ul>
<li>설계도를 바탕으로 소프트웨어 세계에 구현된 구체적인 실체<ul>
<li>즉, 객체를 소프트웨어에 실체화 하면 그것을 &#39;인스턴스&#39;라고 부른다.</li>
<li>실체화된 인스턴스는 메모리에 할당된다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="7-static-키워드에-대해-설명해주세요">7. static 키워드에 대해 설명해주세요.</h3>
<p>클래스 멤버를 정의할 때 사용되며, 객체가 생성되기 전에 초기화 되며, 모든 인스턴스에서 공유되어 사용됩니다.</p>
<ul>
<li>클래스 멤버를 정의할 때 사용</li>
<li>객체가 생성되기 전에 클래스의 로딩 과정에서 메모리에 할당되므로, 객체 생성 없이 클래스 이름만으로 접근할 수 있다.</li>
<li>static 키워드를 적절히 사용하면, 메모리를 효율적으로 사용하거나 객체 생성 없이도 편리하게 접근할 수 있는 장점이 있다.</li>
</ul>
<h3 id="8-클래스-멤버와-인스턴스-멤버">8. 클래스 멤버와 인스턴스 멤버</h3>
<ul>
<li>클래스 멤버: 클래스에 존재하는 변수와 메서드.</li>
<li>인스턴스 멤버: 객체(인스턴스)에 존재하는 변수와 메서드. static 키워드를 사용하지 않고 정의한다.</li>
<li>클래스 멤버에서는 인스턴스 멤버가 접근 가능하지만, 인스턴스 멤버에서는 클래스 멤버로 접근이 불가능하다.</li>
</ul>
<h3 id="9-static-멤버와-non-static-멤버는-무슨-차이가-있나요">9. static 멤버와 non-static 멤버는 무슨 차이가 있나요?</h3>
<ul>
<li>static 멤버는 클래스가 로딩될 때 메모리에 할당되며, 모든 인스턴스에서 공유됩니다. 반면에 non-static 멤버는 각 인스턴스가 생성될 때 메모리에 할당되고, 인스턴스마다 고유한 값을 가집니다.</li>
</ul>
<ul>
<li>다음과 3가지의 차이점이 존재한다.</li>
</ul>
<table>
<thead>
<tr>
<th>항목</th>
<th>메모리 할당 시기</th>
<th>접근 방법</th>
<th>공유 여부</th>
</tr>
</thead>
<tbody><tr>
<td><code>static</code></td>
<td>클래스가 로딩될 때</td>
<td>인스턴스를 생성하지 않고 클래스 이름으로 접근</td>
<td>모든 인스턴스가 동일한 값 공유</td>
</tr>
<tr>
<td><code>non-static</code></td>
<td>인스턴스가 생성될 때</td>
<td>인스턴스를 생성한 후 접근</td>
<td>인스턴스마다 고유한 값 존재</td>
</tr>
</tbody></table>
<h3 id="10-main-메서드는-왜-static-메서드인가요">10. main 메서드는 왜 static 메서드인가요?</h3>
<ul>
<li>main 메서드는 프로그램이 실행될 때 가장 먼저 호출됩니다. 인스턴스가 생성되기 전에 호출되어야 하기 때문에 static으로 정의되어야 합니다.</li>
</ul>
<ul>
<li>main 메서드는 프로그램이 시작할 때 JVM에 의해 호출됩니다. 만약 non-static 메서드라면, main 메서드를 호출하기위해 클래스를 인스턴스화 시켜야 하기 때문에 JVM 에서 직접 호출이 불가능합니다.
따라서 main 메서드는 static 메서드여야 합니다.</li>
</ul>
<h3 id="11-자바-프로그램-실행-시-static-이-붙은-변수는-어떻게-처리되나요">11. 자바 프로그램 실행 시 static 이 붙은 변수는 어떻게 처리되나요?</h3>
<ul>
<li>static 이 붙은 변수는 해당 클래스가 로딩될 때 Method Area에 한번 초기화되고 값 변경이 일어나지 않습니다. 이후에 인스턴스를 초기화하지 않고 사용할 수 있습니다.</li>
</ul>
<ul>
<li>자바 프로그램이 실행되고 JVM이 프로그램에서 사용되는 클래스를 로드하고, 해당 static 변수를 초기화합니다.</li>
<li>JVM은 Method Area 에 static 변수에 메모리를 할당합니다.</li>
</ul>
<hr>
<h3 id="12-오버로딩과-오버라이딩을-비교해주세요">12. 오버로딩과 오버라이딩을 비교해주세요.</h3>
<ul>
<li>오버로딩은 메서드의 이름은 같고 파라미터를 다르게 한 것이고, 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것을 의미합니다.</li>
</ul>
<ul>
<li>오버로딩<ul>
<li>이름은 같고 매개변수의 수, 타입 또는 순서가 다른 여러 메서드 정의</li>
<li>반환하는 타입은 달라도 된다.</li>
</ul>
</li>
<li>오버라이딩<ul>
<li>메서드 이름과 매개변수가 동일한 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것</li>
<li>오버라이딩된 메서드가 자식클래스의 인스턴스에서 호출되면 부모 클래스의 메서드는 무시된다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="13-인터페이스와-추상클래스를-비교해주세요">13. 인터페이스와 추상클래스를 비교해주세요.</h3>
<ul>
<li>둘의 차이는 목적에 있어 차이가 있습니다. 추상클래스는 abstract 키워드로 선언된 클래스로서 기능을 이용하고 확장하도록 의도합니다. 반면, 인터페이스는 추상메서드로만 이루어진 것으로 기능의 구현을 강제하도록 의도합니다. 이때문에 추상클래스는 공통 기능을 가지는 기반 클래스로 적합하며, 인터페이스는 다형성이 필요한 경우에 적합합니다. </li>
</ul>
<ul>
<li>추상클래스<ul>
<li>abstract 키워드로 선언된 클래스</li>
<li>자식 클래스가 추상클래스의 기능을 이용하고 확장하는데 초점을 둔다.</li>
<li>클래스이기 때문에 다중상속은 지원하지 않는다.</li>
<li>기능의 확장에 초점을 두기 때문에 공통 기능을 가지는 베이스 클래스에 적합하다.</li>
</ul>
</li>
<li>인터페이스<ul>
<li>추상 메서드와 상수로만 이루어진 것</li>
<li>인터페이스는 선언된 기능을 구현하도록 강제한다.</li>
<li>기능의 구현을 강제하기 때문에 같은 기능을 다르게 구현하는 다형성이 필요한 경우에 적합하다.</li>
<li>다중 상속이 가능하다.<ul>
<li>다중 상속을 할 때 메서드 충돌은 어떻게 해결할까?<ul>
<li>다중 상속을 하더라도 인터페이스에는 구현부가 없고, 구현 부분이 하나이기 때문에 컴파일 에러는 나타나지 않는다.</li>
<li>다만, default 메서드를 통해 인터페이스에서 구현하는 경우 컴파일러는 오류를 내보낸다. (모두 구현된 경우)</li>
<li>이 경우 2가지 해결 방법이 존재한다.<ol>
<li>인터페이스에서 구현하지 않고 상속한 클래스에서 구현한다.</li>
<li>하나의 인터페이스로 구현을 위임한다.</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>추상 메서드<ul>
<li>abstract 키워드와 함께 구현부는 작성되지 않고 선언부만 작성된 메서드</li>
<li>final 키워드가 붙은 메서드는 추상 메서드로 만들 수 없다.</li>
<li>물론 static 메서드도 추상 메서드로 만들 수 없다.</li>
</ul>
</li>
</ul>
<h3 id="14-클래스는-왜-다중-상속을-허용하지-않을까요">14. 클래스는 왜 다중 상속을 허용하지 않을까요?</h3>
<ul>
<li><p>다중 상속을 허용하지 않는 이유는 모호성때문입니다. 다중 상속하는 클래스에서 이름이 같은 메서드가 있다면 어떤 메서드를 컴파일러가 호출할지 모호하기 때문에 자바에서는 다중 상속을 지원하지 않습니다.</p>
</li>
<li><p>자바에서는 모호성때문에 다중 상속을 지원하지 않는다.</p>
</li>
<li><p>부모 클래스들에서 같은 이름을 가진 메서드나 변수가 있다면, 자식 클래스에서 어떤 메서드를 컴파일러가 호출할지 모호하기 때문이다.  </p>
</li>
</ul>
<hr>
<h3 id="15-java의-error-exception-구조에-대해-설명해주세요">15. Java의 Error, Exception 구조에 대해 설명해주세요.</h3>
<ul>
<li>자바의 Error 와 Exception 은 모두 Throwable 객체를 상속받습니다. Error 는 주로 시스템 레벨의 심각한 에러로서 개발자가 처리할 수 없는 에러입니다. 반면, Exception 은 크게 RuntimeException 과 다른 Exception 으로 구분되며, 주로 개발자가 작성한 프로그램에서 발생하는 에러입니다. </li>
<li>Error<ul>
<li>시스템에 발생하는 심각한 예외 상황을 나타냄</li>
<li>OutOfMemoryError, StackOverflowError 등</li>
<li>시스템 자체에서 발생하여 개발자가 대응할 수 없다. -&gt; 따로 처리하지 않아도 된다.</li>
</ul>
</li>
<li>Exception <ul>
<li>개발자가 작성한 프로그램에서 발생하는 예외 상황을 나타냄</li>
<li>RuntimeException, IOException 등</li>
<li>일반적으로 RuntimeException 과 나머지 Exception 으로 구분되어 구조화한다.</li>
<li>try-catch-finally 구문을 사용하여 예외 처리를 해야한다.</li>
</ul>
</li>
</ul>
<h3 id="16-checkedexception-과-uncheckedexception-은-무슨-차이인가요">16. CheckedException 과 UncheckedException 은 무슨 차이인가요?</h3>
<ul>
<li>UncheckedException 와 CheckedException 의 차이는 예외 처리의 강제성에 있습니다. CheckedException 은 컴파일 과정에서 발생하여 예외를 강제하는 반면, UncheckedException 은 런타입 과정에서 발생하는 예외이기 때문에 컴파일 과정에서 예외 처리를 강제하지 않습니다. </li>
</ul>
<ul>
<li>UncheckedException<ul>
<li>RuntimeException 과 이를 상속한 예외</li>
<li>런타임 과정에서 발생하는 예외</li>
<li>예외 처리를 강제받지 않음<ul>
<li>다만 예외가 런타임 과정에서 발생하기 때문에 예상하지 못한 에러가 발생할 수 있다.</li>
<li>따라서 예외 상황이 발생할 것을 대비하여 예외 처리를 하는 것이 좋다.</li>
</ul>
</li>
</ul>
</li>
<li>CheckedException<ul>
<li>RuntimeException 을 제외한 Exception 예외</li>
<li>컴파일 과정에서 발생하는 예외</li>
<li>컴파일러에 의해 예외 처리가 강제됨</li>
</ul>
</li>
</ul>
<h3 id="17-예외처리의-세-가지-방법을-설명해주세요">17. 예외처리의 세 가지 방법을 설명해주세요.</h3>
<ul>
<li>예외 처리 방법으로 예외 상황을 정상 상태로 돌려놓는 예외 복구, 호출한 메서드로 예외 처리를 넘기는 예외 회피, 다른 예외로 전환하는 예외 전환이 있습니다.</li>
<li>예외 복구<ul>
<li>예외가 발생하더라도 애플리케이션이 정상적인 흐름으로 동작하도록 진행</li>
</ul>
</li>
<li>예외 회피<ul>
<li>예외가 발생하면 throws 를 통해 호출한 메서드로 예외 처리를 위임하는 것</li>
</ul>
</li>
<li>예외 전환<ul>
<li>다른 예외로 전환.</li>
<li>호출한 메서드에서 예외를 처리할 때 더 명확하게 예외 상황을 인지할 수 있도록 돕는다.</li>
<li>throw 를 통해 실행</li>
</ul>
</li>
</ul>
<hr>
<h3 id="18-final-키워드는-왜-사용할까요-어떤-이점이-있을까요">18. final 키워드는 왜 사용할까요? 어떤 이점이 있을까요?</h3>
<ul>
<li>final 키워드는 변수와 메서드, 클래스에 붙어 변하지 않도록 하는 역할을 수행합니다. 의도치 않은 변경을 줄여 코드 안정성을 보장하고 final 변수는 상수이기 때문에 컴파일 과정에서 성능 향상을 가져올 수 있습니다. 또한, 코드 가독성을 높일 수 있습니다.</li>
<li>코드 안정성<ul>
<li>의도치 않은 코드 변경을 줄일 수 있기 때문에 코드 안정성이 높아진다.</li>
</ul>
</li>
<li>성능 향상<ul>
<li>final 변수는 상수로 취급하여 컴파일 과정에서 변수를 계산하는 과정이 준다. 이만큼 성능 향상을 불러올 수 있다.</li>
</ul>
</li>
<li>코드 가독성<ul>
<li>변수, 메서드, 클래스에 final 키워드를 붙이면 변경되지 않는다는 의미를 명확하게 전달할 수 있다.</li>
</ul>
</li>
</ul>
<h3 id="19-final-finally-finalize-에-대해-설명해주세요">19. final, finally, finalize 에 대해 설명해주세요</h3>
<ul>
<li>final 키워드는 변수, 메서드, 클래스를 변경 불가능하도록 만드는 것이고, finally 는 try-catch 구문 마지막에 항상 실행될 코드 블록을 정의하기 위해 사용됩니다. 마지막으로 finalize 는 GC 가 더이상의 참조가 존재하지 않는 객체를 메모리에서 삭제할 때 사용되는 메서드입니다.</li>
<li>final<ul>
<li>기본 데이터 타입에 적용: 변수에 저장된 값의 변경이 불가능</li>
<li>참조 데이터 타입에 적용: 참조 변수의 힙 메모리를 재할당 불가능</li>
<li>메서드에 적용: 오버라이드 불가능</li>
<li>클래스에 적용: 상속 불가능</li>
</ul>
</li>
<li>finally<ul>
<li>try-catch 구문이 종료될 때 항상 실행될 코드 블록을 정의하기 위해 사용</li>
<li>JVM 이 종료되거나 해당 프로세스가 종료되지 않는 이상 무조건 실행된다.<ul>
<li>return 문이 try 에 있어도 finally 코드 블록이 실행됨</li>
<li>try-with-resources 구문을 사용할 수 있으면 try-catch-finally 대신 사용할 것<ul>
<li>예외가 중복될 경우 디버깅이 힘듦</li>
<li>가독성이 나빠짐</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>finalize<ul>
<li>Garbage Collector 가 더이상 참조가 존재하지 않는 객체를 메모리에서 삭제할 때 호출하는 메서드</li>
<li>Object 클래스의 finalize 메서드를 오버라이딩하여 커스텀할 수 있다.</li>
</ul>
</li>
</ul>
<h3 id="20-final-키워드는-컴파일-과정에서-다르게-실행될까요">20. final 키워드는 컴파일 과정에서 다르게 실행될까요?</h3>
<ul>
<li>final 키워드가 붙은 변수는 상수와 같이 취급이 됩니다. 메서드는 오버라이딩이 안되기 때문에 오버라이딩한 메서드를 찾는 과정이 생략됩니다. 클래스는 상속이 불가능하기 때문에 자식 클래스를 찾는 과정이 생략됩니다.</li>
</ul>
<hr>
<h3 id="21-제네릭에-대해-설명해주세요">21. 제네릭에 대해 설명해주세요.</h3>
<ul>
<li>제네릭은 클래스 내부에서 사용하는 타입을 외부에서 지정할 수 있는 방법입니다. 장점으로는 컴파일 시점에 타입 체크를 진행해 타입 안정성을 보장하고 코드 중복을 줄여줍니다. 반면 단점으로는  문법이 생소하여 가독성이 떨어지고 공변성 때문에 배열과의 호환성이 좋지 않습니다.</li>
</ul>
<ul>
<li>클래스 내부에서 사용하는 타입을 외부에서 지정하는 방법</li>
<li>장점<ul>
<li>컴파일 시점에 타입 체크를 통해 타입 안정성을 보장</li>
<li>코드 중복을 줄여줌</li>
</ul>
</li>
<li>단점<ul>
<li>문법이 생소하여 가독성이 떨어짐.</li>
<li>배열의 공변성으로 인해 배열과의 호환성이 떨어짐</li>
</ul>
</li>
</ul>
<hr>
<h3 id="22-리플렉션이-무엇이고-언제-활용-가능한지-설명해주세요">22. 리플렉션이 무엇이고, 언제 활용 가능한지 설명해주세요.</h3>
<ul>
<li><p>리플렉션은 동적으로 클래스의 정보를 얻어 사용할 수 있는 기법입니다. 주로 런타임에 클래스에 접근하여 정보를 얻어야 할 때 사용됩니다. 예시로는 Spring 의 애노테이션, Jackson 등이 있습니다.</p>
</li>
<li><p>런타임에 클래스의 이름, 메서드, 필드 등을 동적으로 가져오는 API</p>
</li>
<li><p>클래스 정보가 런타임 시점에 필요할 때 이용</p>
</li>
<li><p>Spring 의 애노테이션, IDE 의 자동완성, Jackson 등이 있다.</p>
</li>
</ul>
<h3 id="23-리플렉션의-장단점에-대해-설명해주세요">23. 리플렉션의 장단점에 대해 설명해주세요.</h3>
<ul>
<li><p>리플렉션의 장점으로는 클래스의 정보를 동적으로 로딩할 수 있다는 장점이 있습니다. 또한 객체를 런타임에 생성하여 유연성을 높일 수 있습니다. 반면 단점으로는 private 메서드에 접근할 수 있는 보안문제와 타입이 정해지지 않는 클래스의 정보를 동적으로 가져오기 때문에 성능 저하가 있습니다.</p>
</li>
<li><p>장점</p>
<ul>
<li>클래스의 정보를 동적으로 로딩</li>
<li>객체를 런타임에 생성</li>
</ul>
</li>
<li><p>단점</p>
<ul>
<li>타입이 정해지지 않는 클래스의 정보를 가져오기 때문에 컴파일러의 최적화를 받지 못한다. 이 때문에 성능 저하가 발생한다.</li>
<li>동적으로 클래스 정보를 가져오기 때문에 가독성이 떨어진다.</li>
<li>private 메서드에 접근할 수 있기 때문에 보안문제가 생긴다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="24-자바의-직렬화와-역직렬화에-대해-설명해주세요">24. 자바의 직렬화와 역직렬화에 대해 설명해주세요.</h3>
<p>자바에서 직렬화는 시스템 내부에서 사용되는 객체 또는 데이터를 외부 시스템에서도 사용할 수 있도록 바이트 형태로 변환하는 기술입니다. 반면, 역직렬화는 바이트로 변환된 데이터를 객체로 변환하는 기술입니다.  </p>
<ul>
<li>직렬화<ul>
<li>시스템 내부에서 사용되는 객체 또는 데이터를 외부 시스템에서도 사용할 수 있도록 바이트 형태로 변환하는 기술</li>
<li>JVM 의 메모리(힙 또는 스택)에 있는 객체 데이터를 변환</li>
<li>조건<ul>
<li>기본 타입 (primitive)</li>
<li><code>java.util.Serializable</code> 인터페이스를 상속받은 객체</li>
</ul>
</li>
<li>방법<ul>
<li><code>java.io.ObjectOutputStream</code> 객체 이용</li>
</ul>
</li>
</ul>
</li>
<li>역직렬화<ul>
<li>바이트로 변환된 데이터를 객체로 변환하는 기술</li>
<li>JVM 의 메모리에 저장</li>
<li>조건<ul>
<li>직렬화 대상이 된 객체의 클래스가 클래스 패스에 존재해야 하며, <code>import</code> 되어 있어야 한다.<ul>
<li>직렬화와 역직렬화를 진행하는 과정이 다른 시스템에서 일어날 수 있다.</li>
</ul>
</li>
<li>자바 직렬화 대상 객체는 동일한 <code>serialVersionUID</code> 를 가지고 있어야 한다.</li>
</ul>
</li>
<li>방법<ul>
<li><code>java.io.ObjectInputStream</code> 객체 이용</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="25-자바의-직렬화는-언제-어디서-사용되나요">25. 자바의 직렬화는 언제, 어디서 사용되나요?</h3>
<ul>
<li><p>JVM 의 메모리에서만 저장된 객체 데이터를 영속화할 때 사용합니다. 장점으로는 시스템이 종료되더라도 사라지지 않는 점이 있습니다. 예시로는 파일로 저장하는 서블릿 세션, 캐시 등이 있습니다.</p>
</li>
<li><p>언제?</p>
<ul>
<li>JVM 메모리에서만 있는 객체 데이터를 영속화할 때 사용</li>
</ul>
</li>
<li><p>장점</p>
<ul>
<li>시스템이 종료되더라도 없어지지 않음</li>
</ul>
</li>
<li><p>예시</p>
<ol>
<li>서블릿 세션<ul>
<li>서블릿 기반의 WAS 들은 대부분 세션의 자바 직렬화를 지원하고 있다.</li>
<li>세션을 통해 파일로 저장하거나 세션 클러스터링, DB 를 저장하는 등에서 세션 자체가 직렬화가 되어 저장되고 전달됨</li>
</ul>
</li>
<li>캐시<ul>
<li>퍼포먼스를 위한 캐시 라이브러리(Ehcache, Redis, Memcached 등)에서 주로 이용</li>
</ul>
</li>
<li>자바 RMI(Remote Method Invocation)<ul>
<li>자바 RMI: 원격 시스템 간의 메시지 교환을 위해서 사용하는 기술<ul>
<li>소켓 통신을 하지 않고 추상화하여 메서드를 통해 호출</li>
</ul>
</li>
<li>원격에 있는 메서드를 호출할 때 전달하는 메시지(주로 객체)를 직렬화</li>
</ul>
</li>
</ol>
</li>
</ul>
<hr>
<h3 id="26-자바의-synchronized-키워드를-설명해주세요">26. 자바의 Synchronized 키워드를 설명해주세요.</h3>
<ul>
<li><p>Synchronized 키워드를 통하여 메서드나 코드 블록에 Lock 을 걸어 스레드 간 상호 배제를 할 수 있습니다. 메서드에 작성할 경우 해당 클래스 인스턴스에 Lock 을 걸고, 코드 블록에 작성할 경우 블록으로 작성된 부분만 Lock 이 걸리게 됩니다.</p>
</li>
<li><p>Lock 을 걸어 스레드 간의 상호배제를 할 수 있는 키워드.</p>
</li>
<li><p>적용 위치: 메서드, 코드 블록</p>
</li>
<li><p>메서드에 적용</p>
<ul>
<li>클래스 인스턴스에 Lock</li>
</ul>
</li>
<li><p>static 메서드에 적용</p>
<ul>
<li>클래스에 Lock</li>
<li>static synchronized 메서드와 synchronized 메서드의 Lock 은 공유하지 않는다.</li>
</ul>
</li>
<li><p>메서드의 코드 블록에 적용</p>
<ul>
<li><p>인스턴스의 블록 단위에 Lock </p>
</li>
<li><p>동기화 전후에는 Lock 이 적용되지 않기 때문에, 효율적 사용 가능</p>
</li>
<li><p>block 에 <code>this</code> 를 명시할 경우 메서드에 붙은 것과 같은 효과</p>
<pre><code class="language-java">public class Test {
public void run() {
    // ...

    synchronized (this) {
        // ...
    }

    // ...
}
}</code></pre>
</li>
</ul>
</li>
<li><p>block 에는 객체 인스턴스를 지정하거나 클래스를 지정할 수 있다.</p>
</li>
<li><p>static 메서드의 코드 블록에 적용</p>
<ul>
<li>클래스에 Lock</li>
<li>코드 블록에 this 를 지정할 수 없다.</li>
</ul>
</li>
<li><p>동기화 순서</p>
<ul>
<li>Thread 의 동기화 순서를 보장하지 않는다.</li>
</ul>
</li>
</ul>
<h3 id="27-동기화와-비동기화의-차이를-설명해주세요">27. 동기화와 비동기화의 차이를 설명해주세요.</h3>
<ul>
<li>동기화와 비동기화의 차이는 호출되는 함수의 반환을 신경쓰는지 여부와 연관이 있습니다. 호출되는 함수의 반환값을 기다리면 동기화, 기다리지 않으면 비동기화입니다. 자바에서 동기화는 synchronized 키워드를 통해 구현 가능하고, 비동기화는 Thread 클래스를 통해 구현할 수 있습니다.</li>
<li>동기화<ul>
<li>호출되는 함수의 반환값을 기다린다. 반환이 되었으면 다음 흐름을 진행한다.</li>
<li>synchronized 키워드</li>
<li>Atomic 클래스<ul>
<li><a href="https://steady-coding.tistory.com/568">CAS(Compare-And-Swap)</a> 알고리즘을 사용하여 lock 없이 동기화 처리 가능</li>
<li>lock 없이 동기화</li>
</ul>
</li>
<li>volatile<ul>
<li>Main Memory 에 저장</li>
<li>모든 스레드에서 Main Memory 에 읽기, 쓰기를 하기 때문에 값이 일치함</li>
</ul>
</li>
</ul>
</li>
<li>비동기화<ul>
<li>호출되는 함수의 반환값을 기다리지 않고 다음 흐름을 진행한다.</li>
<li>Thread 를 통해 구현</li>
</ul>
</li>
</ul>
<h3 id="28-동시성-문제가-무엇인가요-자바에서-동시성-문제를-해결할-수-있는-방법이-있을까요">28. 동시성 문제가 무엇인가요? 자바에서 동시성 문제를 해결할 수 있는 방법이 있을까요?</h3>
<ul>
<li><p>동시성 문제란 동일한 자원에 대해 여러 스레드가 동시에 접근하면서 발생하는 문제입니다. 자바에서는 해당 쓰레드만 접근할수 있는 ThreadLocal 를 통해 해결할 수 있습니다. 하지만 ThreadLocal 의 사용이 끝나면 반드시 저장된 값을 제거하는 과정을 거쳐야합니다.</p>
</li>
<li><p>동일한 자원에 대해 여러 스레드가 동시에 접근하면서 발생하는 문제</p>
</li>
<li><p>지역 변수에서는 발생하지 거의 발생하지 않고, 싱글톤, static 과 같은 공용 필드에서 주로 발생</p>
</li>
<li><p>읽기와 쓰기를 동시에 하는 경우에 발생</p>
</li>
</ul>
<h3 id="29-thread-local에-대해-설명해주세요">29. Thread Local에 대해 설명해주세요.</h3>
<ul>
<li>스레드마다 접근할 수 있는 개인 저장소를 의미합니다. ThreadLocal 의 데이터는 사용이 끝나면 반드시 삭제해야합니다. 스레드 풀 환경에서 사용이 완료된 데이터를 지워주지 않으면 재사용되는 스레드가 올바르지 않는 데이터를 참조할 수 있기 때문입니다.</li>
</ul>
<hr>
<h3 id="30-자바의-어노테이션에-대해-설명해주세요">30. 자바의 어노테이션에 대해 설명해주세요.</h3>
<ul>
<li><p>인터페이스를 기반으로 한 문법으로 주석처럼 코드에 달아 특별한 의미를 부여하거나 기능을 주입할 수 있습니다. 어노테이션에는 크게 세가지 종류가 있습니다. JDK 에 포함되어 있는 build-in 어노테이션과 어노테이션의 정보를 나타내기 위한 Meta 어노테이션, 개발자가 직접 정의한 Custom 어노테이션이 있습니다.</p>
</li>
<li><p>인터페이스를 기반으로 한 문법</p>
</li>
<li><p>사용</p>
<ul>
<li>컴파일러에게 필요한 정보 제공</li>
<li>컴파일/배포 시 필요한 처리 기능</li>
<li>런타임 처리 제공</li>
</ul>
</li>
<li><p>build-in 어노테이션</p>
<ul>
<li>@Override</li>
<li>@Deprecated</li>
<li>@SuppressWarnings</li>
<li>@FunctionalInterface</li>
<li>...</li>
</ul>
</li>
<li><p>메타 어노테이션</p>
<ul>
<li>@Target: 어노테이션이 적용 가능한 대상 지정</li>
<li>@Retention: 어노테이션이 유지되는 기간 지정</li>
<li>@Documented: javadoc 포함 여부 지정</li>
<li>@Inherited: 어노테이션의 상속 가능 여부 지정</li>
<li>@Repeatable: 어노테이션을 반복하여 적용 가능하도록 지정</li>
</ul>
</li>
<li><p>주의 사항</p>
<ul>
<li>@AllArgsConstructor, @RequiredArgsConstructor<ul>
<li>인스턴스 멤버의 순서가 변경되면 생성자의 순서도 변경되기 때문에 타입이 같은 경우 개발자가 인지하지 못할 수도 있다.</li>
</ul>
</li>
<li>@ToString<ul>
<li>양방향 관계에서 해당 어노테이션을 통해 순환참조가 일어날 수 있다.</li>
</ul>
</li>
<li>@Data<ul>
<li>위의 모든 문제가 일어날 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="31-자바-8에-추가된-기능들에-대해-간단히-설명해주세요">31. 자바 8에 추가된 기능들에 대해 간단히 설명해주세요.</h3>
<ul>
<li><p>자바 8에는 익명 함수를 단순하게 표기한 람다 표현식, 하나의 추상 메서드만 갖고 있는 함수형 인터페이스, 인터페이스의 default 메서드, 연속된 정보를 처리하는 Stream 클래스, null 처리를 간편하게 하기 위한 Optional 클래스 등이 있습니다.</p>
</li>
<li><p>주요하게 추가된 것</p>
<ul>
<li>Lambda</li>
<li>Functional Interface<ul>
<li>하나의 추상 메서드만 가지는 인터페이스</li>
</ul>
</li>
<li>Stream</li>
<li>Optional</li>
<li>인터페이스의 Default Method</li>
<li>날짜 관련 클래스 추가<ul>
<li><code>ZoneDataTime</code>, <code>LocalDate</code>, <code>DateTimeFormatter</code>, <code>DayOfWeek</code></li>
</ul>
</li>
<li>병렬 배열 정렬<ul>
<li>parallelSort() 메서드 추가</li>
</ul>
</li>
<li>StringJoiner<ul>
<li>순차적으로 나열되는 문자열 사이에 특정 문자열을 넣어줄 때 사용</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="32-stream에-대해-설명해주세요">32. Stream에 대해 설명해주세요.</h3>
<ul>
<li><p>자바 8에 추가된 Collection 타입의 데이터를 처리하는 API 입니다. 주요 특징으로는 병렬 처리 용이하고 원본 데이터를 변경하지 못하며 재사용 불가능하고 최종 연산을 할 때 중간 연산이 실행된다는 점이 있습니다.</p>
</li>
<li><p>특징</p>
<ul>
<li>병렬 처리 용이<ul>
<li>parallel() 메서드 제공. (cf. <a href="https://m.blog.naver.com/tmondev/220945933678">common fork join pool</a>)</li>
<li>코어 수가 많을수록, 처리할 데이터가 많을수록, 데이터당 처리 시간이 길수록 병렬 처리 성능 향상</li>
</ul>
</li>
<li>Immutable<ul>
<li>원본 데이터에 대한 변경 불가능</li>
</ul>
</li>
<li>Lazy<ul>
<li>중간 연산은 최종 연산에 이용될 때 값 계산</li>
<li>중간 연산: filter, map, flatMat, limit, sorted, peek, ...</li>
<li>최종 연산: foreach, reduce, findFirst, anyMatch, count, collect, ...</li>
</ul>
</li>
<li>재사용 불가능<ul>
<li>최종 연산 완료 후 Stream 이 닫히므로 재사용 불가능</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="33-stream과-반복문-for문의-성능차이가-있을까요">33. Stream과 반복문 for문의 성능차이가 있을까요?</h3>
<ul>
<li>for 문은 단순 인덱스 기반으로 접근하고, 컴파일러가 최적화를 하기 때문에 성능이 더 빠릅니다. 특히 for 문은 기본 데이터 타입을 통해 접근하면 wrapper 타입에 비해 Heap 메모리에 접근하지 않아도 되서 성능이 더 올라가게 됩니다.</li>
</ul>
<h3 id="34-stream에서-사용할-수-있는-함수형-인터페이스에-대해-설명해주세요">34. Stream에서 사용할 수 있는 함수형 인터페이스에 대해 설명해주세요.</h3>
<ul>
<li>사용할 수 있는 함수형 인터페이스로는 인자를 받지 않고 반환만 하는 Supplier, 인자를 받고 반환은 하지 않는 Consumer, 인자를 받고 반환을 하는 Function, 인자를 받아서 참 거짓을 판단하는 Predicate 등이 있습니다. </li>
</ul>
<h3 id="35-lambda에-대해-설명해주세요">35. Lambda에 대해 설명해주세요.</h3>
<ul>
<li><p>Lambda 는 자바 8에서 추가되어 메서드를 하나의 식으로 표현할 수 있는 익명 함수입니다. 함수형 인터페이스를 통해 정의할 수 있으며 기존 익명 함수로 작성하던 코드를 줄일 수 있다는 장점이 있습니다.</p>
</li>
<li><p>자바 8에서 추가되어 메서드를 하나의 식으로 표현하는 익명 함수</p>
</li>
<li><p>함수형 인터페이스를 통해서 사용 가능</p>
</li>
<li><p>장점</p>
<ul>
<li>기존 익명 함수로 작성하던 코드를 줄일 수 있다.</li>
<li>가독성이 증가된다.</li>
<li>병렬 프로그래밍에 용이하다.</li>
</ul>
</li>
<li><p>단점</p>
<ul>
<li>남용시 코드 이해가 어렵다.</li>
<li>재귀 활용과 디버깅이 어렵다.</li>
</ul>
</li>
</ul>
<h3 id="36-익명-클래스anonymous-inner-class와-lambda의-차이점을-알고계신가요">36. 익명 클래스(Anonymous Inner Class)와 Lambda의 차이점을 알고계신가요?</h3>
<ul>
<li>익명 클래스는 클래스를 의미하고 여러 메서드를 포함할 수 있지만, Lambda 는 익명 메서드를 의미합니다. 또한 익명 클래스의 this 는 새로 생성된 클래스 객체를 의미하고 Lambda 의 this 는 Lambda 를 정의한 클래스를 의미합니다.</li>
<li>익명 클래스<ul>
<li>이름 없는 클래스</li>
<li>추상 및 구체 클래스 확장 O</li>
<li>여러 추상 메서드를 포함하는 인터페이스 구현 O</li>
<li>익명 클래스 생성 시 인스턴스 변수 선언 O</li>
<li>익명 내부 클래스 인스턴스화 O</li>
<li>this 키워드가 생성된 익명 클래스 객체를 의미</li>
</ul>
</li>
<li>Lambda<ul>
<li>이름 없는 메서드</li>
<li>추상 및 구체 클래스 확장 X</li>
<li>여러 추상 메서드를 포함하는 인터페이스 구현 X</li>
<li>익명 클래스 생성 시 인스턴스 변수 선언 X</li>
<li>익명 내부 클래스 인스턴스화 X</li>
<li>this 키워드가 생성된 Lambda 가 정의된 클래스를 의미</li>
</ul>
</li>
</ul>
<h3 id="37-람다식에서-외부-변수를-사용할-때-final-키워드를-붙여서-사용하는-이유가-무엇일까요-final을-안-붙여도-되지-않을까요">37. 람다식에서, 외부 변수를 사용할 때 final 키워드를 붙여서 사용하는 이유가 무엇일까요? final을 안 붙여도 되지 않을까요?</h3>
<ul>
<li>외부 지역 변수를 제어하는 스레드와 람다식을 제어하는 스레드가 다를 수 있기 때문입니다. 이 경우 각 스레드간 스택 영역이 다르기 때문에 값을 공유할 수 없고, 동기화할 수 없기 때문에 외부 변수가 최신 값으로 변경이 되었는지 확신할 수 없습니다. 따라서 매번 다른 결과가 도출될 수 있기 때문에 final 키워드를 붙여야 합니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[기술 면접 - java 2편]]></title>
            <link>https://velog.io/@ch980113_/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91-java-2%ED%8E%B8</link>
            <guid>https://velog.io/@ch980113_/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91-java-2%ED%8E%B8</guid>
            <pubDate>Tue, 13 Aug 2024 15:24:23 GMT</pubDate>
            <description><![CDATA[<h3 id="1-optional에-대해-설명해주세요-optional을-사용하면-무슨-이점이-있을까요">1. Optional에 대해 설명해주세요. Optional을 사용하면 무슨 이점이 있을까요?</h3>
<ul>
<li>Optional 은 Null 이 될 수 있는 값을 감싸는 Wrapper 클래스입니다. </li>
<li>명시적으로 Null 가능성을 표현할 수 있고, Null 체크를 직접 하지 않아도 되고, NPE 가 발생할 가능성이 있는 값을 직접 다룰 필요가 없다는 점이 장점입니다.</li>
<li>Null 이 될 수 있는 값을 감싸는 Wrapper 클래스</li>
<li>장점<ul>
<li>명시적으로 변수에 대한 Null 가능성을 표현할 수 있다.</li>
<li>Null 체크를 직접 하지 않아도 된다.</li>
<li>Null Pointer Exception 이 발생할 가능성이 있는 값을 직접 다룰 필요가 없다.</li>
</ul>
</li>
<li>단점<ul>
<li>Wrapper 클래스이기 때문에 생성 비용이 비싸다.</li>
<li>직렬화가 불가능하기 때문에 클래스의 인스턴스 필드로 사용하면 안된다.</li>
<li>필드로 사용하기 위해 고안된 것이 아니므로 값을 반환하는 용도로 사용해야 한다.</li>
</ul>
</li>
</ul>
<h3 id="2-optional을-사용하면서-주의해야할-점이-있을까요">2. Optional을 사용하면서 주의해야할 점이 있을까요?</h3>
<ul>
<li>Optional 은 직렬화를 구현하지 않았기 때문에 필드로 사용하는 것을 주의해야 합니다. 또한 생성자나 메서드 인자로 사용하는 것을 주의해야 합니다. 생성 비용이 비싼 Optional 대신 일반 객체를 넘겨 null 체크를 하는 것이 좋습니다.</li>
<li>필드로 사용하지 말자<ul>
<li>Optional 은 Serializable 을 구현하지 않았기 때문에 직렬화가 되지 않는다.</li>
</ul>
</li>
<li>생성자나 메서드 인자로 사용하지 말자<ul>
<li>생성비용이 비싼 Optional 대신 일반 객체를 넘겨 호출받는 쪽에서 null 체크를 하자. Optional 이 오더라도 Optional 에 null 이 할당되어 있을 수도 있다.</li>
</ul>
</li>
<li>orElse 대신 orElseGet 을 사용하자<ul>
<li>null 일 경우에만 반환하는 코드가 호출되므로 더 효율적이다.</li>
</ul>
</li>
<li>컬렉션을 Optional 로 감싸지 말자</li>
</ul>
<hr>
<h3 id="3-object-클래스의-equals와-hashcode는-무슨-역할을-하나요">3. Object 클래스의 equals()와 hashcode()는 무슨 역할을 하나요?</h3>
<ul>
<li>equals 는 객체의 내부 요소를 비교하여 객체의 동등성을 확인할 떄 사용합니다. </li>
<li>hashcode 는 런타임 시점에 객체의 유일한 값을 반환하는 것입니다. </li>
<li>이는 HashMap, HashTable 등 여러 Collection 클래스에서 객체끼리 구분할 때 사용합니다.</li>
</ul>
<h3 id="4-equals와-hashcode는-언제-재정의해야할까요-또-왜-같이-오버라이딩-하는게-좋을까요">4. equals()와 hashcode()는 언제 재정의해야할까요? 또, 왜 같이 오버라이딩 하는게 좋을까요?</h3>
<ul>
<li><p>equals 를 재정의하지 않으면 객체의 주소값만 비교하는 것이 기본 구현입니다. </p>
</li>
<li><p>하지만 객체가 같은 값을 가질 때 같은 객체로 인식하기 위해서는 클래스의 필드에 맞게 재정의가 필요합니다. </p>
</li>
<li><p>hashcode 는 객체간의 구분을 위해 사용하므로 유일하게 객체를 식별할 때 재정의해야 합니다. - Object 의 명세에 의하면 equals 가 동일하면 동일한 해시코드를 반환해야 합니다. 이 때문에 같이 오버라이드 해야합니다.</p>
</li>
<li><p>equals 만 구현했을 때 문제점</p>
<ul>
<li>만약 equals 만 구현하여 동등한 객체로 인식되는데 다른 해시 값이 나온다면, Object 명세에도 어긋나지만, 의미상으로도 이상하다. 동등한 객체인데 HashMap 이나 다른 Collection 객체에서는 다른 객체로 인식되는 문제가 생긴다.</li>
</ul>
</li>
<li><p>hashcode 만 구현했을 때 문제점</p>
<ul>
<li>만약 hashcode 만 구현하여 동일한 해시코드가 나오는데 동등성이 보장되지 않는다면, 마찬가지로 Collection 객체에서 같은 객체로 인식했는데 equals 메서드를 통해 비교할 때는 다르다는 결과가 나오게 된다. 이는 프로그램의 잠재적인 위험이 된다.</li>
</ul>
</li>
<li><p>hashcode 를 구현할 때 주의할 점</p>
<ul>
<li>핵심 필드를 꼭 포함해서 구현하자<ul>
<li>성능보다는 핵심필드를 포함하자</li>
</ul>
</li>
<li>자세한 구현 사항을 API 사용자는 모르는 것이 좋다.<ul>
<li>사용자가 구현에 의존하지 않을 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="5-서로-다른-인스턴스가-같은-hashcode값을-가질-수-있을까요">5. 서로 다른 인스턴스가 같은 hashcode값을 가질 수 있을까요?</h3>
<ul>
<li><p>서로 다른 인스턴스더라도 해시코드 값을 가질 수 있습니다. 이때문에 해시 충돌을 해결하는 것이 중요해졌습니다. 해시 충돌을 완화하는 방법에는 크게 Open Addressing 과 Separate Chaining 방식이 존재합니다. 자바의 HashMap 에서는 Separate Chaining 방식을 사용하며, 이는 해시 버킷에 들어갈 수 있는 엔트리의 제한을 두지 않는 방식입니다.</p>
</li>
<li><p>Open Addressing</p>
<ul>
<li>한 버킷당 들어갈 수 있는 엔트리가 하나</li>
<li>해시 충돌이 일어난 경우, 다른 버킷에 저장</li>
<li>이를 위해 빈 버킷을 찾는 여러 알고리즘이 존재한다.<ul>
<li>Linear probing</li>
<li>Quadratic probing</li>
<li>Dobule hasing</li>
</ul>
</li>
<li>특징<ul>
<li>전체 버킷 중 사용중인 버킷의 비율이 커지면 탐사 비용이 비약적으로 상승한다.</li>
<li>데이터를 삭제할 때 비효율적이다.</li>
</ul>
</li>
</ul>
</li>
<li><p>Separate Chaining</p>
<ul>
<li>한 버킷에 여러 엔트리가 들어갈 수 있음</li>
<li>버킷은 주로 LinkedList 또는 Tree 를 사용</li>
<li>특징<ul>
<li>위의 방식과 비교하여 추가적인 메모리 공간 필요</li>
<li>적재율에 따라 선형적으로 성능이 저하됨</li>
</ul>
</li>
</ul>
</li>
<li><p>자바에서의 hash 충돌 발생 해결 방법 (HashMap)</p>
<ul>
<li>Separate Chaining</li>
<li>Java 7 까지는 LinkedList 를 고정적으로 사용</li>
<li>Java 8 부터 데이터의 개수에 따라 적으면 LinkedList, 많으면 Tree 사용</li>
</ul>
</li>
</ul>
<hr>
<h3 id="6-string-클래스는-final로-선언되어있습니다-왜-그런걸까요">6. String 클래스는 final로 선언되어있습니다. 왜 그런걸까요?</h3>
<ul>
<li><p>String 클래스가 final 로 선언되면서 불변성을 가지게 되었습니다. </p>
</li>
<li><p>이 이유로는 String Pool 을 통한 메모리 절약, 다수의 클래스에 매개변수로 사용되기 때문에 보완 관련 문제, 해시 기반 Collection 의 키 값으로 사용하기 위함 등이 있습니다.</p>
</li>
<li><p>String Pool</p>
<ul>
<li>String 은 자바를 설계할 때 가장 많이 사용할 것으로 예상된 데이터 타입이다.</li>
<li>이를 최적화하기 위해 String Pool 에 String 리터럴을 포함하는 방법을 이용했다.</li>
<li>String 객체를 공유하여 잉여 객체 생산을 막는 것이 목표이다.</li>
<li>이를 위해서는 final 또는 불변이어야 가능하다.</li>
</ul>
</li>
<li><p>Security</p>
<ul>
<li>String 은 다수의 자바 클래스의 매개 변수로 쓰이고 있다. </li>
<li>만약 String 이 불변이지 않으면, String 의 조작을 통해 시스템의 특점 파일에 대한 액세스 권한을 얻는 등 심각한 보안 문제가 발생한다.</li>
</ul>
</li>
<li><p>Multithreading</p>
<ul>
<li>자바에서 멀티 스레드를 지원하기 위해 String 객체는 thread safe 를 보장해야 한다.</li>
</ul>
</li>
<li><p>Optimization and Performance</p>
<ul>
<li>String 을 불변 클래스로 만들면서 성능 최적화를 할 수 있게 되었다.</li>
<li>값이 변경되지 않는 것을 이용해서 해시 코드 값을 lazy 하게 계산하고 일단 생성 되면 String Pool 에 캐싱한다.</li>
<li>이를 통해 한번 계산된 해시 코드 값을 계속 사용하는 등 성능 개선을 할 수 있다.</li>
<li>HashMap 등 해시 관련 함수에 이용할 시 성능 향상의 원인이 된다.</li>
</ul>
</li>
</ul>
<h3 id="7-string을-new-또는--로-생성했을-때의-차이점을-설명해주세요">7. String을 new 또는 &quot;&quot; 로 생성했을 때의 차이점을 설명해주세요.</h3>
<ul>
<li>String 을 &quot;&quot; 와 같이 리터럴로 생성했을 때는 String Pool 에 캐시됩니다. 따라서 객체를 재활용하는 특징이 있습니다. </li>
<li>반면, new 키워드로 생성했을 때는 다른 객체와 똑같이 Heap 메모리에 생성되고 객체를 공유하지 못하는 특징이 있습니다.</li>
<li>String Pool 도 GC 가 될까?<ul>
<li>Java 7 이전<ul>
<li>String Pool 은 PermGen 이라는 곳에 저장되어 있었습니다.</li>
<li>이 공간은 런타임에 확장할 수 없고, GC 에 적합하지 않습니다.</li>
<li>그리고 일반 Heap 메모리에 비해 공간이 작아서 문자열을 많이 생성할 경우 메모리 부족 에러가 발생했습니다.</li>
</ul>
</li>
<li>Java 7 이후<ul>
<li>String Pool 은 이후 일반 Heap 공간에 저장되고 이는 GC 대상이 되는 공간입니다.</li>
<li>이 방식을 통해 참조되지 않은 문자열을 풀에서 제거해 메모리 부족 위험이 줄어들었습니다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="8-string-stringbuilder-stringbuffer-를-각각-비교해주세요">8. String, StringBuilder, StringBuffer 를 각각 비교해주세요.</h3>
<ul>
<li><p>String 은 다른 두 클래스와 다르게 새로운 값을 할당할 때마다 새로운 클래스에 대한 객체가 생성됩니다. </p>
</li>
<li><p>또한 + 연산을 통해 String 객체를 합치는 경우 GC 되기 전까지 메모리에 부하를 주게 됩니다. </p>
</li>
<li><p>이와 반대로 StringBuilder, StringBuffer 는 메모리에 append 하는 방식으로 클래스에 대한 객체를 생성하지 않습니다. </p>
</li>
<li><p>다만 이 둘의 차이는 StringBuilder 는 thread safe 하지 않고, StringBuffer 는 thread safe 하다는 점이 있습니다.</p>
</li>
<li><p>JDK 1.5 이전 버전</p>
<ul>
<li>문자열 연산을 할 때 각 리터럴마다 새로운 메모리를 할당</li>
</ul>
</li>
<li><p>JDK 1.5 이후 버전</p>
<ul>
<li>문자열 연산을 할 때 컴파일 과정에서 StringBuilder 로 컴파일 되도록 변경</li>
<li>단 반복문을 사용하여 문자열 연산을 할 경우 이전과 똑같이 새로운 메모리 할당</li>
</ul>
</li>
<li><p>성능</p>
<ul>
<li>StringBuilder &gt; StringBuffer &gt;&gt;&gt; String</li>
</ul>
</li>
</ul>
<hr>
<h3 id="9-컬렉션-프레임워크에-대해-설명해주세요">9. 컬렉션 프레임워크에 대해 설명해주세요.</h3>
<ul>
<li><p>컬렉션 프레임워크는 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 클래스의 집합입니다. </p>
</li>
<li><p>주요 인터페이스로는 List, Set, Map, Queue 등이 있습니다. </p>
</li>
<li><p>이중 Map 은 다른 것들과 특징이 달라 Collection 을 상속하지 않고 나머지는 Collection 을 상속합니다. 장점으로는 효율적이고 빠른 코드 작성을 할 수 있습니다.</p>
</li>
<li><p>정의: 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 클래스 집합</p>
</li>
<li><p>특징</p>
<ul>
<li>가변적</li>
<li>데이터 삽입, 탐색, 정렬 등 편리한 API 다수 제공</li>
<li>JDK 1.2 버전부터 지원<ul>
<li>초기에는 Vector, Properties, Stack, HashTable, Dictionary 등이 제공되고, 통일성있고 표준화된 인터페이스가 존재하지 않았다.</li>
</ul>
</li>
</ul>
</li>
<li><p>장점</p>
<ul>
<li>다수의 데이터 처리를 직접 구현하지 않고 사용하면 되서 편리하다.</li>
<li>효율적인 데이터 처리로 인해 성능 향상이 있다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="10-list-인터페이스의-구현체에-대해-설명해주세요">10. List 인터페이스의 구현체에 대해 설명해주세요.</h3>
<ul>
<li><p>List 의 구현체로는 ArrayList, LinkedList, Vector, Stack 이 존재합니다. </p>
</li>
<li><p>ArrayList 는 배열처럼 연속된 메모리에 저장되어 검색은 용이하나 삽입, 삭제에는 부적절합니다. </p>
</li>
<li><p>LinkedList 는 양방향 포인터 구조로 데이터 검색보다는 삽입과 삭제가 빈번하게 일어나는 경우에 유용합니다. </p>
</li>
<li><p>Vector 는 ArrayList 와 동일하게 배열로 구현되어있고 내부에서 동기 처리가 일어나는 것이 특징입니다. </p>
</li>
<li><p>마지막으로 Stack 은 Vector 를 상속받아 동기 처리가 일어납니다.</p>
</li>
<li><p>ArrayList</p>
<ul>
<li>내부적으로 배열을 사용하여 메모리가 연속적으로 저장된다.</li>
<li>배열과 달리 메모리가 동적이다.</li>
<li>데이터 삽입, 삭제 시 해당 데이터 이후 모든 데이터의 복사가 이루어지므로 빈번한 삽입, 삭제는 비효울적이다.</li>
<li>인덱스를 통해 검색하므로 검색에 효율적이다.</li>
</ul>
</li>
<li><p>LinkedList</p>
<ul>
<li>양방향 포인터 구조로 저장된다.</li>
<li>데이터의 삽입, 삭제 시 포인터의 위치만 바꾸면 되기 때문에 효율적이다.</li>
<li>데이터 검색 시 포인터를 타면서 순회하기 때문에 비효율적이다.</li>
</ul>
</li>
<li><p>Vector</p>
<ul>
<li>내부적으로 배열을 사용한다.</li>
<li>동기화 처리를 하여 Thread Safe 하다.</li>
<li>성능이 좋지 않고 무거워 잘 쓰이지 않는다.</li>
<li>멀티 스레드 환경에서도 ArrayList 를 활용하는 것이 좋다.<pre><code class="language-java">class MyList {
ArrayList&lt;T&gt; list = new ArrayList&lt;&gt;(Collections.synchronizedList());
}</code></pre>
</li>
</ul>
</li>
<li><p>Stack</p>
<ul>
<li>Vector 를 상속받아 구현하였다.</li>
<li>동기화 처리를 하여 Thread-safe 하다.</li>
</ul>
</li>
</ul>
<h3 id="11-array와-arraylist는-어떤-차이점이-있을까요">11. Array와 ArrayList는 어떤 차이점이 있을까요?</h3>
<ul>
<li>Array 와 ArrayList 의 차이는 길이의 가변성, 제네릭 지원, 기본 데이터 타입 저장 유무에 차이가 있습니다. </li>
<li>배열은 길이가 불변에 제네릭을 지원하지 않고 기본 데이터 타입을 저장할 수 있고, ArrayList 는 길이가 가변이고 제네릭을 지원합니다. 기본 데이터 타입은 저장할 수 없습니다.</li>
</ul>
<h3 id="12-arraylist-와-linkedlist를-비교해주세요">12. ArrayList 와 LinkedList를 비교해주세요.</h3>
<ul>
<li>ArrayList 는 배열로 구현되어 메모리에 순차적으로 데이터가 저장되게 됩니다. </li>
<li>이러한 특성 때문에 데이터를 검색할 때 인덱스를 통해 찾을 수 있어 효율적입니다. </li>
<li>하지만 삽입 또는 삭제 시 해당 데이터의 이후 데이터들을 모두 복사하는 과정이 필요하므로 빈번한 삽입, 삭제에는 비효율적입니다. </li>
<li>반면, LinkedList 는 양방향 포인터 구조로 되어있어 데이터가 메모리에 불연속적으로 저장됩니다. 데이터와 데이터 사이의 포인터를 통해 연결되어 삽입, 삭제 시 포인터만 바꾸면 되서 효율적이지만 검색 시 데이터들을 순회해야 하기 때문에 비효율적입니다.</li>
</ul>
<hr>
<h3 id="13-map-인터페이스의-구현체에-대해-설명해주세요">13. Map 인터페이스의 구현체에 대해 설명해주세요.</h3>
<ul>
<li>Map 의 구현체로는 엔트리가 배열로 저장되고 해시 값을 인덱스로 사용하는 HashMap, 엔트리가 Linked List 를 사용하는 LinkedHashMap, 레드 블랙 트리로 저장되는 TreeMap, 다중 락을 지원하는 ConCurrentHashMap, 싱글 락을 지원하는 HashTable 이 있습니다.</li>
<li>HashMap<ul>
<li>Entry&lt;Key, Value&gt; 가 배열의 형태로 저장</li>
<li>배열의 인덱스로 Key 객체의 해시코드 값 이용<ul>
<li>입력과 무관하게 출력.</li>
<li>정렬 제공 X</li>
</ul>
</li>
<li>Key, Value 모두 null 값을 허용</li>
<li>Thread-safe 하지 않음</li>
<li>검색 및 삽입 시간 복잡도: O(1)</li>
<li>Fail-Fast Iterators</li>
</ul>
</li>
<li>LinkedHashMap<ul>
<li>Entry&lt;Key, Value&gt; 가 LinkedList 형태로 저장</li>
<li>입력 받은 순서대로 저장<ul>
<li>입력한 순서대로 출력.</li>
</ul>
</li>
<li>Key, Value 모두 null 값을 허용</li>
<li>Thread-safe 하지 않음</li>
<li>검색 및 삽입 시간 복잡도: O(1)</li>
</ul>
</li>
<li>TreeMap<ul>
<li>Red Black 자료구조로 저장</li>
<li>키 값을 기준으로 오름차순으로 정렬<ul>
<li>입력받은 순서 보장 X</li>
</ul>
</li>
<li>Key null 값을 허용안함</li>
<li>Thread-safe 하지 않음</li>
<li>검색 및 삽입 시간 복잡도: O(logn)</li>
</ul>
</li>
<li>ConCurrentHashMap<ul>
<li>Key, Value 모두 null 값을 허용 X</li>
<li>Thread-safe 보장<ul>
<li>버킷 단위로 lock</li>
<li>버킷의 수 == 동시작업 가능한 쓰레드 수</li>
<li>수정 작업시 동기 처리</li>
</ul>
</li>
</ul>
</li>
<li>HashTable<ul>
<li>Key, Value 모두 null 값을 허용 X</li>
<li>Thread-safe 보장<ul>
<li>모든 작업에 동기 처리</li>
</ul>
</li>
<li>Fail-Safe Iterators</li>
</ul>
</li>
</ul>
<h3 id="14-hashtable에-대해-설명해주세요">14. HashTable에 대해 설명해주세요.</h3>
<ul>
<li>키 벨류 형태로 데이터를 저장하는 자료구조로 배열을 이용합니다. </li>
<li>모든 메서드에 synchronized 키워드가 붙어있어 thread-safe 하다는 특징이 있습니다. 다만 이때문에 성능 저하가 존재할 수 있습니다.</li>
</ul>
<h3 id="15-hashmap과-hashtable을-비교해주세요">15. HashMap과 HashTable을 비교해주세요.</h3>
<ul>
<li>HashMap 과 HashTable 모두 배열의 형태로 저장되는 점에서 동일합니다. 다만 키 값에 null 을 허용하는지, 동기 처리를 하는지에 차이가 존재합니다.<h3 id="16-hashmap과-concurrenthashmap은-어떤-차이가-있나요">16. HashMap과 ConcurrentHashMap은 어떤 차이가 있나요?</h3>
</li>
<li>HashMap과 ConcurrentHashMap은 키 값에 null 허용 유무, 동기 처리 유무에 차이가 있습니다. </li>
<li>ConcurrentHashMap 은 버킷에 lock 을 걸어 버킷의 수만큼 스레드를 동작시킬 수 있습니다. 또한 읽기 작업에는 락을 걸지 않고 수정 시에만 적용한다는 특징이 있습니다.</li>
</ul>
<hr>
<h3 id="17-set-인터페이스의-구현체에-대해-설명해주세요">17. Set 인터페이스의 구현체에 대해 설명해주세요.</h3>
<ul>
<li>Set 의 구현체로는 해시 값을 사용하는 HashSet, 저장된 순서를 유지하는 LinkedHashSet, 레드 블랙 트리의 형태로 저장되는 TreeSet 등이 있습니다. </li>
<li>HashSet<ul>
<li>저장된 순서 유지 X</li>
<li>null 입력 가능</li>
<li>해시 값으로 저장<ul>
<li>검색 속도가 빠르다.</li>
</ul>
</li>
<li>내부적으로 HashMap 을 사용함</li>
</ul>
</li>
<li>LinkedHashSet<ul>
<li>저장된 순서 유지 O</li>
<li>null 입력 가능</li>
<li>내부적으로 LinkedHashMap 을 사용함</li>
</ul>
</li>
<li>TreeSet<ul>
<li>데이터가 정렬된 형태로 저장<ul>
<li>Red Black 트리 자료구조 이용</li>
</ul>
</li>
<li>null 입력 가능 X</li>
<li>내부적으로 TreeMap 을 사용함</li>
</ul>
</li>
</ul>
<h3 id="18-list와-set을-비교해주세요">18. List와 Set을 비교해주세요.</h3>
<ul>
<li>List 와 Set 은 인덱스를 통해 접근하는지, 동일한 요소를 저장할 수 있는지에 차이가 있습니다. </li>
<li>구현체에 따라 다르지만 List 는 인덱스를 통해 접근할 수 있고 동일한 요소를 저장할 수 있습니다. 반면, Set 은 인덱스를 통해 접근할 수 없고 동일한 요소를 저장할 수 없습니다.</li>
</ul>
<table>
<thead>
<tr>
<th>List</th>
<th>Set</th>
</tr>
</thead>
<tbody><tr>
<td>indexed sequence</td>
<td>non-indexed sequence</td>
</tr>
<tr>
<td>중복 허용</td>
<td>중복 허용 X</td>
</tr>
</tbody></table>
<hr>
<h3 id="19-java의-컴파일실행-과정을-설명해주세요">19. Java의 컴파일(실행) 과정을 설명해주세요.</h3>
<ul>
<li>먼저 JVM 이 OS 로부터 메모리를 할당받습니다. </li>
<li>이후 컴파일러에 의해 소스코드가 바이트코드로 변환됩니다. 다음 Class Loader 를 통해 Class 파일들을 JVM 으로 로딩시킨 후 이 파일들을 Execution Engine 이 해석한 후 실행하게됩니다.</li>
</ul>
<ol>
<li>자바로 개발된 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당합니다.</li>
<li>자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일합니다.</li>
<li>Class Loader를 통해 JVM Runtime Data Area로 로딩합니다.</li>
<li>Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석합니다.</li>
<li>해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어집니다.</li>
</ol>
<h3 id="20-jdk-jre-jvm에-대해-설명해주세요">20. JDK, JRE, JVM에 대해 설명해주세요.</h3>
<ul>
<li>JVM 은 자바 가상머신으로 바이트 코드를 실행시킬 수 있습니다. JRE 는 자바 실행 환경으로 실행하는데 필요한 도구들이 들어있습니다. JVM 이 이 안에 포함됩니다. JDK 는 개발을 위한 도구입니다. 컴파일러와 JRE 가 포함됩니다.</li>
<li>JVM<ul>
<li>바이트 코드(.class)를 돌리는 자바 가상머신</li>
<li>운영체제 별 제공<ul>
<li>플랫폼에 독립적</li>
</ul>
</li>
</ul>
</li>
<li>JRE<ul>
<li>실행 환경을 제공하는 도구들</li>
<li>JVM 과 Java Class 라이브러리들, Class Loader 로 구성<ul>
<li>Class Loader: 프로그램을 실행하는데 필요한 클래스를 JVM 에 로딩하는 역할 수행</li>
</ul>
</li>
</ul>
</li>
<li>JDK<ul>
<li>프로그램을 개발하기 위해 필요한 도구 모음</li>
<li>JRE 와 컴파일러, 디버깅 툴 등으로 구성</li>
</ul>
</li>
</ul>
<h3 id="21-jvm의-메모리-구조에-대해-설명해주세요">21. JVM의 메모리 구조에 대해 설명해주세요.</h3>
<ul>
<li>JVM 의 Runtime Data 영역에는 클래스의 정보를 저장하는 메서드 영역, 참조타입이 저장되는 힙 영역, 스레드 별 지역 변수, 매개변수 등이 저장되는 스택 영역, 스레드가 실행중인 스택 프레임 주소를 저장하는 PC 레지스터, 자바가 아닌 다른 언어로 작성된 코드를 저장하는 Native 메서드 스택가 있습니다.</li>
<li>Method Area<ul>
<li>Class Area, Static Area</li>
<li>클래스 정보가 저장됨<ul>
<li>멤버변수, 메서드 정보(이름, 타입, 접근제어자 등)</li>
<li>class 인지 interface 인지, static 변수, final 변수</li>
</ul>
</li>
<li>상수 자료형을 위한 Runtime Constant Pool 존재</li>
<li>모든 스레드에서 공유</li>
<li>GC 대상</li>
</ul>
</li>
<li>Heap Area<ul>
<li>레퍼런스 타입이 저장됨<ul>
<li>new 연산자로 생성된 객체와 배열 저장</li>
<li>String Pool</li>
</ul>
</li>
<li>모든 스레드에서 공유</li>
<li>런타임 시 동적으로 할당되어 사용</li>
<li>참조가 없는 객체는 GC 대상이 됨</li>
</ul>
</li>
<li>Stack Area<ul>
<li>프로그램 실행 과정에서 임시로 할당되거나 메서드 영역에서만 존재하는 데이터 저장<ul>
<li>지역변수, 매개변수, 임시 데이터 등</li>
</ul>
</li>
<li>스레드마다 스택 하나씩 할당</li>
</ul>
</li>
<li>PC register<ul>
<li>스레드에서 실행할 명령어 주소값 저장</li>
<li>스레드가 시작될 때 생성됨</li>
</ul>
</li>
<li>Native Method Stack<ul>
<li>.class 의 바이트 코드가 아닌 기계어로 작성된 프로그램을 실행시키는 영역</li>
<li>JAVA 가 아닌 다른 언어로 작성된 코드를 위한 영역</li>
</ul>
</li>
</ul>
<hr>
<h3 id="22-정적-바인딩-동적-바인딩">22. 정적 바인딩, 동적 바인딩</h3>
<ul>
<li>바인딩<ul>
<li>값이 할당되어 변경할 수 없는 상태</li>
</ul>
</li>
<li>정적 바인딩<ul>
<li>값이 컴파일 시점에 확정되는 것</li>
<li>static, private, final 메서드 및 변수<ul>
<li>override 가 불가능</li>
</ul>
</li>
<li>성능상으로 이점이 있음</li>
</ul>
</li>
<li>동적 바인딩<ul>
<li>값이 런타임 시점에 확정되는 것</li>
<li>method overriding</li>
<li>다형성에 유리</li>
<li>힙 영역에 vtable(가상 메서드 테이블) 생성<ul>
<li>vtable 은 클래스가 자신이 상속받은 메서드를 포함한 모든 메서드의 주소값을 저장하는 곳이다.</li>
<li>vtable -&gt;  4byte</li>
<li>메서드를 오버라이딩 했을 경우 오버라이딩한 메서드의 주소값을 가지기 때문에 부모 클래스 타입으로 선언되어도 오버라이딩한 메서드가 호출된다.</li>
</ul>
</li>
</ul>
</li>
<li>예상 질문<ul>
<li>정적 바인딩과 동적 바인딩의 차이점에 대해 설명해주세요.</li>
</ul>
</li>
</ul>
<h3 id="23-가비지-컬렉터">23. 가비지 컬렉터</h3>
<ul>
<li>가비지 컬렉터란?<ul>
<li>Heap 메모리에 있는 사용하지 않는 객체를 제거하는 역할을 수행합니다.</li>
<li>Weak Generational Hypothesis: Heap 영역 설계 시 고려한 전제<ul>
<li>대부분의 객체는 금방 접근 불가능한 상태가 된다.</li>
<li>오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.</li>
</ul>
</li>
<li>Heap 메모리 영역은 객체의 생존 기간에 따라 Young, Old 2가지 영역으로 설계되었다.</li>
<li>장점<ul>
<li>메모리를 수동으로 관리하던 것에서 비롯된 에러를 예방할 수 있다.</li>
</ul>
</li>
<li>단점<ul>
<li>GC 의 메모리 해제 타이밍을 개발자가 정확히 알기 어렵다.</li>
<li>삭제될 객체를 탐색하고 삭제하는 과정에서 오버헤드가 발생한다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="24-객체-지향-프로그래밍캡상추다">24. 객체 지향 프로그래밍(캡상추다)</h3>
<ul>
<li>객체지향 프로그래밍이란?<ul>
<li>프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법<ul>
<li>장점</li>
</ul>
</li>
<li>코드 재사용 용이</li>
<li>유지보수 용이</li>
<li>대형 프로젝트에 적합<ul>
<li>단점</li>
</ul>
</li>
<li>처리 속도 느림</li>
<li>설계가 어려움</li>
</ul>
</li>
<li>객체지향의 특징<ul>
<li>캡슐화<ul>
<li>클래스 안에 서로 연관있는 속성과 기능들을 하나의 캡슐로 만들어 데이터를 외부로부터 보호하는 것</li>
<li>목적<ul>
<li>데이터 보호: 외부로부터 클래스에 정의된 속성과 기능들을 보호</li>
<li>데이터 은닉: 내부의 동작을 감추고 외부에는 필요한 부분만 노출 (각 객체 고유의 독립성과 책임 영역을 안전하게 지킬 수 있다.)</li>
</ul>
</li>
<li>접근제어자와 getter/setter 를 통해 구현</li>
</ul>
</li>
<li>상속<ul>
<li>기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법요소</li>
<li>코드의 재사용을 통해 반복적인 코드를 최소화하고 공유하는 속성과 기능에 간편하게 접근할 수 있다.</li>
<li>상속과 구현<ul>
<li>상속: 상위 클래스의 속성과 기능들을 하위 클래스에서 그대로 받아 사용하거나 오버라이딩을 통해 선택적으로 재정의해서 사용</li>
<li>구현: 반드시 인터페이스에 정의된 추상 메서드의 내용이 하위 클래스에서 정의</li>
</ul>
</li>
</ul>
</li>
<li>추상화<ul>
<li>객체의 공통적인 속성과 기능을 추출하여 정의하는 것</li>
<li>추상클래스와 인테페이스로 구현</li>
<li>제어 추상화<ul>
<li>메서드의 작동방식과 같은 내부 로직을 숨기는 것</li>
<li>프로그래밍을 빠르게 설계하고 구현할 수 있다.</li>
</ul>
</li>
<li>데이터 추상화<ul>
<li>객체를 간단한 개념으로 일반화 시키는 것</li>
<li>공통 기능을 미리 개발함으로써, 구조를 빠르게 확장시킬 수 있다.</li>
</ul>
</li>
</ul>
</li>
<li>다형성<ul>
<li>객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질</li>
<li>메서드 오버라이딩과 오버로딩을 통해 구현</li>
<li>가능한 것 예시<ul>
<li>여러 종류의 객체를 배열로 다룰 수 있다.</li>
<li>하나의 타입만으로 여러 가지 타입의 객체를 참조할 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="25-solid-원칙">25. SOLID 원칙</h3>
<ul>
<li>SRP(Single Responsibility Principle): 단일 책임 원칙<ul>
<li>어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.<ul>
<li>클래스는 하나의 책임만 가진다.</li>
</ul>
</li>
</ul>
</li>
<li>OCP(Open Closed Priciple): 개방 폐쇄 원칙<ul>
<li>확장에는 열려있으나 변경에는 닫혀있어야 한다.</li>
<li>다형성과 연관이 있다.</li>
</ul>
</li>
<li>LSP(Listov Substitution Priciple): 리스코프 치환 원칙<ul>
<li>하위 타입은 상위 타입으로 대체할 수 있다.</li>
</ul>
</li>
<li>ISP(Interface Segregation Principle): 인터페이스 분리 원칙<ul>
<li>클라이언트의 목적과 용도에 적합한 인터페이스만 제공하는 것</li>
<li>불필요한 간섭을 최소화할 수 있다.</li>
</ul>
</li>
<li>DIP(Dependency Inversion Principle): 의존 역전 원칙<ul>
<li>고수준의 모듈은 저수준의 모듈에 의존하면 안된다.</li>
<li>추상화된 것은 구체적인 것에 의존하면 안된다.</li>
<li>변하기 쉬운 것에 의존하는 것보다 변하지 않는 것에 의존해야 한다.</li>
</ul>
</li>
</ul>
<h3 id="26-객체-지향-프로그래밍-vs-절차-지향-프로그래밍">26. 객체 지향 프로그래밍 vs 절차 지향 프로그래밍</h3>
<ul>
<li>설계 방식 <ul>
<li>객체지향<ul>
<li>자료구조와 이를 중심으로한 모듈들을 설계한 후 이들의 실행 순서와 흐름을 조합하는 방식</li>
</ul>
</li>
<li>절차지향<ul>
<li>프로그램의 순서와 흐름을 먼저 세우고 필요한 자료구조와 함수들을 설계하는 방식</li>
</ul>
</li>
</ul>
</li>
<li>목적<ul>
<li>객체지향<ul>
<li>필요한 객체들의 종류과 속성등이 중심</li>
</ul>
</li>
<li>절차지향<ul>
<li>실행 순서, 절차 중심</li>
</ul>
</li>
</ul>
</li>
<li>장단점<ul>
<li>객체지향<ul>
<li>장점</li>
</ul>
</li>
<li>코드의 재사용성이 높다.</li>
<li>디버깅이 쉽다.<ul>
<li>단점</li>
</ul>
</li>
<li>설계가 어렵다.</li>
<li>처리 속도가 느리다.</li>
</ul>
</li>
<li>절차지향<ul>
<li>장점<ul>
<li>컴퓨터의 처리구조와 유사해 실행 속도가 빠르다.</li>
</ul>
</li>
<li>단점<ul>
<li>유지보수가 어렵다.</li>
<li>실행 순서가 정해져 있어 순서가 바뀌면 결과가 바뀐다.</li>
<li>디버깅이 어렵다.</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[jenkins를 이용하여 배포하기]]></title>
            <link>https://velog.io/@ch980113_/jenkins%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ch980113_/jenkins%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 18 Jun 2024 04:07:51 GMT</pubDate>
            <description><![CDATA[<p>실수로 다른 계정에서 작성해버려서..^^ 아래 참고하기</p>
<p><a href="https://velog.io/@kyonggseo/Jenkins%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0">jemkims를 이용하여 배포하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1장 - 요구사항 확인]]></title>
            <link>https://velog.io/@ch980113_/1%EC%9E%A5-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%ED%99%95%EC%9D%B8</link>
            <guid>https://velog.io/@ch980113_/1%EC%9E%A5-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%ED%99%95%EC%9D%B8</guid>
            <pubDate>Fri, 12 Apr 2024 04:35:57 GMT</pubDate>
            <description><![CDATA[<p>내가 볼려고 만든 정리본 -- 수제비를 참고하였다.</p>
<blockquote>
<h2 id="소프트웨어-전통적-방법론">소프트웨어 전통적 방법론</h2>
</blockquote>
<ul>
<li>종류<ul>
<li><code>폭포수 모델</code><ul>
<li>가장 오래된 모델</li>
</ul>
</li>
<li><code>프로토타이핑 모델</code><ul>
<li>피드백</li>
</ul>
</li>
<li><code>나선형 모델</code><ul>
<li>점진적 개선해서 완벽하게 만드는 것</li>
<li>위험 감소 및 변경에 유연</li>
<li>계획 및 정의 -&gt; 위험 분석 -&gt; 개발 -&gt; 고객 평가 (계위개고)</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<h2 id="소프트웨어-개발-방법론">소프트웨어 개발 방법론</h2>
</blockquote>
<ul>
<li><code>애자일 방법론</code><ul>
<li>절차보다는 사람이 중심</li>
<li>문서보다 코드를 강조</li>
<li>종류<ul>
<li><code>XP</code><ul>
<li>1-3주의 반복</li>
<li>TDD</li>
<li>리팩토링</li>
</ul>
</li>
<li><code>스크럼</code><ul>
<li>스프린트 : 2-4주 개발</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="객체지향-설계-원칙solid">객체지향 설계 원칙(SOLID)</h2>
</blockquote>
<ul>
<li><code>단일 책임의 원칙(SRP : Single Responibility Priciple)</code><ul>
<li>하나의 클래스는 하나의 목적을 위해서 생성</li>
</ul>
</li>
<li><code>개방 폐쇄 원칙(OCP : Open Close)</code><ul>
<li>확장은 오픈, 변경은 클로즈</li>
</ul>
</li>
<li><code>리스코프 치환의 법칙(LSP : Liskov Subsititution)</code><ul>
<li>상속받은 자식클래스는 어디서나 부모클래스로 교체할 수 있어야 함</li>
</ul>
</li>
<li><code>인터페이스 분리의 원칙(ISP : Interface Segregation)</code><ul>
<li>특정 기능에 대한 인터페이스는 다른 기능이 변해도 영향 받지 않아야 함</li>
</ul>
</li>
<li><code>의존성 역전의 법칙(DIP : Dependency Inversion)</code><ul>
<li>클래스를 참조할 때, 클래스의 상위인 추상클래스, 인터페이스를 사용할 것</li>
</ul>
</li>
</ul>
<h2 id="객체지향이란">객체지향이란</h2>
<ul>
<li>속성과 메서드가 결합한 상태</li>
<li>캡슐화, 상속성, 다형성, 추상화, 정보 은닉, 관계성</li>
</ul>
<h2 id="객체지향-분석-방법론-종류">객체지향 분석 방법론 종류</h2>
<ul>
<li>OMT<ul>
<li>럼바우가 만듦</li>
<li>종류 : 객체, 동적, 기능 모델링<ul>
<li><code>객체 모델링</code><ul>
<li>ER다이어그램</li>
</ul>
</li>
<li><code>동적모델링</code><ul>
<li>상태 다이어그램</li>
</ul>
</li>
<li><code>기능모델링</code><ul>
<li>DFD 자료흐름도 사용</li>
</ul>
</li>
</ul>
</li>
<li>부치, 야콥슨(Jscobson) 이라는 사람들이 만든 방법도 있음   </li>
</ul>
</li>
</ul>
<h2 id="비용-산정-모델">비용 산정 모델</h2>
<ul>
<li><code>Loc 모형</code><ul>
<li>S/W 각 기능의 원시코드 라인 수의 낙관치, 중간치, 비관치를 측정하여 예측치를 구해서 비용 산정</li>
</ul>
</li>
<li><code>Man Month</code><ul>
<li>한 사람이 1개월 동안 할 수 있는 일의 양을 기준으로 비용 산정</li>
<li>Man Month : LOC / 월간 생산량</li>
<li>프로젝트 기간 : man month / 인력</li>
</ul>
</li>
<li><code>COCOMO</code><ul>
<li>보헴이 제안</li>
<li>프로그램 규모에 따라 비용 산정</li>
<li>비용 산정 결과는 프로젝트를 완성하는데 필요한 노력으로 산정(Man-Month)</li>
<li>종류<ul>
<li><code>조직형(Organic)</code><ul>
<li>5만</li>
</ul>
</li>
<li><code>반 분리형(Semi-Organic)</code><ul>
<li>30만 이하</li>
</ul>
</li>
<li><code>임베디드형(Embedded)</code><ul>
<li>30만 이상</li>
</ul>
</li>
</ul>
</li>
<li><code>기능점수 (FP)</code><ul>
<li>가중치를 부여</li>
</ul>
</li>
<li><code>푸트남 모형</code><ul>
<li>소프트웨어 개발주기의 단계별로 요구할 인력의 분포를 가정하는 방식</li>
<li>생명주기 예측 모형</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h1 id="현행-시스템-분석">현행 시스템 분석</h1>
<blockquote>
<h2 id="소프트웨어-아키텍처-41-뷰">소프트웨어 아키텍처 4+1 뷰</h2>
</blockquote>
<ul>
<li>1은 유스케이스</li>
<li>4는 논리 뷰, 구현 뷰, 프로세스 뷰, 배포 뷰</li>
</ul>
<h3 id="유스케이스-뷰">유스케이스 뷰</h3>
<ul>
<li>다른 뷰를 검증</li>
<li>사용자, 설계자, 개발자 관점</li>
</ul>
<h3 id="논리-뷰">논리 뷰</h3>
<ul>
<li>기능적인 요구사항</li>
<li>설계자, 개발자 관점</li>
</ul>
<h3 id="프로세스-뷰">프로세스 뷰</h3>
<ul>
<li>비기능적인 속성</li>
</ul>
<h3 id="구현-뷰">구현 뷰</h3>
<ul>
<li>정적인 소프트웨어 모듈의 구성</li>
<li>컴포넌트 구조와 의존성</li>
</ul>
<h3 id="배포-뷰">배포 뷰</h3>
<ul>
<li>배치되는지 매핑햇 보여줌</li>
</ul>
<h2 id="소프트웨어-아키텍처-패턴-유형">소프트웨어 아키텍처 패턴 유형</h2>
<ul>
<li><code>파이프-필터 패턴</code><ul>
<li>테이터 스트림을 생성</li>
</ul>
</li>
<li><code>브로커 패턴</code><ul>
<li>분리된 컴포넌트들로 이루어진 분산 시스템에서 사용</li>
</ul>
</li>
<li><code>모델뷰컨트롤러 패턴</code><ul>
<li>모델 : 핵심 기능과 데이터 보관</li>
<li>뷰 : 사용자에게 보여줌</li>
<li>컨트롤러 : 사용자로부터 요청받아 처리 </li>
<li>컨트롤러 -&gt; 모델 -&gt; 컨트롤러 -&gt; 뷰</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="디자인패턴">디자인패턴</h2>
</blockquote>
<h3 id="생성-패턴-생빌-프로-팩앱싱">생성 패턴 (생빌 프로 팩앱싱)</h3>
<ul>
<li><p><code>Builder</code> = 조립하는거야</p>
<ul>
<li>복잡한 인스턴스를 조립하여 만드는 구조</li>
</ul>
</li>
<li><p><code>Prototype</code>- 어떤 type으로 만들래? -&gt; 원형 </p>
<ul>
<li>일반적인 원형을 만들고 복사한 후 필요한 부분만 수정하여 사용</li>
</ul>
</li>
<li><p><code>Factory Method</code> - 엄마 팩 좀 줘. =&gt; 엄마라는 상위클래스가 있고 그 안에 어떤 행위를 할 수 있는 함수가 정의되어 있고 자식클래스(나)는 그 행위함수를 오버라이딩해서 팩을 요청하도록 수정하여 엄마한테 요청  </p>
<ul>
<li>상위클래스에서 인터페이스를 정의하고 하위클래스에서 인스턴스를 생성</li>
<li>상위클래스에서는 인스턴스를 만드는 방법만 정의하고 하위클래스에서 그 데이터의 생성과 조작하는 함수를 오버라이딩해서 분리하는 것</li>
</ul>
</li>
<li><p><code>Abstact Factory</code> = &gt;abstract가 추상클래스를 상속받는 메서드니깐 말 그대로 비슷한 객체들의 조합인 인터페이스를 만든다고 생각</p>
<ul>
<li>구체적 클래스에 의존하지 않고 서로 연관되거나 의존적인 객체들의 조합을 만드는 인터페이스 제공</li>
</ul>
</li>
<li><p><code>Singleton</code></p>
<ul>
<li>객체를 하나만 생성, 어디에서든 참조 가능하도록</li>
</ul>
</li>
</ul>
<h3 id="구조패턴-구-브데-퍼플-프록-컴-어">구조패턴 (구 브데 퍼플 프록 컴 어)</h3>
<ul>
<li><code>Bridge</code><ul>
<li>기능의 클래스 계층과 구현의 클래스 계층을 연결</li>
</ul>
</li>
<li><code>Decorator</code><ul>
<li>기존에 구현된 클래스에 필요한 기능을 추가해 나가는 패턴으로 객체의 결합을 통해 기능을 동적으로 확장</li>
</ul>
</li>
<li><code>Facade</code> <ul>
<li>복잡한 인터페이스에 대해 단순한 인터페이스를 제공함으로써 단순한(통합된) 인터페이스 제공</li>
</ul>
</li>
<li><code>Flyweight</code><ul>
<li>클래스의 경량화를 목적으로 다수의 객체가 생성될 경우 모두가 갖는 본질적인 요소를 클래스화하여 공유하는 여러개의 가상 인스턴스 제공하여 메모리 절감</li>
</ul>
</li>
<li><code>Proxy</code><ul>
<li>실체 객체에 대한 대리 객체로 정보은닉의 역할</li>
</ul>
</li>
<li><code>Composit</code><ul>
<li>객체들의 관계를 트리 구조로 구성하여 복합 객체와 단일 객체를 동일하게 취급</li>
</ul>
</li>
<li><code>Adapter</code><ul>
<li>기존에 생성된 클래스를 재사용할 수 있도록 중간에서 맞춰주기</li>
</ul>
</li>
</ul>
<h3 id="행위패턴행-미인이-탬옵-스테-비커-스트-메체">행위패턴(행 미인이 탬옵 스테 비커 스트 메체)</h3>
<ul>
<li><code>Mediator</code><ul>
<li>객체의 수가 많아지면 복잡하기 때문에 중재자를 두어 상호 작용의 유연한 변경을 지원</li>
</ul>
</li>
<li><code>Interpreter</code><ul>
<li>여러 형태의 언어 구문을 해석할 수 있도록 문법 자체를 캡슐화하여 사용</li>
</ul>
</li>
<li><code>Iterator</code><ul>
<li>컬렉션 구현 방법을 노출시키지 않으면서 그 집합체 안에 들어있는 모든 항목에 반복자를 사용하여 내부구조를 노출하지 않고 복잡 객체의 원소를 순차적으로 접근 가능하게 해줌</li>
</ul>
</li>
<li><code>Template Method</code> =&gt; 탬플릿 안에 특정 내용만 세부처리를 할 수 있게 도와줄게<ul>
<li>어떤 작업을 처리하는 일부분을 서브 클래스로 캡술화해 전체 일을 수행하는 구조는 바꾸지 않으면서 특정 단계에서 수행하는 내역을 바꾸는 것 즉, 상위 작업의 구조를 바꾸지 않으면서 서브 클래스로 작업의 일부분을 수행</li>
</ul>
</li>
<li><code>Observer</code> =&gt; 오저거바뀜<ul>
<li>객체의 상태가 바뀌면 의존하는 객체들에게 연락이 가고 자동의 내용 갱신</li>
</ul>
</li>
<li><code>State</code> =&gt; 상태<ul>
<li>객체의 상태에 따라 행위 내용을 변경</li>
</ul>
</li>
<li><code>Visitor</code> =&gt; 방문만 할게<ul>
<li>객체의 구조를 변경하지 않고 기능만 따로 추가하거나 확장할 때 사용</li>
</ul>
</li>
<li><code>Command</code><ul>
<li>실행될 기능을 캡슐화하여 재사용성이 높은 클래스를 설계하는 요구사항을 캡슐화</li>
</ul>
</li>
<li><code>Strategy</code><ul>
<li>춧상 클래스 같은 알고리즘을 각각 하나의 클래스로 캡슐화한 다음 필요할 때 서로 교환해서 사용할 수 있게 하는 패턴으로 행위 객체를 클래스로 캡슐화해 동적으로 행위를 자유롭게 변환</li>
</ul>
</li>
<li><code>Memento</code><ul>
<li>갹채를 이전상태로 복구, 작업 취소(Undo)의 요청 가능</li>
</ul>
</li>
<li><code>Chain of Responsibirity</code><ul>
<li>한 요청을 2개 이상의 객체에서 처리</li>
</ul>
</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[8장 - 서버 프로그램 구현]]></title>
            <link>https://velog.io/@ch980113_/8%EC%9E%A5-%EC%84%9C%EB%B2%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@ch980113_/8%EC%9E%A5-%EC%84%9C%EB%B2%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Fri, 12 Apr 2024 04:15:58 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="개발환경-구축">개발환경 구축</h2>
</blockquote>
<ul>
<li><code>웹서버</code><ul>
<li>HTTP를 통해 웹 브라우저에서 요청하는 문서를 전송해주는 프로그램</li>
<li>정적 컨텐츠</li>
<li>아파치, NginX</li>
</ul>
</li>
<li><code>WAS (웹어플리케이션 서버)</code><ul>
<li>동적 콘텐츠</li>
<li>톰캣</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="형상-관리-도구">형상 관리 도구</h2>
</blockquote>
<ul>
<li><code>RCS</code></li>
<li><code>CVS</code></li>
<li><code>GIT</code></li>
<li><code>SVN</code></li>
</ul>
<hr>
<blockquote>
<h2 id="소프트웨어-모듈-응집도">소프트웨어 모듈 응집도</h2>
</blockquote>
<ul>
<li><code>우논시절 통순기</code></li>
<li>응집도가 높아야 좋은 모델<ul>
<li><code>우연적</code> (젤 낮음)</li>
<li>논리적</li>
<li>시간적</li>
<li>절차적</li>
<li>통신적</li>
<li>순차적</li>
<li><code>기능적</code> (젤 높음)</li>
</ul>
</li>
</ul>
<blockquote>
<h2 id="소프트웨어-모듈-결합도">소프트웨어 모듈 결합도</h2>
</blockquote>
<ul>
<li><code>내공 외제 스자</code></li>
<li>결합도가 낮아야 좋은 모델<ul>
<li><code>내용</code> (젤 낮음)</li>
<li>공통</li>
<li>외부</li>
<li>제어</li>
<li>스템프</li>
<li><code>자료</code> (젤 높음)</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="모듈-테스트">모듈 테스트</h2>
</blockquote>
<ul>
<li><code>XUnit</code><ul>
<li>화이트박스 기법</li>
<li>Jaca, C++ 등 다양한 언어를 지원해주는 프레임워크</li>
<li>종류<ul>
<li><code>JUnit</code><ul>
<li>자바 언어용</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[5장 - 인터페이스 구현]]></title>
            <link>https://velog.io/@ch980113_/5%EC%9E%A5-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@ch980113_/5%EC%9E%A5-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 11 Apr 2024 10:57:49 GMT</pubDate>
            <description><![CDATA[<h1 id="인터페이스-기능-구현">인터페이스 기능 구현</h1>
<h2 id="json">JSON</h2>
<ul>
<li>키-쌍 값으로 이루어짐</li>
<li>인간이 읽을 수 있는 텍스트 사용</li>
<li>AJAX에서 사용</li>
<li>XML 대체</li>
</ul>
<h2 id="xml">XML</h2>
<ul>
<li>HTML의 단점을 보안한 인터넷 언어</li>
<li>직접 문서의 태그를 정의</li>
</ul>
<h2 id="ajax">AJAX</h2>
<ul>
<li>자바스크립트 사용</li>
<li>웹서버와 클라이언트 간 비동기적 XML 데이터를 주고 받음</li>
</ul>
<h2 id="rest">REST</h2>
<ul>
<li>웹과 같은 분산하이퍼미디어 환경에서 HTTP 메서드를 사용하여 주고받음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[4장 - 통합 구현]]></title>
            <link>https://velog.io/@ch980113_/4%EC%9E%A5-%ED%86%B5%ED%95%A9-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@ch980113_/4%EC%9E%A5-%ED%86%B5%ED%95%A9-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 11 Apr 2024 09:57:42 GMT</pubDate>
            <description><![CDATA[<h1 id="내외부-연계-모듈-구현">내외부 연계 모듈 구현</h1>
<h2 id="eai-방식">EAI 방식</h2>
<ul>
<li>기업에서 운영되는 서로 다른 플랫폼 간의 정보를 전달이 가능하도록 하는 솔루션</li>
<li>유형<ul>
<li><code>포인트 투 포인트</code><ul>
<li>1:1</li>
</ul>
</li>
<li><code>허브 앤 스코프</code><ul>
<li>중앙 집중형</li>
</ul>
</li>
<li><code>메시지 박스</code><ul>
<li>미들웨어</li>
</ul>
</li>
<li><code>하이브리드</code><h2 id="esb-방식">ESB 방식</h2>
</li>
</ul>
</li>
<li>기업에서 운영되는 서로 다른 플랫폼 간을 하나의 시스템으로 관리</li>
<li>미들웨어 중심의 느슨한 결합</li>
</ul>
<h2 id="웹서비스-방식">웹서비스 방식</h2>
<ul>
<li><code>WSDL</code><ul>
<li>웹 서비스명, 위치정보를 XML 형식으로 구현되어 있는 언어</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2장- 화면 설계]]></title>
            <link>https://velog.io/@ch980113_/2%EC%9E%A5-%ED%99%94%EB%A9%B4-%EC%84%A4%EA%B3%84</link>
            <guid>https://velog.io/@ch980113_/2%EC%9E%A5-%ED%99%94%EB%A9%B4-%EC%84%A4%EA%B3%84</guid>
            <pubDate>Thu, 11 Apr 2024 09:51:06 GMT</pubDate>
            <description><![CDATA[<h1 id="ui-요구사항">UI 요구사항</h1>
<blockquote>
<h2 id="ui-요구사항-확인">UI 요구사항 확인</h2>
</blockquote>
<ul>
<li>사용자와 시스템 사이에서 의사소통 할 수 있도록 고안된 매개체</li>
<li>UI, UX</li>
</ul>
<h3 id="ui-유형">UI 유형</h3>
<ul>
<li><code>CLI</code><ul>
<li>정적인, 명령어</li>
</ul>
</li>
<li><code>GUI</code><ul>
<li>그래픽</li>
</ul>
</li>
<li><code>NUI</code><ul>
<li>신체부위</li>
</ul>
</li>
<li><code>OUI</code><ul>
<li>유기적, 입출력 장치 </li>
</ul>
</li>
</ul>
<h3 id="ui-설계-원칙-직유학유">UI 설계 원칙 (직유학유)</h3>
<ul>
<li>직관성<ul>
<li>쉽게 이해하고 사용</li>
</ul>
</li>
<li>유효성<ul>
<li>목표 달성</li>
</ul>
</li>
<li>학습성<ul>
<li>쉽게 배우기</li>
</ul>
</li>
<li>유연성<ul>
<li>최대한 수용</li>
</ul>
</li>
</ul>
<h3 id="ui-화면-설계-구분">UI 화면 설계 구분</h3>
<ul>
<li><p><code>와이어프레임</code></p>
<ul>
<li>화면 단위의 레이아웃</li>
</ul>
</li>
<li><p><code>스토리보드</code></p>
<ul>
<li>서비스 구축을 위한 정보가 담긴 산출물</li>
</ul>
</li>
<li><p><code>프로토타입</code></p>
<ul>
<li>동적 효과</li>
<li>시물레이션 가능한 모형</li>
</ul>
<hr>
<h1 id="ui-설계">UI 설계</h1>
<blockquote>
<h3 id="uml">UML</h3>
</blockquote>
</li>
<li><p>모델링 기술과 방법론을 통합해서 만든 표준화 범용 모델링 언어</p>
</li>
</ul>
<h3 id="구성요소">구성요소</h3>
<ul>
<li>사물</li>
<li>관계</li>
<li>다이어그램</li>
</ul>
<blockquote>
<h3 id="uml-다이어그램">UML 다이어그램</h3>
</blockquote>
<h3 id="구조적-다이어그램--정적">구조적 다이어그램 = 정적</h3>
<ul>
<li><code>클래스</code><ul>
<li>클래스의 속성 및 연산과 클래스</li>
<li>연관, 의존, 일반화, 실체화, 포함 관계</li>
</ul>
</li>
<li><code>객체</code><ul>
<li>연관된 모든 인스턴스</li>
</ul>
</li>
<li><code>컴포넌트</code><ul>
<li>의존 관계</li>
</ul>
</li>
<li><code>배치</code><ul>
<li>컴포넌트 사이의 종속성</li>
</ul>
</li>
<li><code>복합체 구조</code><ul>
<li>복합 구조를 갖는 경우 표현</li>
</ul>
</li>
<li><code>패키지</code><ul>
<li>클래스들을 그룹화</li>
<li>의존관계에는 <code>&lt;&lt;import&gt;&gt;</code>, <code>&lt;&lt;access&gt;&gt;</code>가 있음</li>
</ul>
</li>
</ul>
<h3 id="행위적-다이어그램--동적">행위적 다이어그램 = 동적</h3>
<ul>
<li><code>유스케이스</code><ul>
<li>사용자의 관점에서 표현</li>
</ul>
</li>
<li><code>시퀀스</code><ul>
<li>시간적 개념을 중심으로 메시지 흐름으로 표현</li>
<li>객체는 사각형 안에 밑줄로 표시</li>
<li>생명선은 점선</li>
</ul>
</li>
<li><code>커뮤니케이션</code><ul>
<li>주고받는 메시지를 표현</li>
<li>객체명 : 클래스명으로 기제</li>
</ul>
</li>
<li><code>상태</code><ul>
<li>상태변화</li>
</ul>
</li>
<li><code>활동</code><ul>
<li>어떤 기능을 수행하는지 표현</li>
</ul>
</li>
<li><code>타이밍</code><ul>
<li>객체 상태 변화와 시간 제약을 명시적 표현</li>
</ul>
</li>
</ul>
<hr>
<h3 id="uml-스트레오-타입">UML 스트레오 타입</h3>
<ul>
<li><code>&lt;&lt;include&gt;&gt;</code><ul>
<li>반드시 포함</li>
</ul>
</li>
<li><code>&lt;&lt;extend&gt;&gt;</code><ul>
<li>있고, 않을 수도</li>
</ul>
</li>
<li><code>&lt;&lt;interface&gt;&gt;</code><ul>
<li>모든 메서드가 추상메서드</li>
</ul>
</li>
<li><code>&lt;&lt;entity&gt;&gt;</code><ul>
<li>정보나 연관된 행위를 형상화라는 클래스</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[3장 - 데이터 입출력 구현]]></title>
            <link>https://velog.io/@ch980113_/3%EC%9E%A5-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@ch980113_/3%EC%9E%A5-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 11 Apr 2024 09:44:52 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터-저장소">데이터 저장소</h1>
<blockquote>
<h2 id="데이터-모델">데이터 모델</h2>
</blockquote>
<h3 id="데이터-모델-절차-요개논물">데이터 모델 절차 (요개논물)</h3>
<ul>
<li><code>요구사항 분석</code></li>
<li><code>개념적 설계</code><ul>
<li>트랜잭션을 모델링</li>
<li><strong>ERD</strong> </li>
</ul>
</li>
<li><code>논리적 설계</code><ul>
<li>트랜잭션의 인터페이스 설계</li>
<li>스키마의 평가 및 정제</li>
</ul>
</li>
<li><code>물리적 설계</code><ul>
<li>반 정규화</li>
<li>접근경로 설계</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="관계-데이터-모델">관계 데이터 모델</h2>
</blockquote>
<h3 id="관계-데이터-모델의-구성요소">관계 데이터 모델의 구성요소</h3>
<ul>
<li><code>릴레이션</code><ul>
<li>행과 열로 구성된 테이블</li>
</ul>
</li>
<li><code>튜플</code><ul>
<li>릴레이션의 행</li>
<li>튜플의 개수 : 카디널리티</li>
</ul>
</li>
<li><code>속성</code><ul>
<li>릴레이션의 열</li>
<li>속성의 개수 : 차수, 애트리뷰트</li>
</ul>
</li>
<li><code>스키마 = 릴레이션 스키마</code><ul>
<li>데이터베이스의 구조 등의 정보를 담고있는 기본적인 구조</li>
</ul>
</li>
<li><code>인스턴스 = 릴레이션 인스턴스</code><ul>
<li>실제 저장된 데이터의 집합</li>
</ul>
</li>
</ul>
<h3 id="관계-대수">관계 대수</h3>
<ul>
<li><p>관계형 데이터베이스에서 원하는 정보와 그 정보를 어떻게 유도하는가를 기술</p>
</li>
<li><p>일반 집합 연산자</p>
<ul>
<li><code>합집합</code><ul>
<li><code>U</code></li>
</ul>
</li>
<li><code>교집합</code><ul>
<li><code>거꾸로 U</code></li>
</ul>
</li>
<li><code>차집합</code><ul>
<li><code>-</code></li>
</ul>
</li>
<li><code>카티션 프로덕트</code><ul>
<li><code>X</code></li>
</ul>
</li>
</ul>
</li>
<li><p>순수 관계 연산자</p>
<ul>
<li><p><code>셀렉트 (σ)</code> = SQL에서 <strong>SELECT</strong> 담당</p>
<ul>
<li>릴레이션에서 조건을 만족하는 튜플 반환
<img src="https://velog.velcdn.com/images/ch980113_/post/0960e638-8203-46f3-8894-417de1e22a52/image.png" alt=""></li>
</ul>
</li>
<li><p><code>프로젝트 (π)</code> = SQL에서 <strong>WHERE</strong> 조건 담당</p>
<ul>
<li>주어진 속성들의 값으로만 구성된 튜플 반환
<img src="https://velog.velcdn.com/images/ch980113_/post/b0de3f12-2644-482b-8b00-a99c5db52b17/image.png" alt=""></li>
</ul>
</li>
<li><p><code>조인 (▷◁)</code></p>
<ul>
<li>공통 속성을 이용해 연결</li>
</ul>
</li>
<li><p><code>디비전 (÷)</code></p>
<ul>
<li>관련있는 튜플 반환</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="erd">ERD</h3>
<ul>
<li>피터챈 모델 </li>
<li>현실 세계에 존재하는 데이터와 그들 간의 관계를 사람이 이해할 수 있는 형태로 명확하게 표현하기 위한 모델</li>
<li>개체, 속성, 관계</li>
</ul>
<h4 id="erd-기호">ERD 기호</h4>
<p> <img src="https://velog.velcdn.com/images/ch980113_/post/64398d13-6cf3-492b-930c-2be2ebf5fd91/image.png" alt=""></p>
<h3 id="정규화">정규화</h3>
<ul>
<li>단계 (원부 이걸 다조)<ul>
<li><code>1정규형(1NF)</code><ul>
<li>원자값으로 구성</li>
</ul>
</li>
<li><code>2정규형</code><ul>
<li>부분 함수 종속 제거</li>
</ul>
</li>
<li><code>3정규형</code><ul>
<li>이행함수 종속 제거</li>
</ul>
</li>
<li><code>BCNF</code><ul>
<li>결정자 후보 키가 아닌 함수 종속 제거</li>
</ul>
</li>
<li><code>4정규형</code><ul>
<li>다치(다중값) 종속 제거</li>
</ul>
</li>
<li><code>5정규형</code><ul>
<li>조인 종속 제거</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="이상현상">이상현상</h4>
<ul>
<li>데이터의 중복성으로 인해 릴레이션을 조작할 때 발생하는 현상
&lt;테이블&gt;
학번   &nbsp;&nbsp;&nbsp;    이름   &nbsp;&nbsp;  교수번호     &nbsp;&nbsp;&nbsp;교수이름 
2010 &nbsp;&nbsp;홍길동&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 김 교수
2011 &nbsp;&nbsp;김영희 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;이 교수
2012 &nbsp;&nbsp;이철수 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?<ul>
<li><code>삽입이상</code><ul>
<li>2012학번을 가진 이철수라는 학생이름을 등록할 경우 교수가 지정되어 있지않으면 삽입 불가 </li>
</ul>
</li>
<li><code>삭제이상</code><ul>
<li>&#39;이교수&#39;라는 교수가 퇴사할 경우 김영희의 정보도 같이 삭제</li>
</ul>
</li>
<li><code>갱신이상</code><ul>
<li>홍길동의 지도교수를 이 교수로 변경할 경우 중복이 되어 모순이 일어난다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="함수-종속">함수 종속</h4>
<ul>
<li><code>부분함수 종속(Partial)</code></li>
<li><code>완전함수 종속(Full)</code></li>
<li><code>이행함수 종속(Transitive)</code></li>
</ul>
<h3 id="반정규화">반정규화</h3>
<ul>
<li>정규화된 엔티티 등에 대해 성능 향상과 개발 운영의 단순화를 위해 중복, 통합 등을 수행</li>
</ul>
<hr>
<blockquote>
<h2 id="물리-데이터-모델">물리 데이터 모델</h2>
</blockquote>
<h3 id="데이터베이스-무결성">데이터베이스 무결성</h3>
<ul>
<li>데이터베이스에 저장된 데이터 값과 그것이 표현하는 현실 세계 값이 일치하는 성질</li>
<li>무결성 종류 (개참속시키)<ul>
<li><code>개체 무결성</code><ul>
<li>기본키는 널값이 안됨</li>
</ul>
</li>
<li><code>참조 무결성</code><ul>
<li>외래키가 참조하는 키는 기본키값이거나 널값</li>
</ul>
</li>
<li><code>속성 무결성</code><ul>
<li>규칙에 준수</li>
</ul>
</li>
<li><code>사용자 정의 무결성</code></li>
<li><code>키 무결성</code></li>
</ul>
</li>
</ul>
<h3 id="키">키</h3>
<ul>
<li>유일성<ul>
<li>유일하게 구분</li>
</ul>
</li>
<li>최소성 <ul>
<li>최소한의 속성으로 구별</li>
</ul>
</li>
<li>종류 <ul>
<li><code>기본 키</code></li>
<li><code>후보 키</code></li>
<li><code>슈퍼 키</code><ul>
<li>유일성은 만족, 최소성은 불만족</li>
</ul>
</li>
<li><code>외래 키</code><ul>
<li>기본 키로 이용되는 키</li>
<li>무결성</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="파티셔닝">파티셔닝</h3>
<ul>
<li><code>레인지 파티셔닝</code><ul>
<li>연속적인 숫자나 날짜를 기준</li>
</ul>
</li>
<li><code>해시 파티셔닝</code><ul>
<li>해시함수 값</li>
</ul>
</li>
<li><code>리스트 파티셔닝</code><ul>
<li>특정 파티션에 저장될 데이터</li>
</ul>
</li>
<li><code>라운드로빈</code><ul>
<li>라운드로빈 회전</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[10장 - 애플리케이션 테스트 관리]]></title>
            <link>https://velog.io/@ch980113_/10%EC%9E%A5-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@ch980113_/10%EC%9E%A5-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Wed, 10 Apr 2024 15:42:42 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="소프트웨어-테스트의-이해">소프트웨어 테스트의 이해</h2>
</blockquote>
<h3 id="소프트웨어-테스트의-기본원칙">소프트웨어 테스트의 기본원칙</h3>
<ol>
<li><p>소프트웨어 테스트 원리</p>
<ul>
<li>결함 존재 증명</li>
<li>완벽 테스팅은 불가능</li>
<li>초기 집중</li>
<li>결함 집중</li>
<li><code>살충제 패러독스</code><ul>
<li>동일한 테스트에 대한 반복적 테스트는 새로운 버그를 찾지 못한다.</li>
</ul>
</li>
<li>정황 의존성</li>
<li>오류-부재의 원인<br/>
</li>
</ul>
</li>
<li><p>소프트웨어 테스트 산출물</p>
<ul>
<li><code>테스트 계획서</code></li>
<li><code>테스트 베이시스</code><ul>
<li>테스트 설계를 위한 기준이 되는 문서</li>
</ul>
</li>
<li><code>테스트 케이스</code><ul>
<li>테스트를 위한 설계 산출물</li>
</ul>
</li>
<li><code>테스트 슈트</code><ul>
<li>실행환경에 따라 구분</li>
</ul>
</li>
<li><code>테스트 시나리오</code><ul>
<li>테스트가 필요한 상황을 작성한 문서</li>
</ul>
</li>
<li><code>테스트 스크립트</code><ul>
<li>테스트 실행 순서를 작성</li>
</ul>
</li>
<li><code>테스트 결과서</code></li>
</ul>
</li>
</ol>
<hr>
<blockquote>
<h2 id="소프트웨어-테스트-유형">소프트웨어 테스트 유형</h2>
</blockquote>
<h3 id="테스트-기법에-따른-분류">테스트 기법에 따른 분류</h3>
<ol>
<li><p><code>정적 테스트</code></p>
<ul>
<li>실행하지 않고 구조를 분석</li>
<li>리뷰<ul>
<li><code>동료검토</code><ul>
<li>2~3명이 0진행</li>
</ul>
</li>
<li><code>인스펙션</code><ul>
<li>전문가가 검사</li>
</ul>
</li>
<li><code>워크스루</code><ul>
<li>회의 전에 배포하여 사전 검토</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p><code>동적 테스트</code></p>
<ul>
<li>실행하여 검출</li>
<li>화이트박스, 블랙박스 테스트</li>
</ul>
<p><code>2-1) 화이트박스 테스트 = 구조기반 테스트</code></p>
<ul>
<li><p>응용프로그램의 내부 구조와 동작을 검사</p>
</li>
<li><p>소스 코드의 모든 문장을 한 번 이상 수행</p>
<p>a. <code>구문 커버리지 (Statement)</code></p>
<ul>
<li>프로그램 내 모든 명령문을 적어도 한 번 이상 수행</li>
<li>조건문 결과와 관계없이 구문 실행 개수로 수행</li>
</ul>
<p>b. <code>결정 커버리지 = 선택/분기 커버리지 (Decision/Branch)</code></p>
<ul>
<li>각 분기의 결정 포인트 내의 전체 조건식이 적어도 한 번은 참과 거짓의 결과를 수행</li>
</ul>
<p>c. <code>조건 커버리지 (Condition)</code></p>
<ul>
<li>각 분기의 결정 포인트 내의 개별 조건식이 참 한번, 거짓 한번의 결과가 되도록 수행</li>
</ul>
<p>d. <code>기본경로 커버리지 (Base 0Path)</code></p>
<ul>
<li>수행 가능한 모든 경로를 다 테스트</li>
<li>맥케이브의 순환복잡도</li>
</ul>
</li>
</ul>
<p><code>2-2) 블랙박스 테스트</code></p>
<ul>
<li><p>외부 사용자의 요구사항 명세를 보면서 수행</p>
<p>a. <code>동등분할 테스트 = 동치/균둥 분할 테스트 (Equivalence Partitioninh)</code></p>
<ul>
<li>도메인 별로 유효값/무효값을 그룹핑하여 대푯값 테스트 케이스를 도출</li>
</ul>
<p>b. <code>경곗값 분석 테스트 (Boundary Value Analysis)</code></p>
<ul>
<li>최솟값 바로 위, 최대치 바로 아래 등 경곗값을 포함하여 설계</li>
</ul>
<p>c. <code>결정 테이블 테스트 (Decision Table)</code></p>
<ul>
<li>테이블 형태로 나열 후 조합하여 테스트</li>
</ul>
<p>d. <code>상태전이 테스트 (State Transition)</code></p>
<ul>
<li>객체의 상태를 구분</li>
<li>다른 상태로 전이되는 경우의 수를 테스트</li>
</ul>
<p>e. <code>유스케이스 테스트 (Use Case)</code></p>
<ul>
<li>유스케이스로 모델링</li>
</ul>
<p>f. <code>분류트리 테스트 (Classification Tree Method)</code></p>
<ul>
<li>트리구조로 분석 및 표현</li>
</ul>
<p>g. <code>페어와이즈 테스트 (Pairwise)</code></p>
<ul>
<li>테스트 데이터값들을 최소 한번씩 조합</li>
<li>커버해야 할 범위를 적은 양의 테스트로 구성하기 위함</li>
</ul>
<p>h. <code>원인-결과 그래프 테스트 (Cause-Effect Graph)</code></p>
<ul>
<li>그래프를 활용하여 효용성이 높은 테스트 케이스 선정</li>
</ul>
<p>i. <code>비교 테스트 (Comparison)</code></p>
<ul>
<li>동일한 결과가 나오는지 비교하여 테스트</li>
</ul>
<p>j. <code>오류추정 테스트 (Error guessing)</code></p>
<ul>
<li>실수를 추정하여 결함이 검출되도록 설계</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="테스트-시각에-따른-분류">테스트 시각에 따른 분류</h3>
<ul>
<li>검증<ul>
<li>개발 과정을 테스트</li>
<li>개발자 혹은 시험자의 시각</li>
</ul>
</li>
<li>확인<ul>
<li>사용자 시각</li>
<li>결과를 테스트하여 제대로 동작하는지 확인</li>
</ul>
</li>
</ul>
<h3 id="테스트-목적에-따른-분류">테스트 목적에 따른 분류</h3>
<ul>
<li>회복 테스트<ul>
<li>고의로 실패를 유도하여 정상적 복귀 여부를 테스트</li>
</ul>
</li>
<li>안전 테스트<ul>
<li>보안적인 결함을미리 점검</li>
</ul>
</li>
<li>성능 테스트<ul>
<li>반응하는 속도 등 테스트</li>
</ul>
</li>
<li>구조 테스트<ul>
<li>복잡도를 평가</li>
</ul>
</li>
<li>회귀 테스트<ul>
<li>일종의 반복 테스트</li>
</ul>
</li>
<li>병행 테스트<ul>
<li>변경된 시스템과 기존 시스템에 동일한 데이터 입력 후  결과 비교</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="테스트-오라클">테스트 오라클</h2>
</blockquote>
<ul>
<li>결과가 참인지 거짓인지를 판단하기 위해 사전에 정의된 참값을 입력하여 비교</li>
<li>종류 (참샘휴일) -&gt; 참새가 휴일에 쉰다.<ul>
<li><code>참 오라클</code><ul>
<li>모든 입력 값에 대하여 기대하는 결과를 생성함</li>
<li>발생된 오류를 모두 검출 가능</li>
</ul>
</li>
<li><code>샘플링 오라클</code><ul>
<li>특정한 몇개의 입력값에 대해서만 기대하는 결과 제공</li>
</ul>
</li>
<li><code>휴리스틱 오라클</code><ul>
<li>샘플링 오라클을 개선<ul>
<li>특정 입력값에 대해 올바른 결과 제공</li>
<li>나머지 값들은 휴라스틱(추정) 값 처리</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="애플리케이션-테스트-시나리오-작성">애플리케이션 테스트 시나리오 작성</h2>
</blockquote>
<h3 id="테스트-레벨">테스트 레벨</h3>
<ul>
<li><p><code>V모델</code></p>
<ul>
<li>개발자 관점 + 사용자 관점에서의 최종 산출물에 대한 확인을 지원하기 위한 모델</li>
</ul>
</li>
<li><p><code>테스트 레벨</code></p>
<ul>
<li><code>단위테스트</code><ul>
<li>사용자 요구사항에 대한 모듈, 컴포넌트에 초점</li>
</ul>
</li>
<li><code>통합테스트</code><ul>
<li>단위테스트를 통과후 테스트</li>
<li>인터페이스 관련 오류</li>
</ul>
</li>
<li><code>시스템테스트</code><ul>
<li>통합된 시스템의 기능 점검</li>
</ul>
</li>
<li><code>인수테스트</code><ul>
<li><code>알파테스트</code><ul>
<li>개발자 환경에서 통제된 환경</li>
</ul>
</li>
<li><code>베타테스트</code><ul>
<li>실제환경에서 일정 수의 사용자에게 피드백</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[9장 - SW 개발 보안 구축 - 2장]]></title>
            <link>https://velog.io/@ch980113_/9%EC%9E%A5-SW-%EA%B0%9C%EB%B0%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@ch980113_/9%EC%9E%A5-SW-%EA%B0%9C%EB%B0%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Wed, 10 Apr 2024 09:06:19 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="입력-데이터-검증-및-표현">입력 데이터 검증 및 표현</h2>
</blockquote>
<h3 id="입력-데이터-검증-및-표현-취약점">입력 데이터 검증 및 표현 취약점</h3>
<ul>
<li><code>XSS</code><ul>
<li>검증되지 않은 웹페이지가 전송되는 경우, 부적절한 스크립트가 실행</li>
</ul>
</li>
<li><code>사이트 간 요청 위조 (CSRF)</code><ul>
<li>사용자 의지와 상관없이 공격자가 의도한 행위를 요청하게 되는 공격</li>
</ul>
</li>
<li><code>SQL 삽입</code><ul>
<li>응용 프로그램의 취약점을 이용<ul>
<li>악의적인 SQL 구문을 삽입</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="시스템-보안-구현">시스템 보안 구현</h2>
</blockquote>
<h3 id="리눅스-주요-로그-파일">리눅스 주요 로그 파일</h3>
<ul>
<li><code>wtmp</code><ul>
<li>사용자 로그인/로그아웃 정보</li>
<li><strong>last</strong> 명령어</li>
</ul>
</li>
</ul>
<h3 id="보안-솔루션">보안 솔루션</h3>
<ul>
<li><code>방화벽</code><ul>
<li>기업 내/외부 간 트래픽을 모니터링</li>
</ul>
</li>
<li><code>웹 방화벽 (WAF)</code><ul>
<li>XSS, SQL인젝션을 탐지하고 방지</li>
</ul>
</li>
<li><code>네트워크 접근 제어 (NAC)</code><ul>
<li>바이러스나 웜으로부터 방지</li>
</ul>
</li>
<li><code>가상사설망 (VPN)</code><ul>
<li>마치 전용망을 사용하는 효과</li>
<li>SSL 방식과 IPSec 방식</li>
</ul>
</li>
<li><code>SIEM</code><ul>
<li>위협에 대응하는 보안 관제 솔루션</li>
<li>머신러닝 기술을 이용하여 대량의 로그분석</li>
</ul>
</li>
<li><code>ESM</code><ul>
<li>각종 이벤트 및 로그를 통합해서 관리 </li>
<li>서로 다른 기종의 보안 장비들을 모니터링하여 통합 관리</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="sw-개발-보안-테스트와-결함-관리">SW 개발 보안 테스트와 결함 관리</h2>
</blockquote>
<ul>
<li><code>정적 분석</code><ul>
<li>SW를 실행하지 않고 보안 약점 분석</li>
</ul>
</li>
<li><code>동적 분석</code><ul>
<li>실행 단계</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="비즈니스-연속성-계획bcp">비즈니스 연속성 계획(BCP)</h2>
</blockquote>
<ul>
<li>각종 재해, 재난으로부터 위기관리를 기반으로 재해복구, 비상계획을 통해 비스니스 연속성을 보장하는 체계</li>
</ul>
<h3 id="비즈니스-연속성-계획-관련-주요-용어">비즈니스 연속성 계획 관련 주요 용어</h3>
<ul>
<li><code>BIA</code><ul>
<li>BCP를 구축하기 위한 비즈니스 영향 분석</li>
</ul>
</li>
<li><code>RTO</code><ul>
<li>다시 가동될 때까지의 시간</li>
</ul>
</li>
<li><code>RPO</code><ul>
<li>데이터 손실 허용 시점</li>
</ul>
</li>
<li><code>DRS</code><ul>
<li>재해복구센터</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="보안-용어">보안 용어</h2>
</blockquote>
<h3 id="보안-공격-관련-용어">보안 <strong>공격</strong> 관련 용어</h3>
<ul>
<li><code>드라이브 바이 다운로드</code><ul>
<li>악성 스크립트를 설치하고 접속시 사용자 동의없이 실행되어 감염</li>
</ul>
</li>
<li><code>워터링 홀</code><ul>
<li>자주 방문하는 페이지에 악성 코드를 심거나, URL로 유인하여 감염</li>
</ul>
</li>
<li><code>하트블라드</code><ul>
<li>하트비트 </li>
</ul>
</li>
<li><code>스피어피싱</code><ul>
<li>파일 클릭하도록 유도하여 감염</li>
</ul>
</li>
<li><code>스미싱</code><ul>
<li>문자메시지 피싱</li>
</ul>
</li>
<li><code>큐싱</code><ul>
<li>큐알코드 피싱</li>
</ul>
</li>
<li><code>봇넷</code><ul>
<li>악성 프로그램에 감염되어 다수의 컴퓨터들이 네트워크로 연결된 형태</li>
</ul>
</li>
<li><code>제로데이 공격</code><ul>
<li>대응책이 발표되기 전 공격이 이루어지는 것</li>
</ul>
</li>
<li><code>바이러스</code><ul>
<li>자가 증식 불가</li>
</ul>
</li>
<li><code>웜</code><ul>
<li>자가 증식 가능</li>
</ul>
</li>
<li><code>악성 봇</code><ul>
<li>공격 당해 원격으로 제어 0당하는 프로그램</li>
</ul>
</li>
<li><code>랜섬웨어</code><ul>
<li>몸 값을 요구</li>
</ul>
</li>
<li><code>이블 트윈</code><ul>
<li>무선 와이파이 피싱 기법</li>
</ul>
</li>
<li><code>사회공학</code><ul>
<li>사람들의 심리와 행동을 이용</li>
</ul>
</li>
<li><code>타이포스쿼팅</code><ul>
<li>URL 하이재킹</li>
<li>네이버를 검색했는데 네이바가 나와서 해킹하는 방법</li>
<li>유사한 URL을 사용</li>
</ul>
</li>
</ul>
<h3 id="주요-시스템-보안-공격-기법">주요 시스템 보안 <strong>공격</strong> 기법</h3>
<ul>
<li><code>키로거 공격</code><ul>
<li>키보드 움직임</li>
</ul>
</li>
</ul>
<h3 id="보안-공격-대응-관련-용어">보안 공격 <strong>대응</strong> 관련 용어</h3>
<ul>
<li><code>ISMS</code><ul>
<li>정보 자산을 관리, 보호하기 위한 종합적인 체계</li>
</ul>
</li>
<li><code>트러스트존</code><ul>
<li>ARM사에서 개발</li>
<li>프로세스 안에 독립적인 보안 구역을 두어 중요한 정보는 따로 보관</li>
</ul>
</li>
<li><code>TKIP</code><ul>
<li>임시 키 무결성 프로토콜</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[7장 - SQL 응용]]></title>
            <link>https://velog.io/@ch980113_/7%EC%9E%A5-SQL-%EC%9D%91%EC%9A%A9</link>
            <guid>https://velog.io/@ch980113_/7%EC%9E%A5-SQL-%EC%9D%91%EC%9A%A9</guid>
            <pubDate>Wed, 10 Apr 2024 02:39:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="데이터베이스-기본">데이터베이스 기본</h1>
</blockquote>
<h2 id="트랜잭션">트랜잭션</h2>
<ul>
<li>인가받지 않은 사용자로부터 데이터를 보장받기 위해 DBMS가 가져야 할 특성</li>
</ul>
<h3 id="트랜잭션-특성">트랜잭션 특성</h3>
<ul>
<li><code>원자성</code><ul>
<li>연산 전체가 성공 또는 실패가 되어야 함</li>
</ul>
</li>
<li><code>일관성</code><ul>
<li>수행 전후 상태가 같아야 함</li>
</ul>
</li>
<li><code>격리성</code><ul>
<li>서로 영향을 미쳐서는 안됨</li>
</ul>
</li>
<li><code>영속성</code><ul>
<li>영속적으로 저장되어야 함</li>
</ul>
</li>
</ul>
<h3 id="병행제어">병행제어</h3>
<ul>
<li>다수 사용자 환경에서 여러 트랜잭션을 수행 할때 일관성 유지를 위해 상호작용을 제어하는 기법</li>
</ul>
<h4 id="병행제어-기법-종류">병행제어 기법 종류</h4>
<ul>
<li><code>로킹</code><ul>
<li>하나의 트랜잭션이 실행되는 동안 다른 트랜잭션이 접근하지 못하도록 상호배제 기능</li>
</ul>
</li>
<li><code>타임스탬프 순서</code><ul>
<li>타임스탬프를 부여하여 부여된 시간에 따라 수행</li>
</ul>
</li>
</ul>
<h3 id="회복기법">회복기법</h3>
<ul>
<li>트랜잭션 도중 장애로 인해 손상된부분을 정상 상태로 복구</li>
<li><code>REDO</code><ul>
<li>트랜잭션 시작과 완료에 대한 기록이 있음</li>
</ul>
</li>
<li><code>UNDO</code><ul>
<li>트랜잭션 시작만 있고 완료에 대한 기록이 없음</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="ddl">DDL</h2>
</blockquote>
<ul>
<li>데이터 정의어</li>
<li>생성, 변경, 삭제, 이름 변경</li>
</ul>
<h3 id="ddl-대상">DDL 대상</h3>
<ol>
<li><p>스키마</p>
<ul>
<li>데이터베이스의 구조, 제약조건을 담고 있음</li>
<li>외부스키마<ul>
<li>사용자, 개발자 관점</li>
</ul>
</li>
<li>개념스키마<ul>
<li>전체적인 논리적 구조</li>
</ul>
</li>
<li>내부스키마<ul>
<li>물리적 저장 장치의 관점</li>
</ul>
</li>
</ul>
</li>
<li><p>테이블</p>
<ul>
<li>데이터를 저장하는 필드로 구성된 집합 = 릴레이션, 엔티티</li>
<li><code>튜플/ 행</code><ul>
<li>테이블 내의 행</li>
<li>테이블에서 동일 값 가질 수 없음</li>
<li>튜플의 개수 : <code>카디널리티</code>(특정 데이터 집단의 유니크한 값의 개수)</li>
</ul>
</li>
<li><code>속성/ 열</code><ul>
<li>열의 개수 : <code>차수, 디그리</code></li>
</ul>
</li>
<li><code>도메인</code><ul>
<li>하나의 속성이 취할 수 있는 같은 타입의 원자값들의 집합</li>
</ul>
</li>
</ul>
</li>
<li><p>뷰</p>
<ul>
<li>논리 테이블</li>
<li>사용자 관점에서는 테이블과 동일</li>
</ul>
</li>
<li><p>인덱스</p>
<ul>
<li>검색 연산을 최적화</li>
<li>기본키는 자동으로 인덱스 생성<br/>

</li>
</ul>
</li>
</ol>
<h3 id="table-관련-ddl-명령어">TABLE 관련 DDL 명령어</h3>
<pre><code> CREATE    생성
 ALTER     수정
 DROP      삭제
 TRUNCATE  내용삭제</code></pre><ol>
<li><p><code>CREATE TABLE</code></p>
<ul>
<li><p>테이블을 생성하는 명령어</p>
<pre><code class="language-sql">CREATE TABLE 사원
(
사번 VARCHARE(10) NOT NULL,
부서번호 VARCHARE(20),
생년월일 DATE NOT NULL,
성별 CHAR(1),
PRIMARY KEY(사번),
FOREIGN KEY(부서번호) REFERENCES 부서(부서코드),
CONSTRAINT 성별제약 CHECK 성별 IN(&#39;M&#39;,&#39;F&#39;)
);</code></pre>
<ul>
<li><code>사원테이블</code>의 VARCHARE(10)타입인 <code>사번컬럼</code>은 NULL이 아니고,</li>
<li>VARCHARE(20)타입인 <code>부서번호칼럼</code>이 있고,</li>
<li>DATE 타입인 <code>생년월일칼럼</code>은 NULL이 아니어야 하고,</li>
<li>그 중 <code>사번컬럼</code>은 기본키이고,</li>
<li><code>부서번호칼럼</code>은 <code>부서테이블</code>의 <code>부서코드칼럼</code>을 참조하고,</li>
<li><code>성별컬럼</code>은 M과 F값만 허용.</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li><p><code>ALTER TABLE</code></p>
<ul>
<li>테이블을 수정</li>
<li>칼럼 추가 문법<pre><code class="language-sql">ALTER TABLE 테이블명 ADD 칼럼명 데이터타입 [제약조건];</code></pre>
</li>
<li>칼럼 수정 문법<pre><code class="language-sql">ALTER TABLE 테이블명 ALTER 칼럼명 데이터타입 [제약조건];</code></pre>
</li>
<li>칼럼 삭제 문법<pre><code class="language-sql">ALTER TABLE 테이블명 DROP COLUMN 칼럼명;</code></pre>
</li>
</ul>
</li>
<li><p><code>DROP TABLE</code></p>
<ul>
<li>테이블을 삭제<pre><code class="language-sql">DROP TABLE 테이블명 [CASCADE | RESTRICT];</code></pre>
</li>
<li><code>CASCADE</code><ul>
<li>참조하는 테이블까지 제거</li>
</ul>
</li>
<li><code>RESTRICT</code><ul>
<li>다른 테이블이 삭제할 테이블을 참조 중이면 제거하지 않기</li>
</ul>
</li>
</ul>
</li>
<li><p><code>TRUNCATE TABLE</code></p>
<ul>
<li>테이블 내의 데이터들을 모두 삭제<pre><code class="language-sql">TRUNCATE TABLE 테이블명;</code></pre>
<br/>

</li>
</ul>
</li>
</ol>
<h3 id="view-관련-ddl-명령어">VIEW 관련 DDL 명령어</h3>
<ol>
<li><code>CREATE VIEW</code><ul>
<li>뷰를 생성<pre><code class="language-sql">CREATE VIEW 뷰이름 AS</code></pre>
</li>
</ul>
</li>
<li><code>DROP VIEW</code><ul>
<li>뷰를 삭제<pre><code class="language-sql">DROP VIEW 뷰이름;</code></pre>
<br/>

</li>
</ul>
</li>
</ol>
<h3 id="index-관련-ddl-명령어">INDEX 관련 DDL 명령어</h3>
<ol>
<li><code>CREATE INDEX</code><ul>
<li>인덱스를 생성<pre><code class="language-sql">CREATE [UNIQUE] INDEX 인덱스명 ON 테이블명(칼럼명1, 칼럼명2);</code></pre>
</li>
</ul>
</li>
<li><code>ALTER INDEX</code><ul>
<li>인덱스를 수정</li>
</ul>
</li>
<li><code>DROP INDEX</code><ul>
<li>인덱스를 삭제<pre><code class="language-sql">DROP INDEX 인덱스명;</code></pre>
</li>
</ul>
</li>
</ol>
<hr>
<h2 id="dml">DML</h2>
<ul>
<li><p>데이터 조작어</p>
<pre><code>SELECT  조회
 INSERT  삽입
 UPDATE  갱신
 DELETE  삭제</code></pre></li>
</ul>
<h3 id="select-명령어">SELECT 명령어</h3>
<ol>
<li>SELECT 명령어 <ul>
<li>데이터의 내용을 조회<pre><code class="language-sql">SELECT [ALL | DISTINCT] 속성명1, 속성명2,
FROM 테이블명
WHERE 조건
GROUP BY 속성명1
HAVING 그룹조건
ORDER BY 속성 [ASC | DESC];</code></pre>
</li>
<li>SELECT 조건<ul>
<li><code>ALL = *</code><ul>
<li>모든 튜플을 검색</li>
</ul>
</li>
<li><code>DISTINCT</code><ul>
<li>증복된 속성이 있는 경우 그 중 첫 번째 한개만 검색</li>
</ul>
</li>
</ul>
</li>
<li>WHERE 조건<ul>
<li>LIKE 연산자<ul>
<li><code>%</code><ul>
<li>글자수 제한 없음</li>
<li>&#39;박%&#39;이면 박으로 시작하는 글자수 제한없이 와야 함</li>
</ul>
</li>
<li><code>_</code><ul>
<li>특정위치에 있어야 함</li>
<li>&#39;박_&#39; 이면 박 뒤에 무조건 1글자가 있어야 함</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li>조인</li>
</ol>
<ul>
<li>두개 이상의 테이블을 연결하여 테이터 검색<ul>
<li><code>내부조인</code><ul>
<li>조인조건에 맞는것끼리 묶어줌<pre><code class="language-sql">SELECT A.칼럼1, A.칼럼2,
    B.칼럼1, B.칼럼2
FROM 테이블1 A [Inner] JOIN 테이블2 B
ON 조인조건
WHERE 검색조건;</code></pre>
</li>
</ul>
</li>
<li><code>왼쪽 외부 조인</code><ul>
<li>왼쪽에 위치한 테이블을 기준으로 조인<pre><code class="language-sql">SELECT A.칼럼1, A.칼럼2,
    B.칼럼1, B.칼럼2
FROM 테이블1 A LEFT [OUTER] JOIN 테이블2 B
ON 조인조건
WHERE 검색조건;</code></pre>
</li>
</ul>
</li>
<li><code>오른쪽 외부 조인</code><ul>
<li>오른쪽에 위치한 테이블을 기준으로 조인<pre><code class="language-sql">SELECT A.칼럼1, A.칼럼2,
    B.칼럼1, B.칼럼2
FROM 테이블1 A RIGHT [OUTER] JOIN 테이블2 B
ON 조인조건
WHERE 검색조건;</code></pre>
</li>
</ul>
</li>
<li><code>교차 조인</code><ul>
<li>각 테이블의 칼럼끼리 다 조인<pre><code class="language-sql">SELECT A.칼럼1, A.칼럼2,
    B.칼럼1, B.칼럼2
FROM 테이블1 A CROSS JOIN 테이블2 B;</code></pre>
</li>
</ul>
</li>
</ul>
<ol start="3">
<li>집합 연산자</li>
</ol>
<ul>
<li><code>UNION</code><ul>
<li>중복 행 제거</li>
</ul>
</li>
<li><code>UNION ALL</code><ul>
<li>중복 행 제거 X</li>
</ul>
</li>
<li>INTERSERT<ul>
<li>중복 레코드만 포함</li>
</ul>
</li>
<li>MINUS<ul>
<li>첫 쿼리에만 있는 것<br/>

</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="insert-명령어">INSERT 명령어</h3>
<ul>
<li>데이터의 내용을 삽입<ul>
<li>INSERT INTO VALUES<pre><code class="language-sql">INSERT INTO 테이블명(속성명1, 속성명2, ..)
VALUES(데이터1, 데이터2, ..);</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="update-명령어">UPDATE 명령어</h3>
<ul>
<li>데이터의 내용을 변경<ul>
<li>UPDATE SET WHERE<pre><code class="language-sql">UPDATE 테이블명
SET 속성명1 = 데이터1, 속성명2 = 데이터2.. 
WHERE 조건;</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="delete-명령어">DELETE 명령어</h3>
<ul>
<li>데이터의 내용을 삭제<ul>
<li>DELETE FROM WHERE<pre><code class="language-sql">DELETE FROM 테이블명
WHERE 조건;</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="dcl">DCL</h2>
<ul>
<li><p>데이터 제어어</p>
<pre><code>GRANT 권한부여
REVOKE 권한취소</code></pre></li>
</ul>
<ol>
<li><p><code>GRANT</code></p>
<ul>
<li>사용자에게 데이터베이스의 권한 부여<pre><code class="language-sql">GRANT 권한 [UPDATE | DELETE] ON 테이블명 TO 사용자;</code></pre>
</li>
</ul>
</li>
<li><p><code>REVOKE</code></p>
<ul>
<li>사용자에게 데이터베이스의 권한 회수<pre><code class="language-sql">REVOKE 권한 [UPDATE | DELETE] ON 테이블명 FROM 사용자;</code></pre>
</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[9장 - SW 개발 보안 구축 - 1장]]></title>
            <link>https://velog.io/@ch980113_/9%EC%9E%A5-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@ch980113_/9%EC%9E%A5-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Tue, 09 Apr 2024 16:04:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="소프트웨어-개발-보안-설계">소프트웨어 개발 보안 설계</h1>
</blockquote>
<h2 id="sw-개발-보안의-구성요소">SW 개발 보안의 구성요소</h2>
<h3 id="3대-구성요소-기무가">3대 구성요소 (기무가)</h3>
<ul>
<li><code>기밀성</code><ul>
<li>인가된 사용자만 접근 가능</li>
</ul>
</li>
<li><code>무결성</code><ul>
<li>데이터가 훼손, 파괴 되지 않음을 보장</li>
</ul>
</li>
<li><code>가용성</code> <ul>
<li>언제든 접근 가능</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="sw-개발-보안을-위한-공격기법의-이해">SW 개발 보안을 위한 공격기법의 이해</h2>
</blockquote>
<h3 id="dos-공격">DoS 공격</h3>
<ul>
<li><code>SYN 플러딩</code><ul>
<li>TCP 프로토콜의 구조적인 문제를 이용한 공격</li>
</ul>
</li>
<li><code>UDP 플러딩</code><ul>
<li>대량의 UDP 패킷을 만들어 자원 고갈</li>
</ul>
</li>
<li><code>스머프/ 스머핑</code><ul>
<li>ICMP Echo 패킷을 직접 브로드캐스팅하여 마비</li>
</ul>
</li>
<li><code>죽음의 핑</code><ul>
<li>ICMP 패킷을 정상보다 크게 만들어 전송하여 마비</li>
</ul>
</li>
<li><code>랜드 어택</code><ul>
<li>수신자가 자기 자신에게 응답하여 가용성 침해</li>
</ul>
</li>
<li><code>티어 드롭</code><ul>
<li>IP 패킷 재조합 과정에서 수신시스템 문제를 발생시키도록</li>
</ul>
</li>
</ul>
<h3 id="ddos-공격">DDoS 공격</h3>
<ul>
<li>여러 대의 공격자를 배치하여 공격</li>
</ul>
<h3 id="drdos">DRDos</h3>
<ul>
<li>DDoS보다 공격의 근원지 파악 어려움</li>
</ul>
<h3 id="세션-하이재킹">세션 하이재킹</h3>
<ul>
<li><strong>TCP의 세션 관리의 취약점</strong>을 이용</li>
<li>비동기화 상태 탐지</li>
<li>ACK 패킷 비율 모니터링</li>
</ul>
<h3 id="네트워크-공격">네트워크 공격</h3>
<ul>
<li><code>스니핑</code><ul>
<li>데이터만 몰래 들여다보는 수동적 공격, 직접 공격X</li>
</ul>
</li>
<li><code>네트워크 스캐너/스니퍼</code><ul>
<li>네트워크의 취약점 파악을 위해 탐색하는 공격 도규</li>
</ul>
</li>
<li><code>패스워드 크래킹</code><ul>
<li><code>사전 크래킹</code><ul>
<li>가능성이 될 단어를 파일로 만들어 대입</li>
</ul>
</li>
<li><code>무차별 크래킹</code><ul>
<li>무작위로 대입</li>
</ul>
</li>
<li><code>패스워드 하이브리드</code></li>
</ul>
</li>
<li><code>트로이 목마</code><ul>
<li>악성 루틴이 몰래 숨어있는 프로그램</li>
</ul>
</li>
</ul>
<h3 id="시스템-보안-위협">시스템 보안 위협</h3>
<ul>
<li><p>버퍼 오버플로</p>
<ul>
<li>스택 버퍼 오버플로</li>
<li>힙 버퍼 오버플로</li>
</ul>
</li>
<li><p>백도어</p>
<ul>
<li>인증 절차를 우회하는 기법</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="서버-인증-및-접근-통제">서버 인증 및 접근 통제</h2>
</blockquote>
<h3 id="서버인증">서버인증</h3>
<ul>
<li>사용자의 정보를 확인하는 보안 절차</li>
</ul>
<h3 id="서버인증의-유형">서버인증의 유형</h3>
<ul>
<li><code>지식기반 인증</code><ul>
<li>ID, 패스워드</li>
</ul>
</li>
<li><code>소지기반 인증</code><ul>
<li>공인인증서</li>
</ul>
</li>
<li><code>생체기반 인증</code><ul>
<li>홍채, 정맥, 얼굴, 지문</li>
</ul>
</li>
<li><code>특징(행위)기반 인증</code><ul>
<li>서명,  발걸음, 몸짓</li>
</ul>
</li>
</ul>
<h3 id="서버-접근-통제의-유형">서버 접근 통제의 유형</h3>
<ul>
<li><code>임의적 접근 통제 (DAC)</code><ul>
<li>주체나 그룹의 <strong>신분</strong>에 근거</li>
<li>신분 기반 접근통제 </li>
</ul>
</li>
<li><code>강제적 접근통제 (MAC)</code><ul>
<li>허용등급, 주체가 갖고있는 접근허가 권한에 근거</li>
<li>규칙기반 접근통제</li>
</ul>
</li>
<li><code>역할 기반 접근 통제(RBAC)</code><ul>
<li>맡은 <strong>역할</strong>에 근거</li>
</ul>
</li>
</ul>
<h3 id="접근-통제-보호-모델">접근 통제 보호 모델</h3>
<ul>
<li><code>벨-라파둘라 모델</code><ul>
<li>미 국방부</li>
<li>기밀성 강조</li>
</ul>
</li>
<li><code>비바 모델</code><ul>
<li>무결성 강조</li>
</ul>
</li>
</ul>
<h3 id="3a">3A</h3>
<ul>
<li><code>인증</code><ul>
<li>신분 검증</li>
</ul>
</li>
<li><code>권한 부여</code><ul>
<li>접근 허용</li>
</ul>
</li>
<li><code>계정 관리</code><ul>
<li>정보 수집, 관리, 접근 추적, 행동 기록</li>
</ul>
</li>
</ul>
<h3 id="인증-관련-기술">인증 관련 기술</h3>
<ul>
<li><code>SSO</code><ul>
<li>커버로스에서 사용</li>
<li>한 번의 인증 과정으로 여러 컴퓨터 이용 가능</li>
</ul>
</li>
<li><code>커버로스</code><ul>
<li>대칭 키 암호 기법의 티켓 기반의 프로토콜</li>
<li>2004년 2개 회사가 합심해 만듦</li>
</ul>
</li>
<li><code>OAuth</code><ul>
<li>다른 웹 사이트에 대한 접근 권한 부여 가능 (구글, 네이버, 카카오)</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="sw-개발-보안을-위한-암호화-알고리즘">Sw 개발 보안을 위한 암호화 알고리즘</h2>
</blockquote>
<h3 id="암호-알고리즘">암호 알고리즘</h3>
<ul>
<li><code>양방향</code><ul>
<li>대칭키<ul>
<li>블록 암호<ul>
<li>DES, AES, SEED</li>
</ul>
</li>
<li>스트림 암호<ul>
<li>RC4</li>
</ul>
</li>
</ul>
</li>
<li>비대칭키<ul>
<li>RSA, 디피-헬만, ECC</li>
</ul>
</li>
</ul>
</li>
<li><code>일방향</code><ul>
<li>해시함수<ul>
<li>고정된 길이의 암호문(해시값) 출력</li>
<li>MAC <ul>
<li>키를 사용하는 메시지 인증 코드</li>
</ul>
</li>
<li>MDC <ul>
<li>키를 사용하지 않는 변경 감지 코드</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="대칭키-암호화-기법---양방향">대칭키 암호화 기법 - 양방향</h3>
<ul>
<li><code>DES</code><ul>
<li>16라운드, 64비트</li>
</ul>
</li>
<li><code>SEED</code><ul>
<li>16라운드, 128비트</li>
</ul>
</li>
<li><code>AES</code><ul>
<li>전사적 공격 가능, 128비트, DES 성능 개선으로 갭발</li>
</ul>
</li>
<li><code>Skipjack</code><ul>
<li>칩이 내장</li>
</ul>
</li>
<li><code>IDEA</code><ul>
<li>8라운드, 64비트</li>
</ul>
</li>
<li><code>ARIA</code><ul>
<li>128비트, 키 길이에 따라 128, 192, 256으로 분류</li>
<li>2004년 2개가 합심해 개발</li>
</ul>
</li>
</ul>
<h3 id="비대칭키-암호화-기법---양방향">비대칭키 암호화 기법 - 양방향</h3>
<ul>
<li><code>RSA</code><ul>
<li>소인수 분해</li>
</ul>
</li>
<li><code>ECC</code><ul>
<li>이산 대수</li>
</ul>
</li>
<li><code>디피-헬만</code><ul>
<li>최초</li>
</ul>
</li>
</ul>
<h3 id="해시함수-암호화-기법---일방향">해시함수 암호화 기법 - 일방향</h3>
<ul>
<li><code>MD5</code><ul>
<li>MD4를 개선</li>
<li>128비트의 해시값 생성</li>
</ul>
</li>
<li><code>SHA-1</code><ul>
<li>160비트의  해시  생성</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h2 id="데이터베이스-암호화-기법">데이터베이스 암호화 기법</h2>
</blockquote>
<ul>
<li><p><code>VPN</code></p>
<ul>
<li>인터넷 공중망에 기술을 활용하여 마치 전용망을 사용하는 효과를 갖음</li>
<li><code>IPSec</code><ul>
<li>IP계층(3계층 네트워크)에서 사용하는 무결성, 인증 보장 보안 프로토콜</li>
</ul>
</li>
<li><code>SSL/TLS</code><ul>
<li>전송계층(4계층), 응용계층(7계층) 사이에서 무결성 보장 보안 프로토콜</li>
</ul>
</li>
</ul>
</li>
<li><p><code>L2TP</code></p>
<ul>
<li>데이터 링크 계층(2계층)에서 사용하는 보안 프로토콜</li>
<li>UDP 포트 사용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[11장 - 응용 SW 기초 기술 활용]]></title>
            <link>https://velog.io/@ch980113_/11%EC%9E%A5-%EC%9D%91%EC%9A%A9-SW-%EA%B8%B0%EC%B4%88-%EA%B8%B0%EC%88%A0-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@ch980113_/11%EC%9E%A5-%EC%9D%91%EC%9A%A9-SW-%EA%B8%B0%EC%B4%88-%EA%B8%B0%EC%88%A0-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Tue, 09 Apr 2024 09:56:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="네트워크-계층-구조">네트워크 계층 구조</h1>
</blockquote>
<h2 id="osi-계층">OSI 계층</h2>
<pre><code>7계층 응용계층          (Application) - HTTP/HTTPS
6계층 표현계층        (Presentation)
5계층 세션계층        (Session)
4계층 전송계층        (Transport)   - TCP/UDP
3계층 네트워크계층        (Network)     - IP/ICMP
2계층 데이터링크계층    (Data Link)   - HDLC/PPP
1계층 물리계층        (Physical)</code></pre><ul>
<li>외우는 방법 <ul>
<li><strong>아파서 티내다, 피나다</strong></li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h1 id="네트워크-장비">네트워크 장비</h1>
</blockquote>
<h3 id="1계층-장비">1계층 장비</h3>
<ul>
<li><code>허브</code> : 하나의 네트워크로 여러 대의 컴퓨터로 송신하기 위한 장비</li>
<li><code>리피터</code> : 디지털 신호를 증폭</li>
</ul>
<h3 id="2계층-장비">2계층 장비</h3>
<ul>
<li><code>브리지</code> : 두 개의 근거리 통신망(LAN)을 연결</li>
</ul>
<h3 id="3계층-장비">3계층 장비</h3>
<ul>
<li><code>라우터</code> : LAN과 LAN을 연결 or LAN과 WAN을 연결</li>
<li><code>게이트웨이</code> : 서로 다른 통신망에 접속</li>
</ul>
<hr>
<blockquote>
<h1 id="프로토콜">프로토콜</h1>
</blockquote>
<h3 id="개념">개념</h3>
<ul>
<li>서로 다른 시스템이나 기기들 간의 데이터 교환을 원활히 하기 위함</li>
<li>3요소 <ul>
<li><code>구문, 의미, 타이밍 (구의타)</code></li>
</ul>
</li>
</ul>
<h2 id="데이터-링크-계층---2계층">데이터 링크 계층 - 2계층</h2>
<h3 id="프로토콜-1">프로토콜</h3>
<ul>
<li><code>HDLC</code><ul>
<li>동기식 비트 중심</li>
</ul>
</li>
<li><code>ATM</code><ul>
<li>정보전달 기본 단위를 53바이트 셀 단위로 전달</li>
<li>비동기식 시분할 다중화 방식의 패킷형 전송기술</li>
<li>광대역 전송</li>
</ul>
</li>
<li><code>PPP</code><ul>
<li>두 통신 노드 간의 직접적인 연결을 위해 사용</li>
</ul>
</li>
<li><code>프레임 릴레이</code><ul>
<li>중계 기능, 다중화 기능만 수행</li>
</ul>
</li>
</ul>
<h3 id="오류-제어">오류 제어</h3>
<ul>
<li><p><code>전진 순방향 오류수정 (FEC : Foward Error Correction)</code></p>
<ul>
<li>데이터 전송 과정에서 오류 발생시 재전송 요구없이 스스로 수정</li>
<li><code>해밍코드방식</code><ul>
<li>수신측에서 오류가 발생한 비트를 찾아 재전송을 요구하지 않고 자신이 직접 오류를 수정 </li>
<li>1비트의 오류 수정이 가능</li>
</ul>
</li>
</ul>
</li>
<li><p><code>후진 역방향 오류수정(BEC : Backward Error Correction)</code></p>
<ul>
<li>오류 발생시 송신 측에 재전송 요구</li>
<li>패리티 검사<ul>
<li>패리티 비트를 추가 </li>
</ul>
</li>
<li>CRC<ul>
<li>다향식을 통해 산출된 값으로 오류 검사 </li>
</ul>
</li>
<li>블록합 검사</li>
<li>자동반복 요청방식(ARQ)</li>
</ul>
<br/>
## 네트워크 계층 - 3계층
### 네트워크 계층 프로토콜 </li>
<li><p><code>IP</code></p>
<ul>
<li>패킷 단위로 데이터를 교환 </li>
</ul>
</li>
<li><p><code>ARP</code></p>
<ul>
<li>IP 주소 -&gt; MAC 주소로 변환  </li>
</ul>
</li>
<li><p><code>RARP</code></p>
<ul>
<li>MAC 주소 -&gt; IP 주소로 변환</li>
</ul>
</li>
<li><p><code>ICMP</code></p>
<ul>
<li>IP 과정 중 오류 발생 시 오류 정보를 메시지 형태로 전송</li>
</ul>
</li>
<li><p><code>IGMP</code></p>
<ul>
<li>인터넷 그룹 관리, 화상회의</li>
</ul>
</li>
<li><p><code>NAT</code></p>
<ul>
<li>사설 네트워크 IP 주소 -&gt; 공인 IP 주소로 변환</li>
</ul>
</li>
<li><p><code>라우팅 프로토콜</code></p>
</li>
</ul>
<h3 id="ipv4--ipv6">IPv4 / IPv6</h3>
<ul>
<li><code>IPv4</code><ul>
<li>32비트</li>
<li>유니캐스트, 멀티캐스트, <code>브로드캐스트</code></li>
<li>서브네팅 <ul>
<li>IP 주소 고갈 문제를 해결하기 위해 분리</li>
</ul>
</li>
</ul>
</li>
<li><code>IPv6</code><ul>
<li>128 비트</li>
<li>16비트씩 8부분</li>
<li>40바이트의 고정길이 </li>
<li>유니캐스트, 멀티캐스트, <code>애니캐스트</code></li>
</ul>
</li>
</ul>
<h3 id="라우팅-프로토콜">라우팅 프로토콜</h3>
<ul>
<li>최적의 경로를 설정<ul>
<li><code>IGP (내부 라우팅 프로토콜)</code><ul>
<li>동일한 AS 내</li>
<li><code>RIP</code> <ul>
<li>거리벡터 알고리즘<ul>
<li>벨만-포드 알고리즘</li>
</ul>
</li>
</ul>
</li>
<li><code>OSPF</code><ul>
<li>RIP의 단점 개선</li>
<li>링크 상태 알고리즘 <ul>
<li>다익스트라 알고리즘</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><code>EGP (외부 라우팅 프로토콜)</code><ul>
<li>서로 다른 AS 간</li>
<li><code>BGP</code><ul>
<li>경로 벡터 알고리즘 <br/>

</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="전송-계층---4계층">전송 계층 - 4계층</h2>
<ul>
<li><code>TCP</code><ul>
<li>안정적으로, 패킷손실 없이, 에러 없이, 순서대로 교환 가능, 흐름제어 기능</li>
<li>TCP 헤더 20바이트</li>
</ul>
</li>
<li><code>UDP</code><ul>
<li>비연결성, 비신뢰성, 순서화X<br/>
## 세션계층 - 5계층</li>
</ul>
</li>
<li>응용 프로그램 간의 대화를 유지하기 위한 구조 제공, 논리적인 연결 담당<br/>
## 표현계층 - 6계층</li>
<li><code>JPEG</code><ul>
<li>이미지</li>
</ul>
</li>
<li><code>MPEG</code><ul>
<li>멀티미디어, 비디오, 오디오<br/>
## 응용계층 - 7계층
### 프로토콜</li>
<li><code>HTTP</code></li>
<li>하이퍼텍스트</li>
<li>80번 포트</li>
<li><code>HTTPS</code></li>
<li>HTTP의 보안이 강화된</li>
<li>443번 포트</li>
<li><code>SMTP</code></li>
<li>이메일 전송</li>
<li>TCP 포트번호 25번</li>
<li><code>IMAP</code></li>
<li>원격서버로 부터 이메일 가져오는</li>
<li>143번 포트</li>
<li><code>Telnet</code></li>
<li>네트워크 연결에 사용</li>
<li>23번 포트</li>
<li><code>SSH</code></li>
<li>Telnet보다 강화된 보안 </li>
<li>원격접속</li>
<li>22번 포트 </li>
<li><code>DNS</code></li>
<li>도메인 이름</li>
<li>53번 포트</li>
<li><code>FTP</code></li>
<li>데이터 전송 채널 - 20번 포트</li>
<li>데이터 전송 제어 채널 - 21번 포트 </li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h1 id="네트워크-전달-방식">네트워크 전달 방식</h1>
</blockquote>
<h2 id="패킷-교환-방식">패킷 교환 방식</h2>
<h3 id="종류">종류</h3>
<ul>
<li><code>데이터그램</code><ul>
<li>연결경로를 확립X</li>
<li>순서 무관하게 독립적 전송</li>
</ul>
</li>
<li><code>가상회선</code><ul>
<li>통신 경로를 미리 설정</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h1 id="네트워크-구조">네트워크 구조</h1>
</blockquote>
<h3 id="애드-혹-네트워크"><code>애드 혹 네트워크</code></h3>
<ul>
<li>노드 들에 의해 자율적으로 구성되는 구조가 없음</li>
<li>종류<ul>
<li>버스형 구조<ul>
<li>하나의 네트워크에 여러대의 노드가 연결</li>
</ul>
</li>
<li>트리형 구조</li>
<li>링형 구조</li>
<li>성형 구조<ul>
<li>중앙 허브, 스위치, 리피터 등 허브에 점대점 연결</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<h1 id="네트워크-용어">네트워크 용어</h1>
</blockquote>
<ul>
<li><code>SDN</code><ul>
<li>제어부 / 전달부로 분리</li>
</ul>
</li>
<li><code>NFV</code><ul>
<li>범용 하드웨어에 가상화 기술 적용</li>
</ul>
</li>
<li><code>NFC</code><ul>
<li>주파수 사용 </li>
<li>RFID의 확장 기술</li>
</ul>
</li>
<li><code>블루투스</code><ul>
<li>근거리 디바이스 간 통신 </li>
<li>피코넷, 스캐터넷</li>
</ul>
</li>
<li><code>Zing</code><ul>
<li>기기를 키오스크에 갖다 대면 데이터 가져올 수 있는 기술</li>
</ul>
</li>
<li><code>메시 네트워크</code><ul>
<li>기존 랜의 한계 극복 등장</li>
<li>차세대 이동통신</li>
<li>그물모양 네트워크</li>
</ul>
</li>
<li><code>사물인터넷</code><ul>
<li>각종 사물에 센서와 통신 기능 내장</li>
</ul>
</li>
<li><code>MQTT</code><ul>
<li>IOT 장치 등에서 최적화되어 사용될 수 있도록 개발</li>
<li>브로커를 사용한 발행/구독 방식의 경량 메시징 전송</li>
</ul>
</li>
<li><code>Zigbee</code><ul>
<li>근거리 통신 지원</li>
<li>저전력, 저비용, 저속</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL - 3월 21일 : 알고리즘 기초3]]></title>
            <link>https://velog.io/@ch980113_/TIL-3%EC%9B%94-21%EC%9D%BC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B8%B0%EC%B4%883</link>
            <guid>https://velog.io/@ch980113_/TIL-3%EC%9B%94-21%EC%9D%BC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B8%B0%EC%B4%883</guid>
            <pubDate>Mon, 25 Mar 2024 00:25:23 GMT</pubDate>
            <description><![CDATA[<h2 id="스택">스택</h2>
<h3 id="1-스택이란">1. 스택이란?</h3>
<ul>
<li><p>스택(Stack)은 컴퓨터 과학에서 자주 사용되는 기본적인 데이터 구조 중 하나로, 마지막에 추가된 요소가 가장 먼저 제거되는 후입선출(Last In First Out, LIFO) 방식을 따른다.</p>
</li>
<li><p>스택 구현의 중요 키워드</p>
<ul>
<li>push : 값을 넣음(스택의 가장 위에 새로운 요소를 추가한다.)</li>
<li>pop : 값을 꺼냄(스택의 가장 위에 있는 요소를 제거하고 그 값을 반환한다.)</li>
<li>peek : 빼지는 않고 값만 알려줌</li>
<li>top : 현재 가리키고 있는 인덱스</li>
<li>isEmpty : 배열이 비어있는지 확인</li>
<li>isFull : 배열이 꽉 차있는지 확인</li>
</ul>
</li>
<li><p>웹 브라우저의 뒤로 가기 기능 / 함수 호출 시의 반환 주소 저장 / 괄호의 짝 맞춤 검사 등 다양한 알고리즘과 프로그램에서 사용된다.</p>
<h3 id="2-스택-만들기">2. 스택 만들기</h3>
<pre><code class="language-java">public class MyStack {
  private int maxSize;        // 스택을 저장할 배열
  private int[] stackArray;   // 스택의 최대 크기
  private int top;            // 스택 포인터, 초기값은 -1

  // 스택의 크기를 받아들이는 생성자
  public MyStack(int maxSize) {
      this.maxSize = maxSize;
      this.stackArray = new int[maxSize];
      this.top = -1;
  }

  // 스택에 데이터 추가
  public void push(int num) {
      if (top &lt; maxSize - 1) {
          System.out.println(num);
          stackArray[++top] = num;
      } else {
          System.out.println(&quot;스택이 가득 찼습니다.&quot;);
      }
  }

  // 스택에서 데이터 제거
  public int pop() {
      if (isEmpty()) {
          System.out.println(&quot;스택이 비었습니다.&quot;);
          return -1;
      } else {
          return stackArray[top--];
      }
  }

  // 스택의 최상단 데이터 확인
  public int peek() {
      if(isEmpty()){
          System.out.println(&quot;스택이 비었습니다.&quot;);
          return -1;
      } else {
          return stackArray[top];
      }
  }

  // 스택이 비어 있는지 확인
  public boolean isEmpty() {
      return top == -1;
  }

  // 스택이 가득 찼는지 확인
  public boolean isFull(){
      return top == maxSize - 1;
  }

  public static void main(String[] args) {
      MyStack stack = new MyStack(5);
      stack.push(1);
      stack.push(2);
      stack.push(3);
      System.out.println(stack.pop());
      System.out.println(stack.peek());
      System.out.println(stack.pop());
      System.out.println(stack.pop());
      System.out.println(stack.isEmpty());
  }
}</code></pre>
<p>예외처리가 추가된 스택</p>
<pre><code class="language-java">public class FixedLengthStack {
  private int[] stackArray; // 스택을 저장할 배열
  private int stackCapacity; // 스택의 최대 크기
  private int stackPointer; // 스택 포인터

  // 스택이 비었을 때 발생하는 예외
  public static class StackEmptyException extends RuntimeException {
      public StackEmptyException() {
      }
  }

  // 스택이 가득 찼을 때 발생하는 예외
  public static class StackFullException extends RuntimeException {
      public StackFullException() {
      }
  }

  // 생성자
  public FixedLengthStack(int maxSize) {
      stackPointer = 0;
      stackCapacity = maxSize;
      stackArray = new int[stackCapacity];
  }

  // 스택에 데이터 추가
  public int push(int item) {
      if (stackPointer &gt;= stackCapacity)
          throw new StackFullException();
      return stackArray[stackPointer++] = item;
  }

  // 스택에서 데이터 제거
  public int pop() {
      if (stackPointer &lt;= 0)
          throw new StackEmptyException();
      return stackArray[--stackPointer];
  }

  // 스택의 최상단 데이터 확인
  public int peek() {
      if (stackPointer &lt;= 0)
          throw new StackEmptyException();
      return stackArray[stackPointer - 1];
  }

  // 스택 초기화
  public void clear() {
      stackPointer = 0;
  }

  // 스택에서 특정 데이터 찾기
  public int indexOf(int item) {
      for (int i = stackPointer - 1; i &gt;= 0; i--) {
          if (stackArray[i] == item)
              return i;
      }
      return -1;
  }

  // 스택 최대 크기 반환
  public int getCapacity() {
      return stackCapacity;
  }

  // 스택에 저장된 데이터 개수 반환
  public int size() {
      return stackPointer;
  }

  // 스택이 비어 있는지 확인
  public boolean isEmpty() {
      return stackPointer == 0;
  }

  // 스택이 가득 찼는지 확인
  public boolean isFull() {
      return stackPointer == stackCapacity;
  }

  // 스택 내용 출력
  public void dump() {
      if (stackPointer &lt;= 0)
          System.out.println(&quot;스택이 비어 있습니다.&quot;);
      else {
          for (int i = 0; i &lt; stackPointer; i++)
              System.out.print(stackArray[i] + &quot; &quot;);
          System.out.println();
      }
  }

  public static void main(String[] args) {
      FixedLengthStack stack = new FixedLengthStack(5); // 크기가 5인 스택 생성

      // 스택에 데이터를 푸시합니다.
      try {
          stack.push(1);
          stack.push(2);
          stack.push(3);
          stack.push(4);
          stack.push(5);
          // 스택이 가득 찼으므로, 다음 줄에서 예외가 발생합니다.
          stack.push(6);
      } catch (FixedLengthStack.StackFullException e) {
          System.out.println(&quot;스택이 가득 찼습니다.&quot;);
      }

      // 스택의 내용을 출력합니다.
      stack.dump();

      // 스택에서 데이터를 팝합니다.
      try {
          System.out.println(&quot;팝한 데이터: &quot; + stack.pop());
          System.out.println(&quot;팝한 데이터: &quot; + stack.pop());
          System.out.println(&quot;팝한 데이터: &quot; + stack.pop());
          // 스택이 비었으므로, 다음 줄에서 예외가 발생합니다.
          System.out.println(&quot;팝한 데이터: &quot; + stack.pop());
          System.out.println(&quot;팝한 데이터: &quot; + stack.pop());
          System.out.println(&quot;팝한 데이터: &quot; + stack.pop());
      } catch (FixedLengthStack.StackEmptyException e) {
          System.out.println(&quot;스택이 비어 있습니다.&quot;);
      }
  }
}</code></pre>
<p>​</p>
<h2 id="큐">큐</h2>
<h3 id="1-큐란">1. 큐란?</h3>
</li>
<li><p>큐(Queue)는 컴퓨터 과학에서 사용되는 중요한 추상 데이터 타입 중 하나로, 선입선출(First In First Out, FIFO)의 원칙을 따른다.</p>
</li>
<li><p>큐의 중요 키워드</p>
<ul>
<li>enQueue : 큐의 뒷쪽에 새로운 요소 추가</li>
<li>deQueue : 큐의 앞쪽에서 요소를 제거하고 반환</li>
<li>peek : 큐의 앞쪽에서 요소를 제거하지 않고 반환</li>
<li>front : 현재 반환해야되는 요소을 가르키는 배열의 인덱스</li>
<li>rear : 마지막 요소의 다음 위치를 가리키는 인덱스</li>
<li>count : 현재 큐에 저장된 요소의 개수</li>
<li>IsEmpty : 큐가 비어 있는지 확인한다.</li>
</ul>
</li>
<li><p>큐는 데이터를 일시적으로 보관해야 할 때 유용하게 사용된다.</p>
</li>
<li><p>프린터의 인쇄 작업 관리 / 운영 체제에서의 작업 스케줄링 / 네트워크 요청의 처리 순서 관리 등</p>
<h3 id="2-큐-만들기">2. 큐 만들기</h3>
</li>
<li><p>enqueue 와 dequeue 메소드에서 rear와 front를 하나씩 늘려주기만 하면 선형 큐</p>
</li>
<li><p>capacity 로 나눠주면 원형 큐가 된다.</p>
</li>
<li><p>선형 큐는 인덱스가 증가만 하므로 배열의 끝에 도달하면 포화된 큐가 아니더라도 앞의 빈 공간을 사용하지 못하는 문제점이 있다.</p>
<pre><code class="language-java">public class MyQueue {
  private int[] queueArray;   // 큐
  private int front;          // 큐의 맨 앞 값의 인덱스
  private int rear;           // 큐 맨 뒤 값의 다음 인덱스
  private int capacity;       // 큐 쵀대 용량
  private int count;          // 큐의 저장된 데이터 수

  // 큐의 크기를 받아들이는 생성자
  public MyQueue(int maxSize) {
      capacity = maxSize;
      queueArray = new int[capacity];
      front = rear = count = 0;
  }

  public void enqueue(int item) {
      if (isFull()) {
          System.out.println(&quot;큐가 가득 차서 데이터를 넣을 수 없어요.&quot;);
      } else {
          queueArray[rear] = item;
          rear = (rear + 1) % capacity;
          count++;

          System.out.println(item);
      }
  }

  public void dequeue() {
      if (isEmpty()) {
          System.out.println(&quot;큐가 비어서 뺄 데이터가 없어요.&quot;);
      } else {
          int item = queueArray[front];
          front = (front + 1) % capacity;
          count--;

          System.out.println(item);
      }
  }

  public void peek() {
      if (isEmpty()) {
          System.out.println(&quot;큐가 비어 있어요.&quot;);
      } else {
          int item = queueArray[front];
          System.out.println(item);
      }
  }

  public boolean isEmpty() {
      return count == 0;
  }

  public boolean isFull() {
      return count == capacity;
  }

  public static void main(String[] args) {
      MyQueue q = new MyQueue(3);
      q.enqueue(1);
      q.enqueue(3);
      q.enqueue(5);
      System.out.println(&quot;q.isFull() : &quot; + q.isFull());
      q.enqueue(7);
      q.dequeue();
      q.peek();
      q.dequeue();
      q.dequeue();
      System.out.println(&quot;q.isEmpty() : &quot; + q.isEmpty());
      q.dequeue();
  }
}</code></pre>
</li>
</ul>
<p>예외처리가 추가된 큐</p>
<pre><code class="language-java">public class FixedLengthQueue {
    private int[] queueArray; // 큐를 저장할 배열
    private int queueCapacity; // 큐의 최대 크기
    private int front; // 첫 번째 요소를 가리키는 인덱스
    private int rear; // 마지막 요소의 다음 위치를 가리키는 인덱스
    private int currentSize; // 현재 큐에 저장된 요소의 개수

    public class QueueEmptyException extends RuntimeException {
        public QueueEmptyException() {
        }
    }

    public class QueueFullException extends RuntimeException {
        public QueueFullException() {
        }
    }

    public FixedLengthQueue(int maxSize) {
        currentSize = front = rear = 0;
        queueCapacity = maxSize;
        queueArray = new int[queueCapacity];
    }

    public int enqueue(int item) {
        if (currentSize &gt;= queueCapacity)
            throw new QueueFullException();
        queueArray[rear] = item;
        rear = (rear + 1) % queueCapacity;
        currentSize++;
        return item;
    }

    public int dequeue() {
        if (currentSize &lt;= 0)
            throw new QueueEmptyException();
        int item = queueArray[front];
        front = (front + 1) % queueCapacity;
        currentSize--;

        return item;
    }

    public int peek() {
        if (currentSize &lt;= 0)
            throw new QueueEmptyException();
        return queueArray[front];
    }

    public void clear() {
        currentSize = front = rear = 0;
    }

    public int indexOf(int item) {
        for (int i = 0; i &lt; currentSize; i++) {
            int index = (front + i) % queueCapacity;
            if (queueArray[index] == item)
                return index;
        }

        return -1;
    }

    public int getCapacity() {
        return queueCapacity;
    }

    public int size() {
        return currentSize;
    }

    public boolean isEmpty() {
        return currentSize == 0;
    }

    public boolean isFull() {
        return currentSize == queueCapacity;
    }

    public void dump() {
        if (currentSize &lt;= 0) {
            System.out.println(&quot;큐가 비어 있습니다.&quot;);
        } else {
            for (int i = 0; i &lt; currentSize; i++) {
                System.out.print(queueArray[(front + i) % queueCapacity] + &quot; &quot;);
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        FixedLengthQueue queue = new FixedLengthQueue(5); // 크기가 5인 큐 생성

        // 큐에 데이터를 인큐(추가)합니다.
        try {
            queue.enqueue(10);
            queue.enqueue(20);
            queue.enqueue(30);
            queue.enqueue(40);
            queue.enqueue(50);
            // 큐가 가득 찼으므로, 다음 줄에서 OverflowIntQueueException 예외가 발생할 수 있습니다.
            // queue.enqueue(60); // 이 줄의 주석을 해제하면 예외가 발생합니다.

        } catch (FixedLengthQueue.QueueFullException e) {
            System.out.println(&quot;큐가 가득 찼습니다. 더 이상 데이터를 추가할 수 없습니다.&quot;);
        }

        // 큐의 내용을 출력합니다.
        queue.dump();

        // 큐에서 데이터를 디큐(제거)합니다.
        try {
            while (!queue.isEmpty()) {
                System.out.println(&quot;디큐한 데이터: &quot; + queue.dequeue());
            }
            // 큐가 비었으므로, 다음 줄에서 EmptyIntQueueException 예외가 발생할 수 있습니다.
            // System.out.println(queue.dequeue()); // 이 줄의 주석을 해제하면 예외가 발생합니다.

        } catch (FixedLengthQueue.QueueEmptyException e) {
            System.out.println(&quot;큐가 비어 있습니다. 더 이상 데이터를 제거할 수 없습니다.&quot;);
        }
    }
}</code></pre>
<h2 id="재귀의-기본">재귀의 기본</h2>
<h3 id="1-재귀란">1. 재귀란?</h3>
<ul>
<li><p>재귀(Recursion)는 자신을 정의할 때 자기 자신을 호출하는 방식을 의미한다.</p>
</li>
<li><p><strong>종료조건이 필수적으로 필요하다</strong></p>
</li>
<li><p>재귀 함수는 기본적으로 두 부분으로 구성된다.
a. 기저 조건(Base Case)
재귀 호출을 멈추고 함수가 자기 자신을 더 이상 호출하지 않는 조건이다.
기저 조건은 재귀가 무한 루프에 빠지지 않도록 하는 중요한 역할을 한다.
b. 재귀적 단계(Recursive Case)
문제의 크기를 줄이고 자기 자신을 호출하는 부분이다.</p>
<pre><code class="language-java">public class RecursiveTest {
  static void recursive(int n){
      if(n &gt; 0){
          recursive(n - 1);
          System.out.println(n);
      }
  }

  public static void main(String[] args) {
      recursive(5);
  }
}</code></pre>
</li>
</ul>
<h3 id="2-팩토리얼-구하기">2. 팩토리얼 구하기</h3>
<pre><code class="language-java">import java.util.Scanner;

public class FactorialCalculator {
    static int factorial(int n) {
        if (n &gt; 0)
            return n * factorial(n - 1);
        else
            return 1;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print(&quot;n!, 정수 n을 입력하세요 : &quot;);
        int n = sc.nextInt();

        System.out.println(n + &quot;! = &quot; + factorial(n));
    }
}</code></pre>
<h3 id="3-유클리드-호제법">3. 유클리드 호제법</h3>
<ul>
<li>유클리드 호제법(Euclidean Algorithm)은 두 양의 정수의 최대공약수(Greatest Common Divisor, GCD)를 찾는 효율적인 방법이다.</li>
<li>기본 아이디어는 두 수의 차이가 그 수들의 최대 공약수에 영향을 미치지 않는다는 것이다.</li>
<li>두 수 a와 b (a &gt; b)의 최대공약수는 a와 a-b의 최대공약수와 같다. 이 원리를 반복하면 최종적으로 최대공약수를 구할 수 있다.</li>
<li>뺄셈을 이용한 방법
가장 단순한 형태로, 두 수 중 큰 수에서 작은 수를 뺀다.
이 과정을 두 수가 같아질 때까지 반복하여, 최종적으로 남은 수가 두 수의 최대공약수가 된다.
→ 큰 수에 대해서는 계산이 비효율적일 수 있다.</li>
<li>나눗셈을 이용한 방법(모듈로 연산)
두 수 a와 b (a &gt; b)가 있을 때, a를 b로 나눈 나머지를 구한다.
그 다음, b와 이 나머지의 최대공약수를 구한다.
반복하여 나머지가 0이 되었을 때의 b가 두 수의 최대공약수이다.
→ 뺄셈을 사용하는 방법보다 훨씬 빠르고 효율적이다.<pre><code class="language-java">import java.util.Scanner;
</code></pre>
</li>
</ul>
<p>public class GCDCalculator {
    // 유클리드 호제법을 사용한 반복문
    static int gcd(int x, int y) {
        while (y != 0) {
            int temp = y;
            y = x % y;
            x = temp;
        }
        return x;
    }</p>
<pre><code>// 유클리드 호제법을 사용한 재귀 호출
static int calculateGCD(int x, int y) {
    if (y == 0)
        return x;
    else
        return calculateGCD(y, x % y);
}

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    System.out.println(&quot;두 수의 최대공약수를 계산합니다.&quot;);
    System.out.print(&quot;첫 번째 정수를 입력하세요: &quot;);
    int x = sc.nextInt();
    System.out.print(&quot;두 번째 정수를 입력하세요: &quot;);
    int y = sc.nextInt();

    System.out.println(&quot;두 수의 최대공약수는 &quot; + gcd(x, y) + &quot;입니다.&quot;);
    System.out.println(&quot;두 수의 최대공약수는 &quot; + calculateGCD(x, y) + &quot;입니다.&quot;);
}</code></pre><p>}</p>
<pre><code>## 꼬리 재귀
- 팩토리얼을 재귀함수와 for문으로 작성한 코드
```java
import java.util.Scanner;

public class FactorialCalculator {
    //재귀함수
    static int factorial(int num) {
        if (num &gt; 0){
            return factorial(num-1) * num;
        } else{
            return 1; //0!은 1이다.
        }
    }

    //for문으로 구현한 함수
    static int factorialForGrammar(int num) {
        int result = 1;
        if (num &gt; 0){
            for(int i = num; i &lt; 0; i--){
                result *= num;
            }
        }else {
            result = 1;
        }
        return result;
    }

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int num = 0;

        do {
            System.out.print(&quot;펙토리얼을 구하고자하는 양의 정수를 입력하세요: &quot;);
            num = sc.nextInt();
        }while(num &lt; 0);

        System.out.println(factorial(num));
        System.out.println(factorialForGrammar(num));
    }
}</code></pre><h3 id="꼬리재귀란"><strong>꼬리재귀란</strong></h3>
<p>위의 팩토리얼 재귀함수 코드를 보면 return뒤에  아래와 같은 형태로 되어있는 것을 볼 수 있다.</p>
<pre><code class="language-java">factorial(num-1) * num;</code></pre>
<ul>
<li>꼬리재귀는 재귀함수에 다른 연산을 하는 것이 아닌 모조건 return뒤에 재귀함수 본인만 오는 것을 말한다.</li>
<li>꼬리 재귀(Tail Recursion)는 함수의 마지막 동작이 자기 자신을 호출하는 형태의 재귀이다.</li>
<li>재귀 호출이 함수의 끝부분에서 발생하며, 현재 함수의 실행 상태를 유지할 필요가 없기 때문에, 컴파일러나 인터프리터가 최적화하기가 더 쉽다.
→ 즉, 새로운 스택 프레임을 추가하지 않고 현재의 스택 프레임을 재사용할 수 있어 메모리 사용량이 줄고, 실행 효율이 높아질 수 있다.</li>
<li>예제 : 팩토리얼 계산<pre><code class="language-java">import java.util.Scanner;
</code></pre>
</li>
</ul>
<p>public class TailRecursiveFactorial {
    // 꼬리 재귀를 사용한 팩토리얼 계산 메서드
    static int factorial(int n, int accumulator) {
        if (n == 1) return accumulator;
        return factorial(n - 1, n * accumulator); // 꼬리 재귀 호출
    }</p>
<pre><code>// 사용자가 입력한 숫자에 대해 팩토리얼을 계산
public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    System.out.print(&quot;팩토리얼을 계산할 정수를 입력하세요: &quot;);
    int x = sc.nextInt();

    // 초기 누적 변수 값으로 1을 사용
    int result = factorial(x, 1);
    System.out.println(x + &quot;의 팩토리얼은 &quot; + result + &quot;입니다.&quot;);
}</code></pre><p>}</p>
<pre><code>
마지막에 수행하는 작업이 재귀 호출인 점이 중요한 특징이다.
호출 시 전달되는 모든 정보가 매개변수에 포함되어 있어서 현재 실행 컨텍스트를 유지할 필요가 없다는 것이다.
## 정렬
정렬(Sorting)은 데이터를 특정 기준에 따라 순서대로 배열하는 과정이다.
### 1. 버블 정렬(Bubble Sort)
- 방식 
: 인접한 두 요소를 비교하고, 필요한 경우에 위치를 교환한다. 이 과정을 모든 요소가 정렬될 때까지 반복한다.
: 한 턴이 끝나면 마지막 요소는 정렬되어 있는 상태
- 특징 : 구현이 간단하지만, 효율성이 낮아 큰 데이터셋에는 부적합하다.
평균 및 최악의 경우 시간 복잡도는 O(n^2) 이다.
```java
import java.util.Arrays;

public class BubbleSortExam {
    public static void bubbleSort(int[] arr) {
        for (int i = 0; i &lt; arr.length - 1; i++) {
            for (int j = 0; j &lt; arr.length - 1 - i; j++) {
                if (arr[j] &gt; arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            System.out.println((i + 1) + &quot;번째 정렬 : &quot; + Arrays.toString(arr));
        }
    }

    public static void main(String[] args) {
        int[] arr = {64, 33, 67, 22, 6, 88, 5};
        System.out.println(&quot;원래배열 : &quot; + Arrays.toString(arr));

        bubbleSort(arr);

        System.out.println(&quot;정렬 후 배열 : &quot; + Arrays.toString(arr));
    }</code></pre><p>}</p>
<p>if 문 안의 내용이 보기 복잡하다면 swap 메소드로 구현하면 좀 더 깔끔해지기도 한다.</p>
<h3 id="2-선택-정렬selection-sort">2. 선택 정렬(Selection Sort)</h3>
<ul>
<li>방식 
: 전체 요소 중에서 가장 작은(혹은 큰) 요소를 찾아 첫 번째(혹은 마지막) 위치에 놓고, 나머지 요소에 대해 같은 과정을 반복한다.
: 한 턴이 끝나면 가장 앞의 요소는 정렬되어 있는 상태</li>
<li>특징 : 버블 정렬과 마찬가지로 구현이 쉽지만, 큰 데이터셋에는 비효율적이다.
시간 복잡도는 평균과 최악의 경우 모두 O(n^2) 이다.<pre><code class="language-java">import java.util.Arrays;
</code></pre>
</li>
</ul>
<p>public class SelectionSortExam {
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }</p>
<pre><code>public static void selectionSort(int[] arr) {
    for (int i = 0; i &lt; arr.length; i++) {
        int min = i;
        for (int j = i; j &lt; arr.length; j++) {
            if (arr[min] &gt; arr[j]) {
                min = j;
            }
        }
        swap(arr, i, min);
        System.out.println((i + 1) + &quot;번째 정렬 : &quot; + Arrays.toString(arr));
    }
}

public static void main(String[] args) {
    int[] arr = {64, 33, 67, 22, 6, 88, 5};
    System.out.println(&quot;원래배열 : &quot; + Arrays.toString(arr));

    selectionSort(arr);

    System.out.println(&quot;정렬 후 배열 : &quot; + Arrays.toString(arr));
}</code></pre><p>}
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL - 3월 20일 : 알고리즘 기초2]]></title>
            <link>https://velog.io/@ch980113_/TIL-3%EC%9B%94-20%EC%9D%BC</link>
            <guid>https://velog.io/@ch980113_/TIL-3%EC%9B%94-20%EC%9D%BC</guid>
            <pubDate>Wed, 20 Mar 2024 12:16:34 GMT</pubDate>
            <description><![CDATA[<h1 id="알고리즘">알고리즘</h1>
<hr>
<h2 id="클래스">클래스</h2>
<ul>
<li>자바에서 클래스는 객체 지향 프로그래밍의 핵심 구성 요소</li>
<li>객체는 클래스에 정의된 속성과 동작을 가지며, 클래스에서 생성된다.</li>
<li>클래스를 사용하면 코드의 재사용성, 확장성 및 관리 용이성이 향상된다.<h3 id="정의-방법">정의 방법</h3>
</li>
</ul>
<pre><code class="language-java">class ClassName {
    // 필드(변수)
    // 메서드(함수)
}</code></pre>
<ul>
<li><code>ClassName</code>은 클래스의 이름으로, Java의 네이밍 컨벤션에 따라 각 단어의 첫 글자는 대문자로 시작한다.</li>
</ul>
<h3 id="주요-구성-요소">주요 구성 요소</h3>
<ol>
<li><strong>필드(Fields)</strong><ul>
<li>클래스 내에서 정의된 변수로, 객체의 상태를 나타낸다. 필드는 객체의 속성, 특성을 저장하기 위해 사용한다.</li>
</ul>
</li>
<li><strong>메서드(Methods)</strong><ul>
<li>객체가 수행할 수 있는 동작을 정의한 코드 블록이다. 메서드는 특정 작업을 수행하고, 결과를 반환하거나, 단순히 작업을 수행할 수 있다.</li>
</ul>
</li>
<li><strong>생성자(Constructor)</strong><ul>
<li>클래스 이름과 동일하며, 객체가 생성될 때 자동으로 호출되는 특별한 메서드이다. 생성자는 객체 초기화에 주로 사용된다.</li>
<li>명시적으로 생성자를 정의하지 않으면, 자바 컴파일러는 기본 생성자를 제공한다.</li>
</ul>
</li>
</ol>
<p>ex. 자바 클래스</p>
<pre><code class="language-java">public class Dog {
    // 필드
    String breed;
    int age;
    String color;

    // 메서드
    // 접근제한자 리턴타입 메소드명 (매개변수들..) {..구현..}
    void bark() {
        System.out.println(&quot;Woof!&quot;);
    }

    void displayInfo() {
        System.out.println(&quot;Breed: &quot; + breed + &quot;, Age: &quot; + age + &quot;, Color: &quot; + color);
    }
}</code></pre>
<p>ex. 객체 생성 및 사용</p>
<ul>
<li>클래스를 정의한 후, new 키워드를 사용하여 클래스의 인스턴스(객체)를 생성할 수 있다<pre><code class="language-java">public class DogTest {
  public static void main(String[] args) {
      Dog myDog = new Dog();
      myDog.breed = &quot;Labrador&quot;;
      myDog.age = 5;
      myDog.color = &quot;Brown&quot;;
      myDog.bark();
      myDog.displayInfo();
  }
}</code></pre>
</li>
</ul>
<hr>
<h2 id="소수">소수</h2>
<ul>
<li>입력한 정수까지 모두 체킹을 하며 소수를 찾는 방식</li>
</ul>
<pre><code class="language-java">import java.util.Scanner;

public class ListPrimes {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;정수를 입력하세요: &quot;);
        int num = sc.nextInt();
        int cnt = 0;

        for (int i = 2; i &lt;= num; i++){
            boolean isPrime = true;
            for (int j = 2; j &lt; i ; j++){
                cnt++;
                if (i % j == 0){
                    isPrime = false;
                    break;
                }
            }
            if(isPrime == true){
                System.out.println(i);
            }
        }
        System.out.println(cnt);
    }
}</code></pre>
<h3 id="설명">설명</h3>
<p>입력한 정수까지의 모든 수를 2부터 체킹하는 수-1까지의 모든 수로 나누어 소수인지 판별을 한다.
이러한 방식은 시간이 오래걸리는 단점이 있음.
입력한 정수까지 홀수만 체킹하며 소수를 찾는 방식</p>
<hr>
<pre><code class="language-java">import java.util.Scanner;

public class ListPrimes2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;정수를 입력하세요: &quot;);
        int num = sc.nextInt();
        int cnt = 0;
        int arrCnt = 0;
        int[] primes = new int[500];

        primes[arrCnt++] = 2; // 2를 먼저 소수의 배열에 넣어준다.

        for (int i = 3; i &lt;= num; i+=2){
            boolean isPrime = true;
            for (int j = 3; j &lt; i ; j++){
                cnt++;
                if (i % j == 0){
                    isPrime = false;
                    break;
                }
            }
            if(isPrime == true){
                System.out.println(i);
            }
        }
        System.out.println(cnt);
    }
}</code></pre>
<h3 id="설명-1">설명</h3>
<p>2를 먼저 소수의 배열 primes에 넣어준다.
3부터 입력한 정수까지 홀수만 체킹을 하며 그 사이의 수로 모두 나누며 소수인지 판별한다.
위의 코드와 다르게 prime배열에 3을 먼저 넣어주고 5부터 판별해도 된다. (2, 3 모두 소수이기 때문)</p>
<hr>
<h2 id="다차원-배열">다차원 배열</h2>
<h3 id="다차원-배열의-초기화">다차원 배열의 초기화</h3>
<p>1번째 방법</p>
<pre><code class="language-java">int[][] scores = new int[3][4];</code></pre>
<p>2번째 방법</p>
<pre><code class="language-java">int[][] scores = {
                {90, 80, 77, 60}, // 첫 번째 학생의 점수
                {80, 70, 60, 50}, // 두 번째 학생의 점수
                {70, 60, 50, 40} // 세 번째 학생의 점수
        };</code></pre>
<hr>
<h2 id="클래스-1">클래스</h2>
<p>클래스는 기본적으로 도면이라고 생각하면된다.
클래스를 인스턴스화 하면 객체가 되는 것이다.</p>
<blockquote>
<p>클래스 → 자동차를 만드는 도면
객체 → 도면을 가지고 만든 나의 자동차</p>
</blockquote>
<pre><code class="language-java">public class Dog {
    String breed;
    int age;
    String color;

    public Dog() {
        //기본 생성자
    }

    public Dog(String breed, int age, String color) {
        this.breed = breed;
        this.age = age;
        this.color = color;
    }

    public Dog(String breed, String color) {
        this.breed = breed;
        this.color = color;
    }

    //메소드
    //접근제한자 리턴타입 메소드명 (매개변수들...)
    static void bark(){
        System.out.println(&quot;Woof!&quot;);
    }
    void displayInfo(){
        System.out.println(&quot;Breed: &quot; + breed + &quot; Age: &quot; + age + &quot; Color: &quot; + color);
    }

    //getter, settter
    public String getBreed() {
        return breed;
    }

    public int getAge() {
        return age;
    }

    public String getColor() {
        return color;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }

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

    public void setColor(String color) {
        this.color = color;
    }
}</code></pre>
<h3 id="설명-2">설명</h3>
<p>강아지 클래스이다. 
즉, 강아지를 만들 수 있는 도면을 만든 것이라고 생각하면 된다.
기본적으로 생성자를 만들지 않으면 자바에서는 기본 생성자를 제공해준다.
위의 코드에서는 “기본생성자”, “품종과 나이, 색깔이 모두 들어간 생성자”, “품종과 색깔만 들아간 생성자” 3 종류가 있다.
위의 <strong>메소드</strong>를 보면 <code>bark()</code>와 <code>displayInfo()</code>가 있다. 
<code>bark()</code>는 static이 붙은 클래스 메소드이다.
<code>displayInfo()</code>는 static이 붙지 않은 인스턴스 메소드이다.
static이 붙은 클래스 메소드는 객체를 생성하지 않아도 사용이 가능하다.
하지만 static이 붙지 않은 인스턴스 메소드는 객체를 생성해야만 사용이 가능하다.</p>
<p>ex. 객체 생성 코드</p>
<pre><code class="language-java">public class DogTest {
    public static void main(String[] args) {
        Dog.bark();

        Dog myDog = new Dog(); //Dog 타입의 myDog를 인스턴스화
        myDog.setAge(3);
        myDog.setBreed(&quot;말티즈&quot;);
        myDog.setColor(&quot;흰색&quot;);
        myDog.age=6;
        myDog.displayInfo();

        Dog myDog2 = new Dog(&quot;포메&quot;, 4, &quot;검정색&quot;);
        myDog2.displayInfo();

        Dog myDog3 = new Dog(&quot;포메&quot;, &quot;흰색&quot;);
        myDog3.displayInfo();
    }
}</code></pre>
<h3 id="설명-3">설명</h3>
<p>위의 코드는 <code>Dog클래스</code>의 객체를 생성해서 사용하는 <code>DogTest클래스</code>이다.
<code>bark()</code> 메소드를 보면 객체를 생성하지 않고 Dog클래스에 바로 접근해서 사용이 가능하다.
위에서 언급했듯이 static 키워드가 붙은 클래스 메소드이기 때문이다.
하지만 <code>displayInfo()</code> 메소드는 객세를 생성한 후 객체에 접근해서 사용이 가능하다.
static이 붙지 않은 인스턴스 메소드이기 때문이다.</p>
<hr>
<h2 id="선형-검색linear-search">선형 검색(Linear Search)</h2>
<h3 id="선형검색">선형검색</h3>
<p>원하는 값을 찾기 위해서 배열의 첫번째 요소부터 마지막 요소까지 차례대로 모두 확인하는 방법</p>
<pre><code class="language-java">import java.util.Scanner;

public class SearchExam {
    static int sequentialSearch(int[] arr, int key){
        for (int i = 0; i &lt; arr.length; i++) {
            if (arr[i] == key)
                return i; // 키와 일치하는 요소의 인덱스 반환
        }
        return -1; // 검색 실패 시 -1 반환
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;찾고자하는 정수를 입력하세요: &quot;);
        int key = sc.nextInt();
        int[] arr = {1,3,5,33,56,2,44};

        int index = sequentialSearch(arr, key);

        if (index != -1){
            System.out.println(&quot;당신이 찾는 데이터는 &quot; +index+&quot;번째 인덱스에 있습니다.&quot;);
        }else {
            System.out.println(&quot;당신이 찾는 데이터가 존재하지 않습니다.&quot;);
        }
    }
}</code></pre>
<h3 id="설명-4">설명</h3>
<p>찾고자 하는 값을 입력하면 <code>sequentialSearch()</code> 메소드에서 배열의 첫번째 요소부터 마지막 요소까지 순차적으로 확인을 한다. 도중에 원하는 값을 찾으면 값이 위치하는 요소의 인덱스를 반환한다.</p>
<h3 id="선형-검색보초법">선형 검색(보초법)</h3>
<ul>
<li><p>선형 검색 알고리즘을 개선한 방법</p>
</li>
<li><p>보초법(Sentinel Method)은 선형 검색에서 조건 검사의 횟수를 줄이기 위해 배열의 마지막에 검색하고자 하는 값을 “보초”로 추가하는 기법이다.</p>
</li>
<li><p>보초는 검색하고자 하는 키 값과 동일한 값을 배열의 맨 끝에 추가함으로써, 배열을 순회하는 동안 매번 배열의 끝에 도달했는지 확인하는 조건 검사를 생략할 수 있게 해준다.</p>
</li>
<li><p><strong>선형 검색(보초법)의 작동 원리</strong></p>
<ol>
<li>검색하고자 하는 키 값을 배열의 마지막에 추가한다(보초).</li>
<li>배열의 첫 번째 요소부터 시작하여 키 값과 일치하는 요소를 찾는다.</li>
<li>배열 내에 키 값과 일치하는 요소가 있으면 그 위치를 반환한다.</li>
<li>보초 덕분에, 배열의 끝에 도달했는지 확인할 필요 없이 보초 값에 도달할 때까지 반복할 수 있다.</li>
<li>배열 내에 키 값과 일치하는 원래의 요소가 없는 경우, 반복은 보초에 의해 종료된다. 이 때, 보초의 위치(즉, 배열의 맨 끝)가 반환되므로, 이를 통해 검색 실패를 판단할 수 있다.</li>
</ol>
</li>
<li><p><strong>장점</strong></p>
<ul>
<li>배열의 끝을 체크하는 조건 검사가 불필요하여, 약간의 성능 향상을 기대할 수 있다.</li>
<li>코드가 더 간결해지고 이해하기 쉬워진다.</li>
</ul>
</li>
<li><p><strong>단점</strong></p>
</li>
</ul>
<ol>
<li><p><strong>배열 수정</strong></p>
<ul>
<li>원래의 배열을 수정해 보초 값을 추가해야 한다.<pre><code>  → 배열의 크기를 변경하거나 추가적인 메모리 공간을 사용해야 할 수 있다.</code></pre></li>
</ul>
</li>
<li><p><strong>검색 대상 제한</strong></p>
<ul>
<li>검색하려는 키 값이 배열 내에 존재하지 않을 때 효율적이다.</li>
<li>그러나 배열 내에 키 값과 일치하는 요소가 여러 개 있는 경우, 보초법을 사용해도 첫 번쨰 일치하는 요소를 찾은 후 검색을 멈추므로, 모든 일치하는 요소를 찾는 데에는 추가적인 로직이 필요하다.</li>
</ul>
</li>
<li><p><strong>특정 상황에서의 성능 이점 부족</strong></p>
</li>
<li><p><strong>보초 값의 선택</strong></p>
<ul>
<li>보초 값을 배열에 추가하기 위해서는 보초 값이 원래 배열 내의 어떤 값과도 중복되지 않아야 한다.</li>
<li>찾고자 하는 값(key)를 마지막 배열 요소에 추가</li>
<li><blockquote>
<p>배열의 크기를 벗어났는지 체크하지 않다도 됨</p>
</blockquote>
</li>
<li>즉, for문을 사용하지 않고 while문을 사용하여 구현 가능</li>
</ul>
</li>
</ol>
<pre><code class="language-java">import java.util.Scanner;

public class LinearSearchSentinel {
    // 배열 arr에서 key와 일치하는 요소를 보초법을 사용하여 선형 검색
    static int linearSearchSentinel(int[] arr, int size, int key) {
        int i = 0;
        arr[size] = key; // 보초 추가

        while (true) {
            if (arr[i] == key)
                break;
            i++;
        }
        return i == size ? -1 : i;
    }

    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);

        System.out.print(&quot;요소 개수: &quot;);
        int num = stdIn.nextInt();
        int[] array = new int[num + 1]; // 요소 개수가 num + 1인 배열로, 마지막은 보초용

        for (int i = 0; i &lt; num; i++) {
            System.out.print(&quot;array[&quot; + i + &quot;]: &quot;);
            array[i] = stdIn.nextInt();
        }

        System.out.print(&quot;찾을 값: &quot;); // 찾고자 하는 값 입력
        int key = stdIn.nextInt();

        int index =linearSearchSentinel(array, num, key); // 배열 array에서 key를 검색

        if (index == -1)
            System.out.println(&quot;찾는 값의 요소가 없습니다.&quot;);
        else
            System.out.println(&quot;찾는 값은 array[&quot; + index + &quot;]에 있습니다.&quot;);
    }
}
</code></pre>
<hr>
<h2 id="이진-검색binary-search">이진 검색(Binary Search)</h2>
<ul>
<li>이진 검색은 “분할 정복(Divide and Conquer)” 전략을 사용하여, 데이터가 정렬되어 있는 배열에서 중간 지점의 값을 키와 비교하여 검색 범위를 반으로 줄이면서 검색하는 방법이다.</li>
<li>이진 검색은 <strong>순차 검색에 비해 훨씬 빠른 검색 속도를 제공</strong>하지만, 검색 전에 배열이 정렬되어 있어야 한다.</li>
<li>작동원리<ol>
<li>배열의 중간 요소을 기준으로 원하는 키값이랑 같은지 확인한다.</li>
<li>중간 요소보다 키값이 크면 중간 요소와 마지막 요소의 중간 요소를 찾는다.</li>
<li>중간 요소보다 키값이 작으면 처음 요소와 중간 요소의 중간 요소를 찾는다.</li>
<li>이를 start 변수와 end 변수를 이용하여 start 변수가 end보다 커지면 탐색을 종료하고 그 전에 원하는 키값을 찾으면 키값이 들어있는 배열 요소의 인덱스를 반환한다.</li>
<li>이는 순차 탐색보다 빠르며 시간복잡도는logN이다.</li>
<li>이진 탐색은 배열이 무조건 정렬이 되어있어야된다.</li>
</ol>
</li>
</ul>
<pre><code class="language-java">import java.util.Arrays;
import java.util.Scanner;

public class BinarySearchExam {
    public static int binarySearch(int[] arr, int key){
        int start = 0;
        int end = arr.length - 1;

        while(start &lt;= end){
            int mid = (start + end) / 2;
            if (key == arr[mid]){
                return mid;
            } else if (key &gt; arr[mid]) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return -1;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;찾고자하는 정수를 입력하세요: &quot;);
        int key = sc.nextInt();
        int[] arr = {1,3,5,33,56,2,44};
        Arrays.sort(arr); //Arrays의 sort메소드를 사용하여 정렬
        System.out.println(Arrays.toString(arr));

        int index =binarySearch(arr, key);

        if (index != -1){
            System.out.println(&quot;당신이 찾는 데이터는 &quot; +index+&quot;번째 인덱스에 있습니다.&quot;);
        }else {
            System.out.println(&quot;당신이 찾는 데이터가 존재하지 않습니다.&quot;);
        }
    }
}</code></pre>
<ul>
<li><strong>장점</strong><ul>
<li><strong>효율성</strong><ul>
<li><code>O(log n)</code> 의 시간 복잡도를 가지며, 큰 데이터 집합에서도 빠른 검색 속도를 보장한다.</li>
</ul>
</li>
<li><strong>정렬된 데이터에 최적화</strong></li>
</ul>
</li>
<li><strong>단점</strong><ul>
<li><strong>데이터 정렬 필요</strong></li>
<li>동<strong>적 배열에서 비효율적</strong><ul>
<li>배열에 자주 삽입이나 삭제가 발생하는 경우, 배열을 정렬된 상태로 유지하는 데 추가 비용이 발생할 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL - 3월 19일 : 알고리즘 기초]]></title>
            <link>https://velog.io/@ch980113_/TIL-3%EC%9B%94-19%EC%9D%BC</link>
            <guid>https://velog.io/@ch980113_/TIL-3%EC%9B%94-19%EC%9D%BC</guid>
            <pubDate>Wed, 20 Mar 2024 06:55:00 GMT</pubDate>
            <description><![CDATA[<h1 id="1-알고리즘이란">1. 알고리즘이란?</h1>
<ul>
<li>어떤 문제를 해결하기 위한 명확한 절차나 일련의 단계</li>
<li>컴퓨터 과학에서 알고리즘은 특정 작업을 수행하거나 문제를 해결하기 위해 정의된, 컴퓨터가 따라야 할 명령의 집합이다.</li>
</ul>
<ol>
<li><strong>명확성</strong> : 알고리즘의 각 단계는 명확하고 이해하기 쉬워야 한다.</li>
<li><strong>입력</strong> : 하나 이상의 입력이 있어야 한다.</li>
<li><strong>출력</strong> : 하나 이상의 출력이 있으며, 이는 주어진 입력에 대한 해답이다.</li>
<li><strong>유한성</strong> : 유한한 수의 단계를 거쳐서 종료되어야 한다.</li>
<li><strong>효율성</strong> : 실행 시간과 사용하는 자원(메모리 등) 측면에서 효율적이어야 한다.</li>
<li><strong>일반성</strong> : 특정 문제 뿐만 아니라 문제의 범주에 속하는 다양한 문제를 해결할 수 있어야 한다.</li>
</ol>
<ul>
<li>알고리즘은 일상 생활의 다양한 문제를 해결하는 데 사용될 수 있으며,</li>
<li>수학적 계산, 데이터 처리, 자동화된 추론, 컴퓨터 프로그래밍 등 다양한 분야에서 중요한 역할을 한다.</li>
</ul>
<hr>
<h2 id="세-값의-최댓값-구하기">세 값의 최댓값 구하기</h2>
<ul>
<li>세 개의 정수 값을 입력받아 그 중 가장 큰 값을 찾아내는 간단한 알고리즘</li>
<li>비교 연산자를 사용하여 각 값을 서로 비교</li>
</ul>
<pre><code class="language-java">public class MaxValue {
    // 세 개의 정수 a,b,c 중 최대값을 구하여 반환하는 메소드
    public static int max(int a, int b, int c) {
        int max = (a &gt; b) ? a : b;
        max = (b &gt; c) ? b : c;

        return max;
    }

    // main
    public static void main(String[] args) {
        System.out.println(&quot;최대값 : &quot; + max(5, 3, 6));
    }
}</code></pre>
<hr>
<h2 id="숫자와-문자열-입력하기-1">숫자와 문자열 입력하기 1</h2>
<h3 id="scanner를-이용한-숫자와-문자열-입력">Scanner를 이용한 숫자와 문자열 입력</h3>
<ul>
<li><code>Scanner</code> 클래스는 <code>java.util</code> 패키지에 포함되어 있으며, 다양한 형태의 입력(문자열, 정수, 실수 등)을 처리할 수 있다.</li>
</ul>
<pre><code class="language-java">import java.util.Scanner;

public class InputExample {
    public static void main(String[] args) {
        // Scanner 객체 생성
        Scanner scanner = new Scanner(System.in);

        // 사용자로부터 정수 입력받기
        System.out.print(&quot;정수를 입력하세요: &quot;);
        int number = scanner.nextInt();

        // 입력 버퍼 비우기 (줄바꿈 문자 제거)
        scanner.nextLine();

        // 사용자로부터 문자열 입력받기
        System.out.print(&quot;문자열을 입력하세요: &quot;);
        String text = scanner.nextLine();

        // 입력받은 정수와 문자열 출력
        System.out.println(&quot;입력받은 정수: &quot; + number);
        System.out.println(&quot;입력받은 문자열: &quot; + text);

        // Scanner 객체 닫기
        scanner.close();
    }
}</code></pre>
<hr>
<h2 id="scanner-클래스의-입력-메소드들">Scanner 클래스의 입력 메소드들</h2>
<ol>
<li><p><code>nextInt()</code> : 정수 (int) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>범위: <code>-2,147,483,648</code> 에서 <code>2,147,483,647</code> 까지 ( -2^31 에서 2^31 - 1 )</li>
</ul>
</li>
<li><p><code>nextLong()</code> : 긴 정수 (long) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>범위: <code>-9,223,372,036,854,775,808</code> 에서 <code>9,223,372,036,854,775,807</code> 까지
( <code>-2^63</code> 에서 <code>2^63 - 1</code> )</li>
</ul>
</li>
<li><p><code>nextFloat()</code> : 부동 소수점 (float) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>범위: 대략 <code>-3.4028235E+38</code> 에서 <code>3.4028235E+38</code> 까지</li>
</ul>
</li>
<li><p><code>nextDouble()</code> : 더블 정밀도의 부동 소수점 (double) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>범위: 대략 <code>-1.7976931348623157E+308</code> 에서 <code>1.7976931348623157E+308</code> 까지</li>
</ul>
</li>
<li><p><code>nextBoolean()</code> : 불리언 (boolean) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>이 메소드는 <code>true</code> 또는 <code>false</code> 문자열에 대해 대소문자를 구분하지 않는다.</li>
</ul>
</li>
<li><p><code>nextByte()</code> : 바이트 (byte) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>범위: <code>-128</code> 에서 <code>127</code> 까지 ( <code>-2^7</code> 에서 <code>2^7 - 1</code> )</li>
</ul>
</li>
<li><p><code>nextShort()</code> : 짧은 정수 (short) 타입의 데이터를 읽어들인다.</p>
<ul>
<li>범위: <code>-32,768</code> 에서 <code>32,767</code> 까지 ( <code>-2^15</code> 에서 <code>2^15 - 1</code> )</li>
</ul>
</li>
<li><p><code>next()</code> : 다음 토큰을 문자열로 읽어들인다.</p>
<ul>
<li>이 메소드는 공백으로 구분된 단어를 반환한다.</li>
</ul>
</li>
<li><p><code>nextLine()</code> : 줄의 끝까지 문자열을 읽어들인다.</p>
<ul>
<li>이 메소드는 한 줄 전체를 입력으로 받으며, 줄바꿈 문자를 읽은 후에 제거한다.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="메서드의-반환값과-메서드의-호출식의-평가">메서드의 반환값과 메서드의 호출식의 평가</h2>
<ul>
<li>자바 프로그래밍에서 메서드는 특정 작업을 수행하는 코드의 묶음이다.</li>
<li>메서드는 입력(매개변수)을 받아 처리하고, 결과를 반환(return)한다.</li>
</ul>
<h3 id="메서드의-반환값">메서드의 반환값</h3>
<ul>
<li><p>메서드가 작업을 완료한 후 결과를 호출한 곳으로 전달할 때 사용하는 값</p>
</li>
<li><p>반환값의 타입은 메서드를 정의할 때 지정하며, 반환값이 없는 경우에는 <code>void</code> 를 사용한다.</p>
</li>
<li><p>반환값이 있는 메서드는 <code>return</code> 키워드를 사용하여 결과값을 반환한다.</p>
<pre><code class="language-java">  접근제한자 &lt;static&gt; 반환타입 메서드명(매개변수) {..구현..}</code></pre>
</li>
</ul>
<h3 id="메서드-호출식의-평가">메서드 호출식의 평가</h3>
<ul>
<li>메서드 호출은 메서드가 실행되어야 함을 나타내며, 메서드 호출식은 그 호출이 평가되는 과정을 말한다.</li>
<li>메서드 호출식의 평가 결과 = 메서드의 반환값</li>
</ul>
<h3 id="반환값과-메서드-호출식의-중요성">반환값과 메서드 호출식의 중요성</h3>
<ul>
<li><p><strong>코드 재사용성 향상</strong></p>
<ul>
<li>메서드를 통해 코드를 분리함으로써, 같은 코드를 반복해서 작성할 필요 없이 메서드 호출을 통해 재사용할 수 있다.</li>
</ul>
</li>
<li><p><strong>프로그램의 구조화</strong></p>
<ul>
<li>메서드를 사용하여 프로그램을 작은 단위로 나눔으로써, 코드의 가독성과 관리가 용이해진다.</li>
</ul>
</li>
<li><p><strong>데이터 흐름의 명확성</strong></p>
<ul>
<li>메서드의 반환값을 통해 데이터가 어떻게 처리되고 전달되는지 명확하게 할 수 있다.</li>
</ul>
</li>
<li><p><strong>ex) 최댓값 반환 메서드</strong></p>
<pre><code class="language-java">  public static int max(int x, int y) {
      if (x &gt; y) {
          return x;
      } else {
          return y;
      }
  }

  public static void main(String[] args) {
      int a = 10;
      int b = 20;
      int maxValue = max(a, b);
      System.out.println(&quot;최대값: &quot; + maxValue);
  }</code></pre>
</li>
</ul>
<hr>
<h2 id="결정트리">결정트리</h2>
<p><img src="https://velog.velcdn.com/images/ch980113_/post/4df8f603-43ac-4367-9839-100f5d63ce13/image.png" alt=""></p>
<ul>
<li>결정트리는 복잡한 조건과 다양한 경우의 수를 시각적으로 표현하여 이해를 돕는다.</li>
<li>프로그래밍에서 결정트리를 사용하면 코드의 흐름을 명확하게 계획하고, 효율적인 알고리즘을 설계할 수 있다.</li>
</ul>
<hr>
<h2 id="세-값의-대소-관계와-중앙값">세 값의 대소 관계와 중앙값</h2>
<ul>
<li><p>특정한 데이터 집합 내에서 중앙값(median)을 찾는 것은 중요한 작업 중 하나이다.</p>
</li>
<li><p><strong>알고리즘 설명</strong></p>
<ol>
<li><p>a 와 b 를 비교하여, a 가 더 큰 경우 b 와 c 를 비교한다. b 가 더 크면 b 가 중앙값이다. 아니면 a 와 c 를 비교하여 더 작은 값이 중앙값이 된다.</p>
</li>
<li><ol start="2">
<li>a 가 b 보다 작은 경우 a 와 c 를 비교한다. a 가 더 크면 a 가 중앙값이다. 아니면 b 와 c 를 비교하여 더 작은 값이 중앙값이 된다.</li>
</ol>
<pre><code class="language-java">// 3개의 정숫값을 입력하고 중앙값을 구하여 출력
import java.util.Scanner;

public class Median {
 static int med3(int a, int b, int c) {
     if (a &gt;= b)
         if (b &gt;= c)
             return b;
         else if (a &lt;= c)
             return a;
         else
             return c;
     else if (a &gt; c)
         return a;
     else if (b &gt; c)
         return c;
     else
         return b;
 }

 public static void main(String[] args) {
     Scanner stdIn = new Scanner(System.in);

     System.out.println(&quot;세 정수의 중앙값을 구합니다.&quot;);
     System.out.print(&quot;a 값 : &quot;);
     int a = stdIn.nextInt();
     System.out.print(&quot;b 값 : &quot;);
     int b = stdIn.nextInt();
     System.out.print(&quot;c 값 : &quot;);
     int c = stdIn.nextInt();

     System.out.println(&quot;중앙값은 &quot; + med3(a, b, c) + &quot;입니다.&quot;);
 }
}</code></pre>
</li>
</ol>
</li>
</ul>
<hr>
<h2 id="조건-판단과-분기">조건 판단과 분기</h2>
<ul>
<li><p>조건 판단과 분기는 프로그램의 흐름을 제어하는 중요한 요소이다.</p>
</li>
<li><p>사용자의 입력이나 계산 결과에 따라 다른 작업을 실행할 수 있도록 하는 기능을 제공</p>
<p>  → 프로그램은 더 유연하고 다양한 상황에 대응할 수 있게 된다.</p>
</li>
</ul>
<blockquote>
<p>조건문을 통해 프로그램의 로직을 세분화하고, 사용자의 입력이나 계산 결과에 따라 다르게 반응하도록 설계할 수 있다.</p>
</blockquote>
<hr>
<h2 id="연산자와-피연산자">연산자와 피연산자</h2>
<ul>
<li>프로그램에서 데이터를 처리하고 조작하는 데 사용되는 기본적인 구성 요소</li>
<li><strong>연산자</strong> : 피연산자에 대해 수행될 연산(ex: +, -, &gt; 등)을 나타내는 기호나 키워드</li>
<li><strong>피연산자</strong> : 연산이 수행될 데이터(ex: 변수, 리터럴 값 등)</li>
</ul>
<h3 id="연산자의-종류">연산자의 종류</h3>
<ol>
<li><strong>산술 연산자</strong><ul>
<li><code>+</code> , <code>-</code> , <code>*</code> , <code>/</code> , <code>%</code></li>
</ul>
</li>
<li><strong>비교 연산자</strong><ul>
<li><code>==</code> , <code>!=</code> , <code>&lt;</code> , <code>&gt;</code> , <code>&lt;=</code> , <code>&gt;=</code></li>
</ul>
</li>
<li><strong>논리 연산자</strong><ul>
<li><code>&amp;&amp;</code> , <code>||</code> , <code>!</code></li>
</ul>
</li>
<li><strong>할당 연산자</strong> : 변수에 값을 할당하는 데 사용<ul>
<li><code>=</code> , <code>+=</code> , <code>-=</code> , <code>*=</code> , <code>/=</code></li>
</ul>
</li>
<li><strong>증감 연산자</strong><ul>
<li><code>++</code> , <code>--</code></li>
</ul>
</li>
<li><strong>조건 연산자</strong>(삼항 연산자)<ul>
<li><code>? :</code> (조건식 ? 값1 : 값2)</li>
</ul>
</li>
<li><strong>비트 연산자</strong><ul>
<li><code>&amp;</code> , <code>|</code> , <code>^</code> , <code>~</code> , <code>&lt;&lt;</code> , <code>&gt;&gt;</code></li>
</ul>
</li>
</ol>
<hr>
<h2 id="순서도의-기호">순서도의 기호</h2>
<ul>
<li>순서도(flowchart)는 프로그램이나 시스템의 흐름을 도식화하여 나타내는 그래픽 표현이다.</li>
</ul>
<ol>
<li><p><strong>시작/종료 (Terminator)</strong></p>
<ul>
<li><p>시작과 종료를 나타내는 기호, 타원형 또는 둥근 모서리의 사각형으로 표현된다.</p>
</li>
<li><p>프로세스의 시작과 끝을 명확하게 한다.</p>
<p>  <img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/c69962b0-3951-485b-b10a-5bb29576bba8/ded10f09-3af2-4bc6-bf0d-a2af14f00eb2/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
<li><p><strong>처리 (Process)</strong></p>
<ul>
<li><p>일반적인 처리 단계를 나타내며, 사각형으로 표현된다.</p>
</li>
<li><p>계산이나 데이터 처리 등의 작업을 나타낼 때 사용한다.</p>
<p>  <img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/c69962b0-3951-485b-b10a-5bb29576bba8/2c177747-96b3-43ce-88d4-d0c1c04007e0/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
<li><p><strong>결정 (Decesion)</strong></p>
<ul>
<li><p>조건 분기를 나타내며, 다이아몬드(마름모) 형태로 표현된다.</p>
<p>  <img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/c69962b0-3951-485b-b10a-5bb29576bba8/d89df272-c6a5-4d98-9eb8-e8517ba0aa34/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
<li><p><strong>입력/출력 (Input/Output)</strong></p>
<ul>
<li><p>입력 또는 출력을 나타내며, 평행사변형으로 표현된다.</p>
<p>  <img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/c69962b0-3951-485b-b10a-5bb29576bba8/749153a5-da23-4f15-ab44-5b65e2303b74/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
<li><p><strong>순차적 연결 (Flowline)</strong></p>
<ul>
<li>화살표는 흐름의 방향을 나타낸다. 처리의 순서와 흐름의 방향을 명확하게 표시한다.</li>
<li>실선, 점선, 파선(긴 선과 짧은 선을 3:1의 비율로 이은 선)</li>
</ul>
</li>
<li><p><strong>서브루틴/프로세스 참조 (Predefined Process)</strong></p>
<ul>
<li><p>하위 프로세스 또는 서브루틴을 나타내며, 더블 사각형으로 표현된다.</p>
</li>
<li><p>재사용 가능한 코드 블록이나 함수 호출을 나타낼 때 사용한다.</p>
<p>  <img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/c69962b0-3951-485b-b10a-5bb29576bba8/d9e8b996-6bdf-451e-bf26-980133014307/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
</ol>
<hr>
<h1 id="2-반복">2. 반복</h1>
<h2 id="1부터-n까지-정수의-합-구하기">1부터 n까지 정수의 합 구하기</h2>
<ul>
<li>기본적인 반복문 사용법을 익히는 좋은 예제</li>
</ul>
<pre><code class="language-java">import java.util.Scanner;

class SumWhile {
    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);

        System.out.println(&quot;1부터 n까지의 합을 구합니다.&quot;);
        System.out.print(&quot;n값: &quot;);
        int n = stdIn.nextInt();

        int sum = 0; // 합
        int i = 1;

        while (i &lt;= n) { // i가 n 이하면 반복
            sum += i; // sum에 i를 더함
            i++; // i 값을 1 증가(increment)
        }
        System.out.println(&quot;1부터 &quot; + n + &quot;까지의 합은 &quot; + sum + &quot;입니다.&quot;);
    }
}</code></pre>
<hr>
<h2 id="연습문제">연습문제</h2>
<h3 id="1---1부터-n까지의-정수-중-짝수들의-합-구하기">1 - 1부터 n까지의 정수 중 짝수들의 합 구하기</h3>
<pre><code class="language-java">import java.util.Scanner;

public class SumEven {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n, sum = 0;

        System.out.print(&quot;정수 n을 입력하세요 : &quot;);
        n = sc.nextInt();

        for (int i = 1; i &lt;= n; i++) {
            if (i % 2 == 0)
                sum += i;
        }
        System.out.println(&quot;n까지의 짝수의 합 : &quot; + sum);
    }
}</code></pre>
<h3 id="2---1부터-n까지의-정수-중-3의-배수의-합-구하기">2 - 1부터 n까지의 정수 중 3의 배수의 합 구하기</h3>
<pre><code class="language-java">import java.util.Scanner;

public class Sum3Drainage {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n, sum = 0;

        System.out.print(&quot;정수 n을 입력하세요 : &quot;);
        n = sc.nextInt();

        for (int i = 1; i &lt;= n; i++) {
            if (i % 3 == 0)
                sum += i;
        }
        System.out.println(&quot;n까지의 3의 배수의 합 : &quot; + sum);
    }
}</code></pre>
<hr>
<h2 id="✔-구조적-프로그래밍---논리연산과-드모르간-법칙">✔ 구조적 프로그래밍 - 논리연산과 드모르간 법칙</h2>
<h3 id="두-자리-양의-정수-입력받기">두 자리 양의 정수 입력받기</h3>
<pre><code class="language-java">import java.util.Scanner;

public class TwoDigits {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n;

        System.out.println(&quot;두자리 양의 정수를 입력해주세요.&quot;);

        do {
            System.out.print(&quot;정수값 입력 : &quot;);
            n = sc.nextInt();
        } while (n &lt; 10 || n &gt; 99);

        System.out.println(&quot;입력한 숫자는 &quot; + n + &quot;입니다.&quot;);
    }
}</code></pre>
<h3 id="논리연산자">논리연산자</h3>
<ul>
<li>주로 boolean 타입의 피연산자를 가지며, 조건문이나 반복문 내에서 조건의 조합을 평가하는 데 사용된다.</li>
<li>논리연산자는 표현식의 진리값을 결정하기 위해 사용되며, 주로 두 조건이나 표현식을 결합할 때 활용된다.</li>
<li><code>&amp;&amp;</code> , <code>||</code> , <code>!</code> , <code>^</code></li>
</ul>
<h3 id="드모르간-법칙">드모르간 법칙</h3>
<ol>
<li><strong>NOT (A AND B) = (NOT A) OR (NOT B)</strong></li>
<li><strong>NOT (A OR B) = (NOT A) AND (NOT B)</strong></li>
</ol>
<ul>
<li>논리연산의 부정과 결합을 다룰 때, 특히 조건문이나 논리식을 간소화하는 데 유용하게 사용된다.</li>
</ul>
<hr>
<h2 id="다중루프---구구단">다중루프 - 구구단</h2>
<pre><code class="language-java">public class Multi99Table {
    public static void main(String[] args) {
        System.out.println(&quot;------- 구구단 곱셈표 -------&quot;);

        for (int i = 1; i &lt; 10; i++) {
            for (int j = 1; j &lt; 10; j++) {
                System.out.printf(&quot;%d * %d =%2d  &quot;, i, j, i * j);
            }
            System.out.println();
        }
    }
}</code></pre>
<hr>
<h2 id="다중루프---직각-이등변-삼각형-출력">다중루프 - 직각 이등변 삼각형 출력</h2>
<pre><code class="language-java">import java.util.Scanner;

public class TriangleLB {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n;

        do {
            System.out.print(&quot;직각 이등변 삼각형의 단 수를 입력해주세요 : &quot;);
            n = sc.nextInt();
        } while (n &lt;= 0);

        for (int i = 0; i &lt;= n; i++) {
            for (int j = 1; j &lt;= i; j++) {
                System.out.print(&quot;*&quot;);
            }
            System.out.println();
        }
    }
}</code></pre>
<hr>
<h2 id="이등변-삼각형-출력">이등변 삼각형 출력</h2>
<pre><code class="language-java">import java.util.Scanner;

public class TriangleLB2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n;

        do {
            System.out.print(&quot;이등변삼각형의 단 수를 입력해주세요 : &quot;);
            n = sc.nextInt();
        } while (n &lt;= 0);

        for (int i = 0; i &lt; n; i++) {
            for (int j = 0; j &lt; n - i; j++)
                System.out.print(&quot; &quot;);
            for (int j = 0; j &lt; (i*2+1); j++)
                System.out.print(&quot;*&quot;);
            System.out.println();
        }
    }
}</code></pre>
<hr>
<h1 id="2-1-배열">2-1. 배열</h1>
<ul>
<li>유틸리티 메서드<pre><code>  1. **`toString()`**: 배열의 내용을 문자열로 변환하여 반환 . 주로 디버깅 목적으로 사용
  2. **`sort()`**: 배열을 정렬. 기본적으로는 오름차순으로 정렬, 오브젝트 배열의 경우에는 해당 객체들이 구현한 Comparable 인터페이스의 compareTo() 메서드에 따라 정렬.
  3. **`binarySearch()`**: 지정된 값의 위치를 찾음. 이 메서드를 사용하기 전에 배열이 반드시 정렬되어 있어야 함.
  4. **`copyOf()`**: 지정된 길이로 배열을 복사.
  5. **`copyOfRange()`**: 배열의 지정된 범위를 복사.
  6. **`fill()`**: 배열의 모든 요소를 지정된 값으로 설정.
  7. **`equals()`**: 두 배열이 같은지 비교.
  8. **`asList()`**: 배열을 고정 크기의 리스트로 변환.</code></pre></li>
</ul>
<hr>
<h2 id="배열의-클론복제">배열의 클론(복제)</h2>
<pre><code class="language-java">import java.util.Arrays;

public class DuplicateArray {
    public static void main(String[] args) {
        int[] original = {10, 20, 30, 40, 50};
        int[] copied = original.clone(); // copied는 original의 복제본을 참조

        copied[2] = 0; // copied 배열의 세 번째 요소를 0으로 변경

        System.out.println(&quot;original = &quot; + Arrays.toString(original));
        System.out.println(&quot;copied = &quot; + Arrays.toString(copied));
    }
}
/* 실행결과
original = [10, 20, 30, 40, 50]
copied = [10, 20, 0, 40, 50]
*/</code></pre>
<h2 id="배열요소의-최댓값-구하기">배열요소의 최댓값 구하기</h2>
<pre><code class="language-java">import java.util.Scanner;

public class MaxOfScores {
    static int maxOf(int[] scores) {
        int max = Integer.MIN_VALUE;
        for (int i = 0; i &lt; scores.length; i++) {
            if (scores[i] &gt; max)
                max = scores[i];
        }
        return max;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print(&quot;학생 수 입력 : &quot;);
        int n = sc.nextInt();
        int[] scores = new int[n];

        for (int i = 0; i &lt; n; i++) {
            System.out.print((i + 1) + &quot;번째 점수 입력 : &quot;);
            scores[i] = sc.nextInt();
        }

        System.out.println(&quot;최댓값 : &quot; + maxOf(scores));
    }
}
</code></pre>
<h2 id="난수-사용해-배열의-요솟값-설정하기">난수 사용해 배열의 요솟값 설정하기</h2>
<pre><code class="language-java">import java.util.Random;
import java.util.Scanner;

public class MaxOfWeightsRand {
    static int maxOf(int[] weights) {
        int max = weights[0];
        for (int i = 1; i &lt; weights.length; i++)
            if (weights[i] &gt; max)
                max = weights[i];
        return max;
    }

    public static void main(String[] args) {
        Random rand = new Random();
        Scanner sc = new Scanner(System.in);

        System.out.println(&quot;몸무게의 최댓값을 구합니다.&quot;);
        System.out.print(&quot;사람 수: &quot;);
        int num = sc.nextInt(); // 입력받은 사람 수로 배열의 크기를 결정
        int[] weights = new int[num]; // 사람 수만큼 몸무게를 저장할 배열 생성

        for (int i = 0; i &lt; num; i++) {
            weights[i] = 40 + rand.nextInt(60); // 몸무게를 40kg에서 100kg 사이의 난수로 결정
            System.out.println(&quot;weights[&quot; + i + &quot;] : &quot; + weights[i]);
        }
        System.out.println(&quot;최댓값은 &quot; + maxOf(weights) + &quot;입니다.&quot;);
    }
}</code></pre>
<ul>
<li><code>.nextInt()</code> : -2,147,483,648 ~ 2,147,483,647 사이의 값 (min ~ max)</li>
<li><code>.nextInt(60)</code> : 0~60 의 난수</li>
</ul>
<h2 id="배열을-역순으로-정렬하기">배열을 역순으로 정렬하기</h2>
<pre><code class="language-java">// 사용자로부터 입력받은 값으로 구성된 배열을 역순으로 정렬
import java.util.Arrays;
import java.util.Scanner;

class InvertArray {
    //--- 배열 요소 a[idx1]과 a[idx2]의 값을 교환 ---//
    static void swap(int[] a, int idx1, int idx2) {
        int temp = a[idx1];
        a[idx1] = a[idx2];
        a[idx2] = temp;
    }

    //--- 배열 a의 요소를 역순으로 정렬 ---//
    static void reverse(int[] a) {
        for (int i = 0; i &lt; a.length / 2; i++)
            swap(a, i, a.length - i - 1);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print(&quot;점수의 개수: &quot;);
        int num = sc.nextInt(); // 점수의 개수를 입력받음
        int[] scores = new int[num]; // 점수를 저장할 배열 생성

        for (int i = 0; i &lt; num; i++) {
            System.out.print(&quot;scores[&quot; + i + &quot;] : &quot;);
            scores[i] = sc.nextInt(); // 점수 입력
        }

        reverse(scores); // 배열 scores의 요소를 역순으로 정렬

        System.out.println(&quot;점수를 역순으로 정렬했습니다.&quot;);
        System.out.println(&quot;scores = &quot; + Arrays.toString(scores));
    }
}</code></pre>
<h2 id="두-배열의-비교">두 배열의 비교</h2>
<pre><code class="language-java">public class CompareArrays {
    static boolean areArraysEqual(int[] arr1, int[] arr2) {
        if (arr1.length != arr2.length)
            return false;

        for (int i = 0; i &lt; arr1.length; i++) {
            if (arr1[i] != arr2[i])
                return false;
        }

        return true;
    }

    public static void main(String[] args) {
        // 테스트를 위한 두 배열 선언
        int[] array1 = {1, 2, 3, 4, 5};
        int[] array2 = {1, 2, 3, 4, 5};
        int[] array3 = {1, 2, 3, 4};

        // areArraysEqual 메소드를 사용하여 배열 비교
        System.out.println(&quot;array1과 array2는 동일한가? &quot; + areArraysEqual(array1, array2));
        System.out.println(&quot;array1과 array3는 동일한가? &quot; + areArraysEqual(array1, array3));
    }
}</code></pre>
<h2 id="기수변환">기수변환</h2>
<h3 id="분할과-나머지를-이용한-방법">분할과 나머지를 이용한 방법</h3>
<ul>
<li>10진수 29를 2진수로 변환 후 출력</li>
</ul>
<pre><code class="language-java">public class DecimalToBinaryExam {
    public static void main(String[] args) {
        int decimal = 29;
        StringBuilder binary = new StringBuilder();

        while (decimal &gt; 0) {
            binary.append(decimal % 2);
            decimal /= 2;
        }
        System.out.println(binary.reverse().toString());
    }
}</code></pre>
<hr>
<h1 id="2-2-stringbuilder">2-2. StringBuilder</h1>
<ul>
<li>StringBuilder / 배열</li>
</ul>
<p>: 문자열을 동적으로 조작하고 수정하는 데 사용됨. 
: 문자열의 변경이 필요한 상황</p>
<pre><code class="language-java">StringBuilder sb = new StringBuilder();

    // 문자열 추가
    sb.append(&quot;Hello&quot;);

    // 문자열 삽입
    sb.insert(5, &quot; &quot;);

    // 문자열 수정
    sb.replace(6, 10, &quot;World&quot;);

    // 문자열 삭제
    sb.delete(5, 6);

    // 문자열 출력
    System.out.println(sb.toString()); // 출력 결과: HelloWorld</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL - 3월 18일 : TDD]]></title>
            <link>https://velog.io/@ch980113_/TIL-3%EC%9B%94-18%EC%9D%BC-%EC%9B%94</link>
            <guid>https://velog.io/@ch980113_/TIL-3%EC%9B%94-18%EC%9D%BC-%EC%9B%94</guid>
            <pubDate>Tue, 19 Mar 2024 01:02:35 GMT</pubDate>
            <description><![CDATA[<h2 id="--tdd-사이클"><strong>- TDD 사이클</strong></h2>
<pre><code>1. 실패하는 테스트 작성 :  아직 구현되지 않은 기능에 대한 테스트를 먼저 작성
이 테스트는 당연히 실패할 것입니다.
2. 테스트를 통과하기 위한 코드 작성 : 테스트를 통과하기 위한 최소한의 코드를 작성
합니다.
3. 리팩토링 : 코드를 개선하고 중복을 제거합니다. 이 과정에서도 모든 테스트가 통과
해야 합니다.

이 사이클을 반복하면서 개발을 진행하게 되며, 이는 코드의 품질을 높이고 버그를 줄이
는 데 도움이 됩니다.</code></pre><ul>
<li><p>테스트 코드 작성 순서</p>
<ol>
<li><p>테스트 케이스 작성</p>
<ul>
<li>TDD의 핵심은 개발 시작 전에 테스트 케이스를 먼저 작성하는 것<pre><code class="language-java">import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
</code></pre>
</li>
</ul>
<p>public class DateCalculatorTest {</p>
<pre><code> private DateCalculator dateCalculator;

 @BeforeEach
 void setup() {
     dateCalculator = new DateCalculator();
 }

 @Test
 void testCalculateAge() {
     LocalDate birthDate = LocalDate.of(1990, 5, 15);
     LocalDate currentDate = LocalDate.of(2022, 2, 28);
     int expectAge = 32;
     int actualAge = dateCalculator.calculateAge(birthDate, currentDate);
     assertEquals(expectAge, actualAge);
 }

 @Test
 void testCalculateDaysBetween() {
     LocalDate startDate = LocalDate.of(2022, 2, 15);
     LocalDate endDate = LocalDate.of(2022, 3, 1);
     int expectedDays = 14;
     int actualDays = dateCalculator.calculateDaysBetween(startDate, endDate);
     assertEquals(expectedDays, actualDays);
 }

 @Test
 void testIsLeapYear() {
     int leapYear = 2024;
     boolean isLeap = dateCalculator.isLeapYear(leapYear);
     assertEquals(true,isLeap);
 }</code></pre><p> }</p>
<pre><code></code></pre></li>
<li><p>실패하는 테스트 실행</p>
<ul>
<li>테스트를 실행하면 DateCalculator 클래스가 존재하지 않기 때문에 실패</li>
</ul>
</li>
<li><p>구현 코드 작성</p>
<pre><code class="language-java">import java.time.LocalDate;

public class DateCalculator {
 public int calculateAge(LocalDate birthDate, LocalDate currentDate) {
     return currentDate.getYear() - birthDate.getYear();
 }

 public int calculateDaysBetween(LocalDate startDate, LocalDate endDate) {
     return (int) startDate.until(endDate).getDays();
 }

 public boolean isLeapYear(int year) {
     return LocalDate.ofYearDay(year, 1).isLeapYear();
 }
}</code></pre>
</li>
<li><p>테스트 실행 및 성공 확인</p>
<ul>
<li><p>테스트를 다시 실행하면 모두 성공</p>
</li>
<li><p>실패하지 않는 한 성공한 테스트를 기반으로 다음 단계로 진행</p>
</li>
</ul>
</li>
<li><p>코드 리팩토링</p>
<ul>
<li>필요한 경우 코드를 리팩토링하여 가독성을 높이고 중복을 제거</li>
</ul>
</li>
</ol>
</li>
</ul>
<p> ==============================================</p>
<ul>
<li><p>** @어노테이션 **</p>
<ul>
<li><p>약속을 정의하고 있고, 정해진 곳에 표시를 해주면 프레임워크가 실행할때 동작한다. </p>
</li>
<li><p>이미 정의되어 있는 것들이 많다.</p>
</li>
<li><p>TDD : 개발 방법론 중 하나. 테스트코드를 기반으로 개발하겠다</p>
</li>
</ul>
</li>
<li><p>테스트하는 도구로 JUnit 사용한다.</p>
<ul>
<li>JUnit : 자바에서 x유닛을 사용하는 것.</li>
</ul>
</li>
<li><p>단위테스트는 개발과정에 이루어져야한다.</p>
</li>
<li><p>Assertions 해당 조건에 맞았을 때 판단해줄 수 있는 부분.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL - 3월 15일 : Git fork, pull request]]></title>
            <link>https://velog.io/@ch980113_/TIL-3%EC%9B%94-15%EC%9D%BC</link>
            <guid>https://velog.io/@ch980113_/TIL-3%EC%9B%94-15%EC%9D%BC</guid>
            <pubDate>Tue, 19 Mar 2024 00:56:05 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>Git이랑 GitHub는 다른 개념</p>
<ol>
<li>git은 로컬 저장소에서 가지고 노는 느낌</li>
<li>github는 클라우드가 있어서 거기에 저장해서 사용할 수 있는 느낌</li>
</ol>
</li>
<li><p>Git 명령어 모음</p>
<ol>
<li><p><code>git init</code> </p>
<ul>
<li>현재 폴더를 Git 저장소로 생성</li>
<li>.git 폴더가 생성</li>
</ul>
</li>
<li><p><code>git status</code> </p>
<ul>
<li>현재 스테이징 영역에 있는 변경사항과 작업 디렉토리의 변경사항을 비교 가능</li>
</ul>
</li>
<li><p><code>git add .</code> </p>
<ul>
<li>모든 변경사항 스테이징 영역에 추가하기</li>
<li>git add &lt;파일&gt; <ul>
<li>특정 파일 스테이징 영역에 추가하기</li>
</ul>
</li>
</ul>
</li>
<li><p><code>git commit -m &quot;commit message&quot;</code> </p>
<ul>
<li>commit message 메시지 입력 후 커밋하기</li>
</ul>
</li>
<li><p><code>git pull</code> </p>
<ul>
<li>원격 저장소의 변경 사항을 작업 브랜치와 병합 : 파일 올리기</li>
</ul>
</li>
<li><p><code>git push</code> </p>
<ul>
<li>로컬 브랜치의 변경 사항을 원격 저장소와 병합 : 파일 내려받기</li>
</ul>
</li>
<li><p><code>git branch</code> </p>
<ul>
<li>현재 있는 모든 브랜치 나열하기</li>
</ul>
<ol start="8">
<li><code>git branch 브런치 이름</code> <ul>
<li>특정 브랜치 생성하기</li>
</ul>
</li>
</ol>
</li>
<li><p><code>git branch -d 브런치 이름</code> </p>
<ul>
<li>특정 브랜치 삭제하기 </li>
</ul>
</li>
</ol>
</li>
</ul>
<pre><code>10. ` git branch -m 새브런치 이름` 
    - 현재 브랜치 이름 변경하기


11. `git merge 브런치 이름 ` 
    - 현재 위차한 branch와 지정한 branch를 merge(병합)하기

13.  `git switch 브런치 이름` 
    - 다른 브랜치로 전환하기

8.  `git switch -c 생성할 branch명` 
    - branch 생성 후 해당 branch로 이동

1.  `git switch branch명` 
    - 해당 branch로 이동

12.  `git checkout branch명` (checkout을 사용해서 위와 같은 작업이 가능하다 ) 
    - 다른 브랜치로 전환하기

13. `git checkout -b blog-create`
    - blog-create 생성 후 브랜치 이동

13. `git push origin main` 

    - 로컬 branch의 변경 사항을 원격 저장소에 업로드함


1. ` git pull origin main ` 
    - 원격 저장소의 변경 사항을 현재의 작업 branch와 병합함

16.  `git clone` 
    - 다른 저장소 복제

17. `git diff (비교할 해시코드1) (비교할 해시코드2)` 
    - 해시코드1 과 해시코드 2의 내용을 비교해서 출력 </code></pre><p>=================================================</p>
<ul>
<li><p>기타 명령어</p>
<ol>
<li><p><code>ls</code> </p>
<ul>
<li>현재 디렉토리의 파일 목록 조회</li>
</ul>
</li>
<li><p><code>ls -la</code> </p>
<ul>
<li>현재 디렉토리의 히든 파일까지 포함하여 파일 목록 조회</li>
</ul>
</li>
<li><p><code>pwd</code> </p>
<ul>
<li>현재 작업 위치 풀력</li>
</ul>
</li>
<li><p><code>mkdir my_project</code>  </p>
<ul>
<li>mkdir 폴더명  </li>
<li>해당 폴더명으로 폴더 생성</li>
</ul>
</li>
<li><p><code>cp Hello.java Hi.java</code> </p>
<ul>
<li>파일 복사 </li>
<li>Hello.java 내용을 Hi.java에 복사</li>
</ul>
</li>
<li><p><code>cd my_project</code> </p>
<ul>
<li>해당 디렉토리로 이동</li>
</ul>
</li>
<li><p><code>cd ..</code>  </p>
<ul>
<li>상위 폴더로 이동</li>
</ul>
</li>
</ol>
</li>
</ul>
<ul>
<li><p>vi editer </p>
<ol>
<li><p><code>vi [Hello.java](http://Hello.java)</code></p>
<p>or </p>
</li>
<li><p><code>vim Hello.java</code></p>
<ul>
<li><p>Hello.java 편집 </p>
</li>
<li><p>해당 파일이 없으면 생성하고 편집</p>
</li>
<li><p><code>i</code>or <code>insert</code>누르고 입력 후 <code>esc</code>로 입력 종료</p>
</li>
<li><p><code>:wq</code> 입력하여  vi or vim 종료</p>
</li>
</ul>
</li>
</ol>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL - 3월 14일 : 배열]]></title>
            <link>https://velog.io/@ch980113_/TIL-3%EC%9B%94-14%EC%9D%BC</link>
            <guid>https://velog.io/@ch980113_/TIL-3%EC%9B%94-14%EC%9D%BC</guid>
            <pubDate>Tue, 19 Mar 2024 00:45:31 GMT</pubDate>
            <description><![CDATA[<h2 id="기본형-배열">기본형 배열</h2>
<ul>
<li>선언 여러가지 가능<pre><code class="language-java">ex1. 기본형타입[] 변수명;
ex2. 기본형타입 변수명[];
</code></pre>
</li>
</ul>
<pre><code>* 초기값 가지고 선언

```java
기본형타입[] 변수명 = new 기본형타입[배열의크기];
변수명[index값] = 값;
기본형타입[] 변수명 = new 기본형타입[]{ 값1, 값2, .... };
기본형타입[] 변수명 = {값1, 값2, 값3.... };</code></pre><hr>
<h2 id="참조형-배열">참조형 배열</h2>
<pre><code class="language-java">public class Array05 {
    public static void main(String[] args) {
        ItemForArray[] array1 = new ItemForArray[3];
        array1[0] = new ItemForArray(500, &quot;사과&quot;);
        array1[1] = new ItemForArray(300, &quot;바나나&quot;);
        array1[2] = new ItemForArray(900, &quot;수박&quot;);

        ItemForArray[] array2 = new ItemForArray[]{new ItemForArray(500, &quot;사과&quot;), new ItemForArray(300, &quot;바나나&quot;), new ItemForArray(900, &quot;수박&quot;)};
        ItemForArray[] array3 = {new ItemForArray(500, &quot;사과&quot;), new ItemForArray(300, &quot;바나나&quot;), new ItemForArray(900, &quot;수박&quot;)};

        System.out.println(array1[0].getName());
        System.out.println(array1[0].getPrice());
        System.out.println(array1[1].getName());
            System.out.println(array1[1].getPrice());
        System.out.println(array1[2].getName());
        System.out.println(array1[2].getPrice());
    }
}</code></pre>
<hr>
<h2 id="이차열-배열">이차열 배열</h2>
<ul>
<li>리스트</li>
</ul>
<pre><code class="language-java">    타입[][] 변수명 = new 타입[행의수][열의수];
    변수명[행인덱스][열인덱스] = 값;</code></pre>
<pre><code class="language-java">public class Array09 {
    public static void main(String[] args) {
        int[][] array = {{0,1,2}, {3,4,5}};

        for(int i = 0; i &lt; array.length; i++){
            for(int j = 0; j &lt; array[i].length; j++){
                System.out.print(array[i][j] + &quot;\t&quot;);
            }
            System.out.println();
        }
    }
}</code></pre>
<h3 id="이차원-가변-배열의-선언과-초기화">이차원 가변 배열의 선언과 초기화</h3>
<ul>
<li>가변 길이 : 두 개의 길이가 달라도 된다는 것을 의미</li>
</ul>
<pre><code class="language-java">    타입[][] 변수명 = new 타입[행의수][];
    변수명[행의인덱스] = new 타입[열의수];</code></pre>
<pre><code class="language-java">public class Array10 {
    public static void main(String[] args) {
        int[][] array = new int[2][];

        array[0] = new int[2];
        array[1] = new int[3];

        array[0][0] = 0;
        array[0][1] = 1;
        array[1][0] = 2;
        array[1][1] = 3;
        array[1][2] = 4;

        for(int i = 0; i &lt; array.length; i++){
            for(int j = 0; j &lt; array[i].length; j++){
                System.out.print(array[i][j] + &quot;\t&quot;);
            }
            System.out.println();
        }
    }
}</code></pre>
<ul>
<li><p>for each 문</p>
<pre><code class="language-java">public class Array12 {
  public static void main(String[] args) {

      int[] array = {1,2,3,4,5};

      for(int i : array){
          System.out.println(i);
      }
  }
}</code></pre>
</li>
</ul>
<p>// i는 index가 아닌 array안의 값</p>
<h3 id="명령-행-아규먼트">명령 행 아규먼트</h3>
<ul>
<li>리스트</li>
</ul>
<pre><code class="language-java">public class EmptyCommandLineArgumentExam {
    public static void main(String[] args){
        System.out.println(args.length);
    }
}</code></pre>
<h3 id="제한-없는-아규먼트">제한 없는 아규먼트</h3>
<ul>
<li>리스트</li>
</ul>
<pre><code class="language-java">public class UnlimitiedArgumentsExam {
    public static void main(String[] args){

        System.out.println(sum(5,10));
        System.out.println(sum(1,2,4,2));
        System.out.println(sum(3,1,2,3,4,1));
    }

    public static int sum(int... args){
        System.out.println(&quot;print1 메소드 - args 길이 : &quot; + args.length);
        int sum = 0;
        for(int i = 0; i &lt; args.length; i++){
            sum += args[i];
        }
        return sum;
    }
}

//print1 메소드 - args 길이 : 2
//15
//print1 메소드 - args 길이 : 4
//9
//print1 메소드 - args 길이 : 6
//14</code></pre>
<hr>
<h2 id="생성자">생성자</h2>
<ul>
<li><p>객체가 생성될때 자동으로 호출 되는 특수 목적의 메서드 </p>
</li>
<li><p>객체의 초기화를 위해 사용</p>
<pre><code class="language-java">public class Book {
  String title;
  int price;

  public Book() {    }                   // 기본생성자

  public Book(String title, int price) {    // 매개변수를 가진 생성자
      this.title = title;
      this.price = price;
  }
}</code></pre>
</li>
<li><p>생성자(Constructor)는 객체가 생성될때 자동으로 호출되는 특수 목적의 멤버함수(메소드)로객체의 초기화를 위해 사용</p>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>