<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kid_an.log</title>
        <link>https://velog.io/</link>
        <description>개발 공부!</description>
        <lastBuildDate>Wed, 28 Jan 2026 14:05:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kid_an.log</title>
            <url>https://velog.velcdn.com/images/kid_an/profile/cae2b9c9-867e-499f-a1a0-f6fbfceebcdf/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kid_an.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kid_an" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Redis란? 인메모리 데이터 구조 저장소)]]></title>
            <link>https://velog.io/@kid_an/Redis%EB%9E%80-%EC%9D%B8%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0-%EC%A0%80%EC%9E%A5%EC%86%8C</link>
            <guid>https://velog.io/@kid_an/Redis%EB%9E%80-%EC%9D%B8%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0-%EC%A0%80%EC%9E%A5%EC%86%8C</guid>
            <pubDate>Wed, 28 Jan 2026 14:05:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/kid_an/post/a1fc1689-910a-461d-8393-119c7536090b/image.png" alt=""></p>
<h2 id="redis란-무엇인가">Redis란 무엇인가</h2>
<p><strong>Key, Value</strong> 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비관계형 데이터베이스 관리 시스템 입니다.</p>
<p>비정형 데이터는 일정한 구조나 형식 없이 저장된 데이터를 의미하며 이러한 데이터들을 저장하고 관리하기 위한 관리 시스템이 <strong>Redis</strong>입니다.</p>
<br>

<h3 id="redis는-비관계형-데이터베이스">Redis는 비관계형 데이터베이스?</h3>
<p>비관계형 데이터베이스는 <strong>특정 데이터 모델에 대해 특정 목적에 맞추어 구축되는 데이터베이스</strong>로서 유연한 스키마를 갖추고 있습니다.</p>
<p>이러한 데이터베이스 유형은 큰 데이터 볼륨, 짧은 지연 시간과 유연한 데이터 모델이 필요한 애플리케이션에 최적화 되어 있습니다.</p>
<h3 id="관계형-데이터베이스와-차이점은">관계형 데이터베이스와 차이점은?</h3>
<p>데이터 저장 방법에 차이점이 있습니다.
관계형 데이터베이는 데이터를 행과 열이 있는 테이블 형식으로 저장합니다.</p>
<table>
<thead>
<tr>
<th align="center">PK</th>
<th align="center">COL1</th>
<th align="center">COL2</th>
</tr>
</thead>
<tbody><tr>
<td align="center">pk1</td>
<td align="center">a</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">pk2</td>
<td align="center">b</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">pk3</td>
<td align="center">c</td>
<td align="center">3</td>
</tr>
</tbody></table>
<br>

<p>비관계형 데이터베이스는 데이터에 엑세스하고 관리하기 위해 다양한 데이터 모델을 사용합니다.
스키마가 없기 때문에 관계형 데이터베이스에서 요구되는 제약 조건 없이 저장됩니다.</p>
<p>대표적으로 <strong>Key, Value</strong> 형태로 저장하며 이때 Key값은 고유 식별자 역할을 합니다. 단순한 객체부터 복잡한 집합체에 이르기까지 무엇이든 키와 값이 될 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/kid_an/post/876d4b7b-1377-421c-bd9c-7dc8b690e92b/image.png" alt=""></p>
<p>이 외에도 도큐먼트 데이터베이스와 그래프 데이터베이스가 있습니다.</p>
<br>

<h2 id="redis는-왜-사용할까">Redis는 왜 사용할까?</h2>
<p>데이터 베이스는 데이터를 물리 디스크에 직접 쓰기 때문에 서버에 문제가 발생하여 다운되더라도 데이터가 손실되지 않습니다.</p>
<p>하지만 매번 디스크에 접근해야 하기 때문에 사용자가 많아질 수록 부하가 많아져서 느려질 수 있습니다.</p>
<p>일반적으로 서비스 운영 초반이거나 규모가 작은, 사용자가 많지 않은 서비스의 경우에는 WEB-WAS-DB의 구조로도 데이터베이스에 무리가 가지 않습니다.</p>
<p>그러나 사용자가 늘어난다면 데이터베이스가 과부하 될 수 있기 때문에 캐시 서버를 도입하여 사용하게 됩니다. 그리고 이 캐시 서버로 이용할 수 있는 것이 바로 <strong>Redis</strong>입니다.</p>
<br>

<h3 id="캐시-서버는-뭔가요">캐시 서버는 뭔가요?</h3>
<p><img src="https://velog.velcdn.com/images/kid_an/post/b77a53aa-76aa-4cd7-8017-c6734d445216/image.png" alt=""></p>
<p>캐시 서버는 클라이언트가 자주 요청하는 데이터를 메모리나 빠른 스토리지에 저장하여, 반복적인 데이터 요청 시 서버에 부담을 줄이고 응답 시간을 단축하는 역할을 합니다.</p>
<p>이 시스템은 네트워크 대역폭을 절약하고, 데이터베이스나 원본 서버의 부하를 감소시켜 성능을 최적화하는 데 중요한 역할을 합니다.</p>
<p>간단한 예를 들어보겠습니다.</p>
<pre><code class="language-text">1. 클라이언트가 서버에 데이터를 요청합니다.
2. 서버는 외부 API를 통해 데이터를 가져오고 그것을 응답으로 넘겨줍니다.
3. 이 때 외부 API 접근의 응답속도가 1000ms 정도 나옵니다.
4. 클라이언트는 데이터를 응답받기까지 1000ms는 적다고 생각합니다.
5. 그래서 중간에 캐시에 저장하기로 합니다.
6. 이제부터 서버는 5 ~ 10분 간격으로 외부 API에 데이터를 요청하여 캐시에 저장합니다.
7. 클라이언트가 서버에 데이터를 요청합니다.
8. 서버는 캐시에서 데이터를 꺼내 클라이언트로 응답해줍니다.
9. 1000ms 씩 걸리던 외부 API 접속 과정이 생략되어 클라이언트는 빠르게 데이터를 받아 볼 수 있습니다.</code></pre>
<p>이렇듯 주 요청하는 데이터를 임시로 저장해두었다가 클라이언트가 요청할 때 빠르게 전달해주는 시스템입니다.</p>
<br>

<h3 id="redis의-장점은-뭔가요">Redis의 장점은 뭔가요?</h3>
<p><strong>1. 성능</strong>
모든 Redis 데이터는 메모리에 저장되어 대기 시간을 낮추고 처리량을 높이며, 평균적으로 읽기 및 쓰기의 작업 속도가 1ms로 디스크 기반 데이터베이스보다 빠릅니다.</p>
<p><strong>2. 유연한 데이터 구조</strong>
Redis의 데이터는 String, List, Set, Hash, Sorted Set, Bitmap, JSON 등 다양한 데이터 타입을 지원합니다.
따라서, 애플리케이션의 요구 사항에 알맞은 다양한 데이터 타입을 활용할 수 있습니다.</p>
<p><strong>3. 개발 용이성</strong>
Redis는 쿼리문이 필요로 하지 않으며, 단순한 명령 구조로 데이터의 저장, 조회 등이 가능합니다.
또한, Java, Python, C, C++, C#, JavaScript, PHP, Node.js, Ruby 등을 비롯한 다수의 언어를 지원합니다.</p>
<p><strong>4. 영속성</strong>
Redis는 영속성을 보장하기 위해 데이터를 디스크에 저장할 수 있습니다. 따라서 서버에 치명적인 문제가 발생하더라도 디스크에 저장된 데이터를 통해 복구가 가능합니다.</p>
<p><strong>5. 싱글 스레드 방식</strong>
Redis는 싱글 스레드 방식을 사용하여 한 번에 하나의 명령어만을 처리하기 때문에 연산을 원자적으로 처리하여 Race Condition(경쟁 상태)가 거의 발생하지 않습니다.
하지만, 멀티 스레드를 지원하지 않기 때문에 시간 복잡도가 O(n)인 명령어의 사용은 주의해서 사용해야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring vs Fast API vs Node.js]]></title>
            <link>https://velog.io/@kid_an/Spring-vs-Fast-API-vs-Node.js</link>
            <guid>https://velog.io/@kid_an/Spring-vs-Fast-API-vs-Node.js</guid>
            <pubDate>Wed, 14 Jan 2026 14:02:56 GMT</pubDate>
            <description><![CDATA[<p><strong>* 백엔드 개발을 위한 서버에는 대표적으로 3가지가 있습니다. 바로 Spring, Fast API, Node.js입니다. 이번 포스팅에서는 위 3가지 기술에 대해 간단하게 비교해보도록 하겠습니다. *</strong></p>
<h2 id="1-간단-비교">1. 간단 비교</h2>
<table>
<thead>
<tr>
<th align="center">기술</th>
<th align="center">핵심 정체성</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Spring</td>
<td align="center">대규모, 안정성 중심의 엔터프라이즈 프레임워크</td>
</tr>
<tr>
<td align="center">Fast API</td>
<td align="center">Python 기반, 속도와 생산성이 매우 높은 API 서버</td>
</tr>
<tr>
<td align="center">Node.js</td>
<td align="center">비동기 I/O 기반, 실시간, 경량 서비스에 강점</td>
</tr>
</tbody></table>
<hr>
<h2 id="2-언어와-실행-구조의-차이">2. 언어와 실행 구조의 차이</h2>
<h3 id="spring">Spring</h3>
<ul>
<li>언어: Java</li>
<li>실행 방식: JVM 위에서 동작</li>
<li>요청 처리 모델: 기본적으로 멀티 스레드</li>
<li>요청 하나당 스레드 할당</li>
</ul>
<p>➡️ 안정성, 예측 가능한 성능이 강점</p>
<hr>
<h3 id="fast-api">Fast API</h3>
<ul>
<li>언어: Python</li>
<li>실행 방식: ASGI 서버(Uvicorn) 위에서 실행</li>
<li>요청 처리 모델: 비동기(async/await)</li>
</ul>
<p>➡️ 비동기 + 타입 힌트 기반</p>
<hr>
<h3 id="nodejs">Node.js</h3>
<ul>
<li>언어: JavaScript</li>
<li>실행 방식: V8 엔진</li>
<li>요청 처리 모델: 싱글 스레드 + 이벤트 루프</li>
</ul>
<p>➡️ I/O가 많은 서비스에 강함
➡️ 블로킹 코드에 취약</p>
<hr>
<h2 id="3-내부-구조-차이">3. 내부 구조 차이</h2>
<h3 id="spring-1">Spring</h3>
<h4 id="구조-특징">구조 특징</h4>
<ul>
<li>MVC 구조</li>
<li>DI(의존성 주입), AOP 기반</li>
<li>필터 -&gt; 인터셉터 -&gt; 컨트롤러 -&gt; 서비스 -&gt; 레포지토리</li>
</ul>
<pre><code class="language-text">Client
-&gt; Filter
-&gt; Intercepter
-&gt; Controller
-&gt; Service
-&gt; Repository
-&gt; DB</code></pre>
<h4 id="특징">특징</h4>
<ul>
<li>코드 구조가 <strong>강제됨</strong></li>
<li>설계가 잘 되면 유지보수가 매우 편함</li>
<li>보일러플레이트 많음</li>
</ul>
<hr>
<h3 id="fast-api-1">Fast API</h3>
<h4 id="구조-특징-1">구조 특징</h4>
<ul>
<li>함수 중심 구조</li>
<li>타입 힌트 기반 자동 검증</li>
<li>Open API(Swagger) 자동 생성</li>
</ul>
<pre><code class="language-python">@app.get(&quot;/users/{id}&quot;)
async def get_user(id: int):
    return {&quot;id&quot; : id}</code></pre>
<h4 id="특징-1">특징</h4>
<ul>
<li>구조가 자유로움</li>
<li>빠른 개발</li>
<li>팀이 커질수록 설계가 중요해짐</li>
</ul>
<hr>
<h3 id="nodejsexpress-기준">Node.js(Express 기준)</h3>
<h4 id="구조-특징-2">구조 특징</h4>
<ul>
<li>미들웨어 체인</li>
<li>요청 -&gt; 미들웨어 -&gt; 컨트롤러</li>
</ul>
<pre><code class="language-javascript">app.get(&quot;/users/:id&quot;, async (req, res) =&gt; {
  res.json({id: req.params.id});
});</code></pre>
<h4 id="특징-2">특징</h4>
<ul>
<li>매우 자유로움</li>
<li>잘못 설계하면 스파게티 코드</li>
<li>NestJS를 쓰면 Spring과 유사해짐</li>
</ul>
<hr>
<h2 id="4-성능-관점-비교">4. 성능 관점 비교</h2>
<table>
<thead>
<tr>
<th align="center">상황</th>
<th align="center">유리한 기술</th>
</tr>
</thead>
<tbody><tr>
<td align="center">CPU 연산 많음</td>
<td align="center">Spring</td>
</tr>
<tr>
<td align="center">DB / API 호출 많음</td>
<td align="center">Node, Fast API</td>
</tr>
<tr>
<td align="center">동시 접속 수 많음</td>
<td align="center">Node</td>
</tr>
<tr>
<td align="center">안정적 TPS 유지</td>
<td align="center">Spring</td>
</tr>
</tbody></table>
<hr>
<h2 id="5-개발-생산성-비교">5. 개발 생산성 비교</h2>
<table>
<thead>
<tr>
<th align="center">항목</th>
<th align="center">Spring</th>
<th align="center">Fast API</th>
<th align="center">Node</th>
</tr>
</thead>
<tbody><tr>
<td align="center">초기 세팅</td>
<td align="center">복잡</td>
<td align="center">매우 빠름</td>
<td align="center">빠름</td>
</tr>
<tr>
<td align="center">코드량</td>
<td align="center">많음</td>
<td align="center">적음</td>
<td align="center">적음</td>
</tr>
<tr>
<td align="center">타입 안정성</td>
<td align="center">⭐⭐⭐⭐⭐</td>
<td align="center">⭐⭐⭐⭐</td>
<td align="center">⭐⭐⭐(TPS 사용시 ⭐⭐⭐⭐)</td>
</tr>
<tr>
<td align="center">러닝 커브</td>
<td align="center">높음</td>
<td align="center">낮음</td>
<td align="center">중간</td>
</tr>
</tbody></table>
<hr>
<h2 id="6-생태계">6. 생태계</h2>
<h3 id="spring-2">Spring</h3>
<ul>
<li>대기업, 금융, 공공기관</li>
<li>인증/보안(Spring Security)</li>
<li>트랜잭션 관리</li>
<li>대규모 조직 협업</li>
</ul>
<p>➡️ 안정성 + 표준</p>
<hr>
<h3 id="fast-api-2">Fast API</h3>
<ul>
<li>스타트업</li>
<li>AI/ML 서버</li>
<li>크롤링, 데이터 처리 API</li>
</ul>
<p>➡️ 빠른 실험과 검증</p>
<hr>
<h3 id="nodejs-1">Node.js</h3>
<ul>
<li>채팅</li>
<li>알림 서버</li>
<li>실시간 서비스</li>
<li>BFF(Backend for Frontend)</li>
</ul>
<p>➡️ 실시간 + 프론트 연계</p>
<hr>
<h2 id="7-조합-예시">7. 조합 예시</h2>
<pre><code class="language-text">Spring Boot (메인 서버)
 ├─ 인증 / 비즈니스 로직
 ├─ DB 트랜잭션
 └─ 사용자 API

Node.js (보조 서버)
 └─ 채팅 / WebSocket

FastAPI (서브 서버)
 └─ 크롤링 / AI / 데이터 처리</code></pre>
<hr>
<h2 id="8-각-기술별-crud-예제-비교">8. 각 기술별 CRUD 예제 비교</h2>
<h3 id="0-공통-crud-요구사항">0. 공통 CRUD 요구사항</h3>
<ul>
<li>사용자 생성(Create)</li>
<li>사용자 조회(Read)</li>
<li>사용자 수정(Update)</li>
<li>사용자 삭제(Delete)</li>
</ul>
<hr>
<h3 id="spring-crud">Spring CRUD</h3>
<h4 id="entity">Entity</h4>
<pre><code class="language-java">@Entity
@Getter @Setter
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}</code></pre>
<hr>
<h4 id="repository">Repository</h4>
<pre><code class="language-java">public interface UserRepository extends JpaRepository&lt;User, Long&gt; {
}</code></pre>
<hr>
<h4 id="service">Service</h4>
<pre><code class="language-java">@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;

    public User create(User user) {
        return userRepository.save(user);
    }

    public User get(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -&gt; new RuntimeException(&quot;User not found&quot;));
    }

    public User update(Long id, User user) {
        User existing = get(id);
        existing.setName(user.getName());
        return userRepository.save(existing);
    }

    public void delete(Long id) {
        userRepository.deleteById(id);
    }
}</code></pre>
<hr>
<h4 id="controller">Controller</h4>
<pre><code class="language-java">@RestController
@RequestMapping(&quot;/users&quot;)
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @PostMapping
    public User create(@RequestBody User user) {
        return userService.create(user);
    }

    @GetMapping(&quot;/{id}&quot;)
    public User get(@PathVariable Long id) {
        return userService.get(id);
    }

    @PutMapping(&quot;/{id}&quot;)
    public User update(@PathVariable Long id, @RequestBody User user) {
        return userService.update(id, user);
    }

    @DeleteMapping(&quot;/{id}&quot;)
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}</code></pre>
<hr>
<h3 id="fast-api-crud">Fast API CRUD</h3>
<pre><code class="language-python">from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    id: int
    name: str

users = {}</code></pre>
<hr>
<h4 id="create">Create</h4>
<pre><code class="language-python">@app.post(&quot;/users&quot;)
async def create_user(user: User):
    users[user.id] = user
    return user</code></pre>
<hr>
<h4 id="read">Read</h4>
<pre><code class="language-python">@app.get(&quot;/users/{id}&quot;)
async def get_user(id: int):
    return users.get(id)</code></pre>
<hr>
<h4 id="update">Update</h4>
<pre><code class="language-python">@app.put(&quot;/users/{id}&quot;)
async def update_user(id: int, user: User):
    users[id] = user
    return user</code></pre>
<hr>
<h4 id="delete">Delete</h4>
<pre><code class="language-python">@app.delete(&quot;/users/{id}&quot;)
async def delete_user(id: int):
    users.pop(id, None)
    return {&quot;message&quot;: &quot;deleted&quot;}</code></pre>
<hr>
<h3 id="nodejs-2">Node.js</h3>
<pre><code class="language-javascript">const express = require(&quot;express&quot;);
const app = express();

app.use(express.json());

const users = {};</code></pre>
<hr>
<h4 id="create-1">Create</h4>
<pre><code class="language-javascript">app.post(&quot;/users&quot;, (req, res) =&gt; {
  const { id, name } = req.body;
  users[id] = { id, name };
  res.json(users[id]);
});</code></pre>
<hr>
<h4 id="read-1">Read</h4>
<pre><code class="language-javascript">app.get(&quot;/users/:id&quot;, (req, res) =&gt; {
  res.json(users[req.params.id]);
});</code></pre>
<hr>
<h4 id="update-1">Update</h4>
<pre><code class="language-javascript">app.put(&quot;/users/:id&quot;, (req, res) =&gt; {
  const { name } = req.body;
  users[req.params.id].name = name;
  res.json(users[req.params.id]);
});</code></pre>
<hr>
<h3 id="delete-1">Delete</h3>
<pre><code class="language-javascript">app.delete(&quot;/users/:id&quot;, (req, res) =&gt; {
  delete users[req.params.id];
  res.json({ message: &quot;deleted&quot; });
});</code></pre>
<hr>
<h2 id="9-추가-spring-vs-nestjs">9. 추가 Spring vs NestJS</h2>
<h3 id="전체-구조-비교">전체 구조 비교</h3>
<table>
<thead>
<tr>
<th align="center">Spring</th>
<th align="center">NestJS</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Controller</td>
<td align="center">Controller</td>
</tr>
<tr>
<td align="center">Service</td>
<td align="center">Service</td>
</tr>
<tr>
<td align="center">Repository</td>
<td align="center">Repository(선택)</td>
</tr>
<tr>
<td align="center">@Autowired / 생성자 주입</td>
<td align="center">생성자 주입</td>
</tr>
<tr>
<td align="center">어노테이션</td>
<td align="center">데코레이터</td>
</tr>
</tbody></table>
<hr>
<h3 id="entity--model">Entity / Model</h3>
<h4 id="springjpa-entity">Spring(JPA Entity)</h4>
<pre><code class="language-java">@Entity
@Getter @Setter
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}</code></pre>
<hr>
<h4 id="nestjstypeorm-entity">NestJS(TypeORM Entity)</h4>
<pre><code class="language-ts">import { Entity, Column, PrimaryGeneratedColumn } from &#39;typeorm&#39;;

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;
}</code></pre>
<h4 id="차이점">차이점</h4>
<ul>
<li>Spring: JPA 표준</li>
<li>NestJS: TypeORM / Prisma 등 선택</li>
<li>문법만 다르고 개념은 동일</li>
</ul>
<hr>
<h3 id="repository-1">Repository</h3>
<h4 id="spring-3">Spring</h4>
<pre><code class="language-java">public interface UserRepository extends JpaRepository&lt;User, Long&gt; {
}</code></pre>
<hr>
<h4 id="nestjs">NestJS</h4>
<pre><code class="language-ts">@Injectable()
export class UserRepository {
  constructor(
    @InjectRepository(User)
    private repo: Repository&lt;User&gt;,
  ) {}

  save(user: User) {
    return this.repo.save(user);
  }

  findById(id: number) {
    return this.repo.findOneBy({ id });
  }
}</code></pre>
<h4 id="차이점-1">차이점</h4>
<ul>
<li>Spring: 인터페이스만 정의 -&gt; 구현 자동</li>
<li>NestJS: 직접 래핑(조금 더 명시적)</li>
</ul>
<hr>
<h3 id="service비즈니스-로직">Service(비즈니스 로직)</h3>
<h4 id="spring-service">Spring Service</h4>
<pre><code class="language-java">@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;

    public User create(User user) {
        return userRepository.save(user);
    }

    public User get(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -&gt; new RuntimeException(&quot;User not found&quot;));
    }
}</code></pre>
<hr>
<h4 id="nestjs-service">NestJS Service</h4>
<pre><code class="language-ts">@Injectable()
export class UserService {
  constructor(private readonly userRepository: UserRepository) {}

  async create(user: User): Promise&lt;User&gt; {
    return this.userRepository.save(user);
  }

  async get(id: number): Promise&lt;User&gt; {
    return this.userRepository.findById(id);
  }
}</code></pre>
<h4 id="차이점-2">차이점</h4>
<ul>
<li>Spring: 동기 코드처럼 보임</li>
<li>NestJS: async/await 명시</li>
<li>DI 방식은 거의 동일</li>
</ul>
<hr>
<h3 id="controller-1">Controller</h3>
<h4 id="spring-controller">Spring Controller</h4>
<pre><code class="language-java">@RestController
@RequestMapping(&quot;/users&quot;)
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @PostMapping
    public User create(@RequestBody User user) {
        return userService.create(user);
    }

    @GetMapping(&quot;/{id}&quot;)
    public User get(@PathVariable Long id) {
        return userService.get(id);
    }
}</code></pre>
<hr>
<h4 id="nestjs-controller">NestJS Controller</h4>
<pre><code class="language-ts">@Controller(&#39;users&#39;)
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  create(@Body() user: User) {
    return this.userService.create(user);
  }

  @Get(&#39;:id&#39;)
  get(@Param(&#39;id&#39;) id: number) {
    return this.userService.get(id);
  }
}</code></pre>
<h4 id="차이점-3">차이점</h4>
<ul>
<li>어노테이션 &lt;-&gt; 데코레이터 문법 차이</li>
<li>의미는 동일</li>
</ul>
<hr>
<h3 id="dto--validation">DTO &amp; Validation</h3>
<h4 id="spring-dto">Spring DTO</h4>
<pre><code class="language-java">public class UserDto {
    @NotBlank
    private String name;
}</code></pre>
<hr>
<h4 id="nestjs-dto">NestJS DTO</h4>
<pre><code class="language-ts">import { IsNotEmpty } from &#39;class-validator&#39;;

export class UserDto {
  @IsNotEmpty()
  name: string;
}</code></pre>
<h4 id="차이점-4">차이점</h4>
<ul>
<li>Spring: Hibernate Validator</li>
<li>NestJS: Class-Validator</li>
<li>검증 위치 개념 동일</li>
</ul>
<hr>
<h3 id="차이-요약">차이 요약</h3>
<table>
<thead>
<tr>
<th align="center">항목</th>
<th align="center">Spring</th>
<th align="center">NestJS</th>
</tr>
</thead>
<tbody><tr>
<td align="center">언어</td>
<td align="center">Java</td>
<td align="center">TypeScript</td>
</tr>
<tr>
<td align="center">실행 환경</td>
<td align="center">JVM</td>
<td align="center">Node.js</td>
</tr>
<tr>
<td align="center">타입 안정성</td>
<td align="center">컴파일 타임</td>
<td align="center">컴파일 타임</td>
</tr>
<tr>
<td align="center">구조 강제</td>
<td align="center">매우 강함</td>
<td align="center">강함</td>
</tr>
<tr>
<td align="center">러닝 커브</td>
<td align="center">높음</td>
<td align="center">중간</td>
</tr>
</tbody></table>
<hr>
<h2 id="10-기술-선택-가이드">10. 기술 선택 가이드</h2>
<ul>
<li>메인 비즈니스 서버 -&gt; Spring</li>
<li>Node 기반이지만 큰 규모 -&gt; NestJS</li>
<li>채팅 / 실시간 -&gt; Node.js or NestJS</li>
<li>빠른 MVP -&gt; Node.js / Fast API</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JWT(JSON Web Token)]]></title>
            <link>https://velog.io/@kid_an/JWTJSON-Web-Token</link>
            <guid>https://velog.io/@kid_an/JWTJSON-Web-Token</guid>
            <pubDate>Tue, 17 Jun 2025 02:56:11 GMT</pubDate>
            <description><![CDATA[<h2 id="0-jwt란">0. JWT란?</h2>
<p><strong>JWT(JSON Web Token)</strong>는 <strong>사용자 인증 저오와 추가 데이터를 JSON 형태로 담아서 암호화한 문자열</strong>이다.</p>
<p>즉, 이 사용자가 누구인지를 증명할 수 있게 해주는 <strong>디지털 서명된 토큰</strong>인 것이다.</p>
<p>ex)</p>
<pre><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOjEsInJvbGUiOiJ1c2VyIn0.
s7Kfj3VfknBvS9vU8HnV9zUpAbWQqf7sn9UiEqlP3ko</code></pre><p>이 문자열은 아래와 같이 총 3부분으로 나뉘어 있다.</p>
<p><img src="https://velog.velcdn.com/images/kid_an/post/2aa8d903-f214-4385-a0dd-a4bc76406982/image.png" alt="">
<img src="https://velog.velcdn.com/images/kid_an/post/db0679f6-d70e-4f5d-9662-be01cfa95ccf/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>부분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Header</td>
<td>토큰 타입, 서명 알고리즘</td>
</tr>
<tr>
<td>Payload</td>
<td>사용자 정보 (ex. userId, role 등)</td>
</tr>
<tr>
<td>Signature</td>
<td>서버가 발급할 때 서명한 값 (변조 방지용)</td>
</tr>
</tbody></table>
<br>

<h2 id="1-왜-jwt를-사용하나">1. 왜 JWT를 사용하나?</h2>
<p>📊세션 방식과 JWT를 비교해보자</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>세션 방식</th>
<th>JWT 방식</th>
</tr>
</thead>
<tbody><tr>
<td>저장 위치</td>
<td>서버 메모리(또는 Redis 등)</td>
<td>클라이언트가 JWT를 저장</td>
</tr>
<tr>
<td>서버 확장성</td>
<td>불리함 (세션 동기화 필요)</td>
<td>유리함 (무상태/Stateless)</td>
</tr>
<tr>
<td>인증 방식</td>
<td>서버가 세션ID로 사용자 식별</td>
<td>클라이언트가 JWT로 사용자 식별</td>
</tr>
</tbody></table>
<p>JWT는 서버에 상태를 저장하지 않고도 인증을 유지할 수 있기 때문에 <strong>마이크로서비스, 모바일 앱, 서버간 통신</strong> 등에서 효율적이다.</p>
<br>

<h2 id="3-프론트엔드에서-jwt의-활용">3. 프론트엔드에서 JWT의 활용</h2>
<p><strong>1. 로그인시 토큰 받기</strong></p>
<pre><code class="language-javascript">// 예: 로그인 API 호출 결과
const response = await axios.post(&quot;/login&quot;, { id, password });
const token = response.data.token;</code></pre>
<p><strong>2. 서버에서 받은 토큰을 저장</strong>
브라우저 저장소에 저장(권장: HttpOnly 쿠키 또는 LocalStorage)</p>
<pre><code class="language-javascript">// 예시 (간단하게 localStorage에 저장)
localStorage.setItem(&quot;token&quot;, token);</code></pre>
<blockquote>
<p>보안상 안전한 방식은 HttpOnly 쿠키 사용이다.</p>
</blockquote>
<p><strong>3. API 호출 시 토큰을 함께 전송</strong>
서버가 인증된 요청인지 확인하려면, <strong>JWT를 헤더에 넣어서</strong> 보내야 한다.</p>
<pre><code class="language-javascript">// 예: 게시글 목록 요청 시
const token = localStorage.getItem(&quot;token&quot;);

axios.get(&quot;/api/posts&quot;, {
  headers: {
    Authorization: `Bearer ${token}`
  }
});</code></pre>
<p><strong>4. 서버는 토큰을 검사</strong></p>
<ul>
<li>서버는 요청이 올 때마다 JWT를 검사하여 유효한 사용자면 응답을 해준다.</li>
<li>보통 Spring Boot에서는 필터나 인터셉터에서 검사를 처리한다.</li>
</ul>
<br>

<h2 id="4-jwt-사용-시나리오">4. JWT 사용 시나리오</h2>
<p><strong>회원가입 &amp; 로그인</strong></p>
<ol>
<li>로그인 성공 -&gt; JWT 발급</li>
<li>프론트는 JWT를 저장</li>
<li>이후 모든 요청에 JWT를 헤더에 넣음</li>
<li>서버는 JWT를 검사해 요청한 사람이 누구인지 파악</li>
</ol>
<br>

<h2 id="5-주의할-점">5. 주의할 점</h2>
<ol>
<li>JWT 탈취 시 큰 위험 -&gt; Https + HttpOnly 쿠키 권장</li>
<li>만료 시간 설정 필수</li>
<li>JWT는 섭버에서 무효화 불가 -&gt; 때문에문에 짧은 유효시간 + RefreshToken을 같이 사용하기도 한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[리다이렉트(Redirect)]]></title>
            <link>https://velog.io/@kid_an/%EB%A6%AC%EB%8B%A4%EC%9D%B4%EB%A0%89%ED%8A%B8Redirect</link>
            <guid>https://velog.io/@kid_an/%EB%A6%AC%EB%8B%A4%EC%9D%B4%EB%A0%89%ED%8A%B8Redirect</guid>
            <pubDate>Sat, 14 Jun 2025 12:59:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/kid_an/post/fb84b05b-26e6-4144-a4dc-22550d446f2f/image.png" alt=""></p>
<h2 id="0-리다이렉트redirect란">0. 리다이렉트(Redirect)란?</h2>
<p>리다이렉트는 <strong>사용자가 어떤 URL로 접속했을 때 자동으로 다른 URL로 이동시키는 것</strong>을 말한다.</p>
<p>예를 들어, <code>example.com</code>에 접속했을 때 자동으로 <code>example.com/home</code>으로 이동하거나, 오래된 페이지 URL을 새 페이지 URL로 연결하는 경우에 사용한다.</p>
<p>사용자는 <code>example.com</code>에 접속했지만 실제로는 리다이렉트 되어 <code>example.com/home</code>으로 이동되어 화면에 보여지는 것이다.</p>
<br>

<h2 id="1-vue-router에서-리다이렉트를-사용하는-경우">1. Vue Router에서 리다이렉트를 사용하는 경우</h2>
<pre><code class="language-javascript">{
  path: &quot;&quot;,
  redirect: &quot;/home&quot;
}
</code></pre>
<p>이런 식으로 사용할 수 있다.
path 부분의 &quot;&quot;은 부모 경로의 자식 라우트 중 빈 문자열을 경로에 사용하여 부모 경로로 접속하면 자동으로 <code>부모경로/home</code> 페이지가 보이도록 한 것이다.</p>
<br>

<h2 id="2-왜-리다이렉트가-필요할까">2. 왜 리다이렉트가 필요할까?</h2>
<p>만약 리다이렉트가 없으면 <code>/부모경로</code>에 들어가도 아무 자식 컴포넌트가 렌더링이 되지 않을 수 있다. 그렇게 되면 사용자가 접속했을 때 아무런 화면도 보이지 않게 되는 것이다.</p>
<p>따라서 유저에게 원하는 화면을 보여주기 위해 리다이렉트를 사용하는 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Portal IT] 메인 페이지 디자인 하기]]></title>
            <link>https://velog.io/@kid_an/Portal-IT-%EB%A9%94%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kid_an/Portal-IT-%EB%A9%94%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 14 Jun 2025 12:49:35 GMT</pubDate>
            <description><![CDATA[<p><em>오늘은 제작할 웹 페이지의 기준이 될 메인 페이지를 디자인할 예정이다.</em></p>
<br>

<br>

<br>

<h2 id="0-디자인-참고하기">0. 디자인 참고하기</h2>
<p>디자인을 시작하기에 앞서, 나는 디자인에 대해 문외한이기 때문에 타 사이트를 참고하여 해보려 한다.</p>
<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/7fabc580-085e-42de-b53f-39939b793d10/image.png" alt=""></p>
<center>네이버 메인</center>

<p><img src="https://velog.velcdn.com/images/kid_an/post/83dd20cb-2137-4efb-a256-19ff71e3631b/image.png" alt=""></p>
<center>네이버 구조</center>
</blockquote>
<br>

<br>

<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/2d1d47c8-d0ce-4e00-a3af-4f4345c872dd/image.png" alt=""></p>
<center>다음 메인</center>

<p><img src="https://velog.velcdn.com/images/kid_an/post/0671f04f-be86-41ca-b5f2-70ddd975ce28/image.png" alt=""></p>
<center>다음 구조</center>
</blockquote>
<br>

<br>

<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/3fe28cc8-7980-4121-af10-8899722d1d3d/image.png" alt=""></p>
<center>구글 메인</center>

<p><img src="https://velog.velcdn.com/images/kid_an/post/2f2ae455-5ce7-4d4e-9b68-d0bd2f8c1975/image.png" alt=""></p>
<center>구글 구조</center>
</blockquote>
<br>

<br>

<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/dfbeb4a6-235d-4083-a259-c682647da6c4/image.png" alt=""></p>
<center>벨로그 메인</center>

<p><img src="https://velog.velcdn.com/images/kid_an/post/6b050218-0d52-4247-bb6a-c77bace726d7/image.png" alt=""></p>
<center>벨로그 구조</center>
</blockquote>
<br>

<br>

<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/3f9a7c35-5619-4b13-ac9d-4877207d5386/image.png" alt=""></p>
<center>사람인 메인</center>

<p><img src="https://velog.velcdn.com/images/kid_an/post/f7ccdbe9-2e05-4701-8d8e-6f91a5deb803/image.png" alt=""></p>
<center>사람인 구조</center>
</blockquote>
<p>포털 사이트 3곳, 채용 사이트 1곳, 소셜네트워크 사이트 1곳 총 5곳의 메인 화면을 분석해보았다.</p>
<p>5곳의 사이트 구조를 전부 합쳐 보면,</p>
<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/1ce4e79f-1767-440e-bc88-80390af653c1/image.png" alt=""></p>
</blockquote>
<p>이런 모양이 나온다.</p>
<p>여기서 하나씩 지워보면서 사이트 구조를 만들어보자.</p>
<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/9c2afe73-57f0-43d3-8cb2-63ee96a64ecf/image.png" alt=""></p>
</blockquote>
<p>구조를 하나씩 지웠으니 크기와 배치를 조정해보자.</p>
<br>

<blockquote>
<p><img src="https://velog.velcdn.com/images/kid_an/post/d2a7e6b7-846f-486c-8b4b-f2c5e93fc900/image.png" alt=""></p>
<center>완성된 구조 모습</center>
</blockquote>
<hr>
<br>

<h2 id="결과">결과</h2>
<br>

<p>구조를 완성했으니 각 요소들을 가져오고 색상도 바꿔보자!</p>
<p><img src="https://velog.velcdn.com/images/kid_an/post/f035c9fd-ba83-4ca8-b946-3b09eaf132b1/image.png" alt=""></p>
<p>요소들은 당장 넣을 내용이 없으니 각 사이트에서 캡처해서 가져와봤다.
생각보다 괜찮게 나온 듯하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드 풀이] 네트워크]]></title>
            <link>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Fri, 25 Apr 2025 07:25:15 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-파악">문제 파악</h2>
<hr>
<h3 id="네트워크"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43162">네트워크</a></h3>
<p>컴퓨터 A와 컴퓨터 B는 직접적으로 연결되어 있다.</p>
<p>컴퓨터 B와 컴퓨터 C는 직접적으로 연결되어 있다.</p>
<p>→ 컴퓨터 A와 C는 간접적으로 연결되어 있다.</p>
<pre><code class="language-java">A-B

B-C

A-C

A-B-C
</code></pre>
<p>이를 하나의 네트워크라고 한다.</p>
<br>

<p><strong>매개변수로 컴퓨터의 개수 n 컴퓨터의 연결 정보가 담긴 2차원 배열 computers가 주어질 때, 네트워크의 개수를 return하라.</strong></p>
<br>

<p><strong>제한 사항</strong></p>
<ol>
<li>컴퓨터의 개수 n은 1 이상 200 이하인 자연수이다.</li>
<li>각 컴퓨터는 0부터 <code>n-1</code> 인 정수로 표현한다.</li>
<li>i번 컴퓨터와 j번 컴퓨터가 연결되어 있으면 computers[i][j]를 1로 표현한다.</li>
<li>computers[i][i]는 항상 1이다.</li>
</ol>
<br>

<p><strong>입출력 예시</strong></p>
<table>
<thead>
<tr>
<th>n</th>
<th>computers</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>3</td>
<td>[[1, 1, 0], [1, 1, 0], [0, 0, 1]]</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>[[1, 1, 0], [1, 1, 1], [0, 1, 1]]</td>
<td>1</td>
</tr>
</tbody></table>
<hr>
<br>

<h2 id="접근-방법">접근 방법</h2>
<hr>
<p>예시를 가지고 그래프를 그려보자.</p>
<table>
<thead>
<tr>
<th>입력 예제 1</th>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>B</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>C</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
</tbody></table>
<p>A-B</p>
<p>B-A</p>
<p>C</p>
<p>위처럼 A와 B는 서로 연결되어 있지만, C는 다른 컴퓨터와 연결되어 있지 않다.</p>
<p>따라서 네트워크의 개수는 2이다.</p>
<table>
<thead>
<tr>
<th>입력 예제 2</th>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>B</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>C</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
</tbody></table>
<p>A-B</p>
<p>B-A</p>
<p>B-C</p>
<p>C-B</p>
<p>A-B-C</p>
<p>위처럼 3대의 컴퓨터는 서로 연결되어 있다.</p>
<p>따라서 네트워크의 개수는 1이다.</p>
<p>네트워크는 그래프로 표현할 수 있다.</p>
<p>모든 네트워크를 탐색하고 한 개의 네트워크가 탐색이 끝나면 count하면 된다.</p>
<p>그래프 탐색에는 BFS와 DFS가 있다.</p>
<p>단순히 탐색만 하는 문제라 둘 중에 어느 것을 사용해도 되므로, BFS와 DFS 둘 다 익숙해지기 위해 두 방법으로 코드를 작성해보겠다.</p>
<blockquote>
<p><strong>BFS사용</strong></p>
</blockquote>
<p>먼저 BFS로 그래프를 탐색하는 것부터 구현해보자.</p>
<p>2차원 배열 computers[i][j]의 [0][0]부터 차례대로 Queue에 넣어보자.</p>
<p>이 때, <code>i == j</code> 인 경우는 건너 뛴다. → i와 j가 같은 경우는 자기 자신을 가리키기 때문이다.</p>
<p>Queue에 [0][1]을 넣고 방문 표시를 한다.</p>
<p>[1][0]부터 값이 1인 인덱스를 탐색한다. → 1이면 이어지고, 0이면 이어지지 않는다.</p>
<p>탐색한 인덱스가 1이면 해당 인덱스의 방문 여부를 확인한다.</p>
<p>방문했으면 다음으로 넘어가고 그렇지 않으면 Queue에 삽입한다.</p>
<p>더 방문할 인덱스가 없으면 탐색을 종료한다.</p>
<p>위 과정을 코드로 작성해보자.</p>
<pre><code class="language-java">import java.util.Queue;
import java.util.HashMap;

Queue&lt;Integer&gt; queue = new Queue&lt;&gt;();
HashMap&lt;Integer, Boolean&gt; visited = new HashMap&lt;&gt;();

int answer = 0;

for(int i = 0; i &lt; computers.length; i++) {
    bfs(0, true);
}

public void bfs(int node, boolean visit) {
    queue.push(node);
    visited.put(0, true);

    while(!queue.isEmpty()) {
        node = queue.poll();

        for(int i = 0; i &lt; computers[node].length; i++) {
            if(node == i) {
                continue;
            } else if(computers[node][i] == 1 &amp;&amp; visited.get(i) != true) {
                    queue.push(i);
                    visited.put(i, true);
            }
        }
    }
    answer++;
}</code></pre>
<br>

<p>이제 프로그래머스에 옮겨 적어보자.</p>
<pre><code class="language-java">import java.util.Queue;
import java.util.LinkedList;

class Solution {
    public void bfs(int node, int[][] computers, boolean[] visited) {
        Queue&lt;Integer&gt; queue = new LinkedList&lt;&gt;();

        queue.offer(node);
        visited[node] = true;

        while(!queue.isEmpty()) {
            node = queue.poll();

            for(int i = 0; i &lt; computers[node].length; i++) {
                if(node == i) {
                    continue;
                } else if(computers[node][i] == 1 &amp;&amp; visited[i] != true) {
                    queue.offer(i);
                    visited[i] = true;
                }
            }
        }
    }

    public int solution(int n, int[][] computers) {
        boolean[] visited = new boolean[n];

        int answer = 0;

        for(int i = 0; i &lt; computers.length; i++) {
          if(visited[i] == false) {
              answer++;
              bfs(i, computers, visited);
            }
        }

        return answer;
    }
}</code></pre>
<p>정답!</p>
<blockquote>
<p><strong>DFS 사용</strong></p>
</blockquote>
<p>BFS를 사용해서 해결했으니, 이번엔 DFS로 풀어보자.</p>
<p>DFS는 재귀 호출을 사용해야 한다.</p>
<p>시작 노드를 DFS 함수의 매개변수로 넣어준다.</p>
<p>시작 노드를 받은 DFS 함수는 방문 여부를 표시하고, 시작 노드가 어디와 연결되어 있는지 배열을 탐색한다.</p>
<p>BFS와 마찬가지로  <code>i == j</code> 인 경우는 건너 뛴다. → i와 j가 같은 경우는 자기 자신을 가리키기 때문이다.</p>
<p>computer[node][i]가 1이면, 다시 DFS 함수에 매개변수로 i값을 넣어준다.</p>
<p>그러면 재귀 호출로 인해 DFS를 반복하여 그래프를 탐색할 수 있다.</p>
<p>위 과정을 코드로 작성해 보자.</p>
<pre><code class="language-java">public void dfs(int currentNode, int[][] computers, boolean[] visited) {
    visited[currentNode] = true;

    for(int i = 0; i &lt; computers[currentNode].length; i++) {
        if(computers[currentNode][i] == 1 &amp;&amp; !visited[i]) {
            dfs(i, computers, visited);
        }
    }
}</code></pre>
<br>

<p>아래는 프로그래머스에 위 코드를 옮겨 적은 것이다.</p>
<pre><code class="language-java">import java.util.Queue;
import java.util.LinkedList;

class Solution {
    public void dfs(int currentNode, int[][] computers, boolean[] visited) {
        visited[currentNode] = true;

        for(int i = 0; i &lt; computers[currentNode].length; i++) {
            if(computers[currentNode][i] == 1 &amp;&amp; !visited[i]) {
                dfs(i, computers, visited);
            }
        }
    }

    public int solution(int n, int[][] computers) {
        boolean[] visited = new boolean[n];

        int answer = 0;

        for(int i = 0; i &lt; n; i++) {
            if(!visited[i]) {
                answer++;
                dfs(i, computers, visited);
            }
        }

        return answer;
    }
}</code></pre>
<p>정답!</p>
<br>

<h2 id="코드-구현">코드 구현</h2>
<hr>
<pre><code class="language-java">import java.util.Queue;
import java.util.LinkedList;

class Solution {
    public void bfs(int node, int[][] computers, boolean[] visited) {
        Queue&lt;Integer&gt; queue = new LinkedList&lt;&gt;();

        queue.offer(node);
        visited[node] = true;

        while(!queue.isEmpty()) {
            node = queue.poll();

            for(int i = 0; i &lt; computers[node].length; i++) {
                if(node == i) {
                    continue;
                } else if(computers[node][i] == 1 &amp;&amp; visited[i] != true) {
                    queue.offer(i);
                    visited[i] = true;
                }
            }
        }
    }

    public int solution(int n, int[][] computers) {
        boolean[] visited = new boolean[n];

        int answer = 0;

        for(int i = 0; i &lt; computers.length; i++) {
            if(visited[i] == false) {
                answer++;
            }

            bfs(i, computers, visited);
        }

        return answer;
    }
}</code></pre>
<br>

<h2 id="배우게-된-점">배우게 된 점</h2>
<hr>
<p>처음으로 BFS를 직접 구현해 보았다.</p>
<p>답안을 보지 않고 했더니, BFS만 구현하는데 2시간이나 걸렸다.</p>
<p>익숙해지도록 연습을 많이 해야겠다.</p>
<p>DFS는 생각보다 훨씬 빠르게 구현했다. 10분 정도 걸린 것 같다.</p>
<p>DFS가 BFS보다 구현하기 쉬운 걸까?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드 풀이] 20. Valid Parentheses]]></title>
            <link>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-20.-Valid-Parentheses</link>
            <guid>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-20.-Valid-Parentheses</guid>
            <pubDate>Wed, 23 Apr 2025 06:07:42 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-파악">문제 파악</h2>
<h3 id="20-valid-parentheses"><a href="https://leetcode.com/problems/valid-parentheses/">20. Valid Parentheses</a></h3>
<blockquote>
<ol>
<li>올바른 괄호를 구해야 한다.</li>
<li>괄호는 소, 중, 대 괄호 다 가능하다.</li>
<li>괄호는 같은 종류의 괄호로 열리고 닫혀야 한다.</li>
<li>괄호 안의 괄호가 열린 후 닫히지 않은 채로 존재하면 안 된다.</li>
<li>괄호가 올바른지 올바르지 않은 지를 <code>true</code>와 <code>false</code>로 판단하여 <code>return</code>한다.</li>
</ol>
</blockquote>
<blockquote>
<p><strong>예시</strong>
( )⇒ 올바른 괄호
( [ ] ) ⇒ 올바른 괄호
( [ ) ] ⇒ 올바르지 않은 괄호</p>
</blockquote>
<h2 id="접근-방법">접근 방법</h2>
<ol>
<li>앞에 열린 괄호가 없는 상태에서 닫힌 괄호가 들어오는 경우에 <code>false</code>를 <code>return</code> 해야 한다.</li>
<li>올바른 괄호 내부에 있는 괄호가 올바르지 않은 경우 <code>false</code> 를 <code>return</code> 한다.</li>
<li>괄호 한 쌍이 서로 다른 종류로 이루어져 있는 경우 <code>false</code>를 <code>return</code> 한다.</li>
<li>이 외의 경우 전부 <code>true</code> 를 <code>return</code> 한다.</li>
</ol>
<br>

<blockquote>
<p><strong>실패한 풀이</strong></p>
</blockquote>
<blockquote>
<p>각 괄호의 종류 별로 <code>open</code> 과 <code>close</code> 를 판단할 <code>boolean</code> 타입 변수를 선언한다.
→ 기본 값은 <code>true</code>로 한다.</p>
</blockquote>
<blockquote>
<p>괄호가 열리면 <code>false</code>  를 삽입한다.
괄호가 닫히면 <code>true</code> 를 삽입한다.
→ 괄호가 닫힌 경우 다른 종류의 괄호 변수 값을 확인한다.
→ 다른 종류의 괄호 변수가 전부 <code>true</code> 가 아니라면, 즉시 <code>false</code> 를 <code>return</code> 한다.
→ 다른 종류의 괄호 변수가 전부 <code>true</code> 이면 계속 탐색을 진행한다.</p>
</blockquote>
<p>탐색이 끝난 후에 모든 괄호 변수가 <code>true</code> 이면 <code>true</code> 를 <code>return</code> 한다.
더 생각을 해봤지만 위의 방법으로는 괄호 내부의 괄호를 판단할 수 없을 것 같다.
다른 방법이 떠오르지 않아 답안을 보기로 했다.</p>
<p>아래는 실패한 코드이다. 괄호 내부의 괄호에서 판단이 되지 않아 실패했다.</p>
<pre><code class="language-java">class Solution {
    public boolean isValid(String s) {
        boolean bigBracket = false, midBracket = false, smallBracket = false;
        int bigCount = 0, midCount = 0, smallCount = 0;

        for(int i = 0; i &lt; s.length(); i++) {
            if(s.charAt(i) == &#39;[&#39; || s.charAt(i) == &#39;]&#39;) {
                bigCount += s.charAt(i) == &#39;[&#39; ? 1 : -1;
            } else if(s.charAt(i) == &#39;{&#39; || s.charAt(i) == &#39;}&#39;) {
                midCount += s.charAt(i) == &#39;{&#39; ? 1 : -1;
            } else {
                smallCount += s.charAt(i) == &#39;(&#39; ? 1 : -1;
            }
        }

        bigBracket = bigCount == 0 ? true : false;
        midBracket = midCount == 0 ? true : false;
        smallBracket = smallCount == 0 ? true : false;

        return bigBracket == true &amp;&amp; midBracket == true &amp;&amp; smallBracket == true ? true : false;
    }
}</code></pre>
<br>

<blockquote>
<p><strong>답안 확인한 후 적용한 풀이</strong></p>
</blockquote>
<p>답안은 Stack을 사용했다.</p>
<p>열린 괄호를 만나면, 스택에 해당 괄호와 같은 종류의 닫힌 괄호를 저장한다.</p>
<blockquote>
<p>닫힌 괄호를 만나면, 가장 최근에 스택에 저장한 값을 반환하여 비교한다.
→ 같으면 삭제하고, 다르면 <code>false</code> 를 <code>return</code> 한다.</p>
</blockquote>
<p>마지막에는 <code>isEmpty()</code> 를 사용하여 비어 있으면 성공적으로 탐색을 마친 것이므로 <code>true</code> 를 반환하도록 한다.</p>
<h2 id="코드-구현">코드 구현</h2>
<pre><code class="language-java">class Solution {
    public boolean isValid(String s) {
        Deque&lt;Character&gt; stack = new ArrayDeque&lt;&gt;();

        for(int i = 0; i &lt; s.length(); i++) {
            if(s.charAt(i) == &#39;(&#39;) {
                stack.push(&#39;)&#39;);
            } else if(s.charAt(i) == &#39;{&#39;) {
                stack.push(&#39;}&#39;);
            } else if(s.charAt(i) == &#39;[&#39;) {
                stack.push(&#39;]&#39;);
            } else if(!stack.isEmpty() &amp;&amp; stack.peek() == s.charAt(i)) {
                stack.pop();
            } else {
                return false;
            }
        }

        return stack.isEmpty();
    }
}</code></pre>
<h2 id="배우게-된-점">배우게 된 점</h2>
<p>Stack을 응용하는 법을 알게 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 완주하지 못한 선수]]></title>
            <link>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%9C-%EC%84%A0%EC%88%98</link>
            <guid>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%9C-%EC%84%A0%EC%88%98</guid>
            <pubDate>Tue, 22 Apr 2025 06:53:24 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="문제-파악">문제 파악</h2>
<h3 id="완주하지-못한-선수"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42576">완주하지 못한 선수</a></h3>
<p>마라톤 선수들이 마라톤에 참여했다.</p>
<p>단 한 명을 제외하고는 모두 완주했다.</p>
<p>마라톤에 참여한 선수들의 이름이 담긴 배열 participant과, 완주한 선수들의 이름이 담긴 배열 completion이 주어진다.</p>
<p>완주하지 못한 선수의 이름을 return하라.</p>
<br>

<p><strong>입력</strong></p>
<table>
<thead>
<tr>
<th align="center">participant</th>
<th align="center">completion</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[&quot;leo&quot;, &quot;kiki&quot;, &quot;eden&quot;]</td>
<td align="center">[&quot;eden&quot;, &quot;kiki&quot;]</td>
</tr>
<tr>
<td align="center">[&quot;marina&quot;, &quot;josipa&quot;, &quot;nikola&quot;, &quot;vinko&quot;, &quot;filipa&quot;]</td>
<td align="center">[&quot;josipa&quot;, &quot;filipa&quot;, &quot;marina&quot;, &quot;nikola&quot;]</td>
</tr>
<tr>
<td align="center">[&quot;mislav&quot;, &quot;stanko&quot;, &quot;mislav&quot;, &quot;ana&quot;]</td>
<td align="center">[&quot;stanko&quot;, &quot;ana&quot;, &quot;mislav&quot;]</td>
</tr>
</tbody></table>
<br>

<p><strong>출력</strong></p>
<table>
<thead>
<tr>
<th align="center">return</th>
</tr>
</thead>
<tbody><tr>
<td align="center">&quot;leo”</td>
</tr>
<tr>
<td align="center">&quot;vinko”</td>
</tr>
<tr>
<td align="center">&quot;mislav”</td>
</tr>
</tbody></table>
<hr>
<h2 id="접근-방법">접근 방법</h2>
<blockquote>
<p><strong>배열의 정렬을 이용한 풀이(현재 풀이)</strong></p>
</blockquote>
<p>문자열도 정렬을 할 수 있을까? → <strong>문자열도 <code>Arrays.sort</code>를 이용해서 정렬이 가능하다.</strong></p>
<p>문자열 정렬을 확인했으니 이 문제는 간단하게 풀 수 있을 것 같다.</p>
<p>주어진 입력은 규칙이 있다.</p>
<p>참가자와 완주자에는 단 한 명의 이름이 없다는 것 외에는 동일하다.</p>
<p>그럼 두 배열을 오름차순으로 정렬시킨 후 서로 비교해서 없는 사람을 찾으면 된다.</p>
<p>하지만 여기엔 반례가 있다.</p>
<p>두 배열에는 길이가 1만큼 차이가 있으며, 완주하지 못한 사람이 가장 마지막에 있을 경우가 그 예이다.</p>
<p>그에 대해선 <code>if</code>로 조건을 처리해주면 될 것이다.</p>
<br>

<p><strong>문제 알고리즘 구현 순서</strong></p>
<ol>
<li>두 배열을 정렬한다.<ul>
<li>정렬이 되면 두 배열은 같은 순서와 같은 값을 가질 것이다.</li>
<li>참가자와 완주자 명단은 한 명의 유무를 제외하고는 동일하기 때문이다.</li>
</ul>
</li>
<li>for 반복문을 하나 생성하고 두 배열을 비교한다.<ul>
<li>완주한 선수 배열이 길이가 더 짧으니 완주한 선수 배열의 길이로 반복 횟수를 설정한다.</li>
<li>순서를 정렬했으니, 순차적으로 비교해도 값은 일치할 것이다.</li>
<li>중간에 일치하지 않는 경우가 바로 완주하지 못한 선수의 이름이다.</li>
<li>만약 일치하지 않는 경우를 찾지 못 하고 반복문이 끝난다면, 참여 선수 배열의 마지막 값이 완주하지 못한 선수의 이름이 된다.</li>
</ul>
</li>
</ol>
<br>

<p><strong>시간 복잡도: O(n log n)</strong> → 정렬의 시간 복잡도이다.</p>
<hr>
<br>

<blockquote>
<p><strong>HashMap을 이용한 풀이(찾아본 다른 풀이) → 시간 복잡도 측면에서 좀 더 효율적이다.</strong></p>
</blockquote>
<p>두 배열을 순차적으로 꺼내면서 나온 선수들의 이름을 카운트 하는 방식은 어떨까?</p>
<p><code>HashMap</code>에 <code>Key</code>값으로 선수의 이름을 넣고, <code>Value</code>값으로 선수의 이름이 나온 횟수를 카운트 하자.</p>
<p>그 후 다시 반복문을 돌리면서 나온 선수의 이름을 차감하면 혼자만 값이 다른 선수가 완주하지 못한 선수가 된다.</p>
<pre><code class="language-java">import java.util.HashMap;

class Solution {
    public String solution(String[] participant, String[] completion) {
        HashMap&lt;String, Integer&gt; hashmap = new HashMap&lt;&gt;();

        for(String name : participant) {
            hashmap.put(name, hashmap.getOrDefault(name, 0) + 1);
        }

        for(String name : completion) {
            hashmap.put(name, hashmap.get(name) - 1);
        }

        for(String name : hashmap.keySet()) {
            if(hashmap.get(name) != 0) {
                return name;
            }
        }

        return &quot;&quot;;
    }
}</code></pre>
<blockquote>
<p><strong>HashMap&lt;String, Integer&gt; hashmap = new HashMap&lt;&gt;();</strong> 
→ <code>HashMap</code> 선언부이다. <code>key</code>를 <code>String</code> 타입으로, <code>value</code>를 <code>Integer</code> 타입으로 선언했다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>for(String name : participant)</strong>
→ <code>particiant</code>의 값을 하나씩 꺼내어 <code>name</code>에 넣는다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>hashmap.put(name, hashmap.getOrDefault(name, 0) + 1);</strong><br>→ <code>hashmap.getOrDefault(name, 0) + 1</code> → <code>name key</code>가 <code>HashMap</code>에 있으면 그 <code>key</code>의 <code>value</code>값을 반환한다. 없으면 0을 반환한다. 이후 1을 증가시킨다.
→ <code>hashmap.put()</code> → 위에서 나온 값을 <code>HashMap</code>의 <code>key</code> 값이 일치하는 곳에 저장한다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>for(String name : completion)</strong>
→ <code>completion</code>의 값을 하나씩 꺼내어 <code>name</code>에 넣는다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>hashmap.get(name) - 1</strong>
→ <code>HashMap</code>에서 <code>name key</code>에 해당하는 <code>value</code> 값을 가져온다. 가져온 값에는 1을 차감한다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>hashmap.put(name, hashmap.get(name) - 1);</strong>
→ 위에서 나온 값을 다시 <code>name key</code>에 일치하는 <code>value</code> 값에 넣는다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>for(String name : hashmap.keySet())</strong>
→ <code>HashMap</code>의 <code>key</code>값들을 추려서 <code>Set&lt;String&gt;</code>형태로 변환한다. → 그 후 <code>name</code>에 하나씩 저장한다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>if(hashmap.get(name) != 0)</strong>
<strong>return name</strong>
→ <code>name</code>의 값과 일치하는 <code>HashMap</code>의 <code>key</code>가 가지고 있는 <code>value</code> 값이 0이 아니면, 해당 <code>name</code>을 <code>return</code>한다.</p>
</blockquote>
<br>

<blockquote>
<p><strong>return &quot;&quot;;</strong>
→ 컴파일 에러 방지용 <code>return</code></p>
</blockquote>
<br>

<p><strong>시간 복잡도: O(n)</strong></p>
<hr>
<h2 id="코드-구현">코드 구현</h2>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public String solution(String[] participant, String[] completion) {
        String answer = &quot;&quot;;

        Arrays.sort(participant);
        Arrays.sort(completion);

        for(int i = 0; i &lt; completion.length; i++) {
            if(participant[i].equals(completion[i]) == false) {
                return participant[i];
            }
        }

        return participant[participant.length - 1];
    }
}</code></pre>
<hr>
<h2 id="배우게-된-점">배우게 된 점</h2>
<p>문자열 배열도 정렬이 가능하다는 사실을 알았다.</p>
<p><code>HashMap</code>의 기본적인 사용법에 대해 익힐 수 있었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 상속 - 타입 변환]]></title>
            <link>https://velog.io/@kid_an/Java-%EC%83%81%EC%86%8D-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@kid_an/Java-%EC%83%81%EC%86%8D-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98</guid>
            <pubDate>Mon, 21 Apr 2025 08:36:22 GMT</pubDate>
            <description><![CDATA[<h2 id="자바의-상속과-타입-변환에-대해">자바의 상속과 타입 변환에 대해</h2>
<pre><code class="language-java">class Parent {
    String field1;
    void method1() {
        System.out.println(&quot;부모의 메소드1&quot;);
    }
    void method2() {
        System.out.println(&quot;부모의 메소드2&quot;);
    }
}

class Child extends Parent {
    String field2;
    void method3() {
        System.out.println(&quot;자식의 메소드3&quot;);
    }
}

public class ChildExample {
    public static void main(String[] args) {
        Parent parent = new Child();

        parent.field2 = &quot;yyy&quot;;
        parent.method3();
    }
}</code></pre>
<p>해당 코드를 실행하려 하면 <code>field2</code>와 <code>method3</code>에 대해서 <code>Symbol</code>을 찾을 수 없다는 에러가 나온다.</p>
<p>이는 즉, <code>field2</code>와 <code>method3</code>를 찾을 수 없다는 뜻이다.</p>
<h3 id="이유가-뭘까">이유가 뭘까?</h3>
<p>정답은 <code>Parent parent = new Child();</code> 이 한 줄에 있다.</p>
<p>해당 코드를 살펴보면, <code>Parent</code> 로 부모 타입의 참조 변수를 생성했기 때문에 <code>Child</code> 클래스에만 있는 멤버(필드 혹은 메서드)에 접근할 수 없기 때문이다.</p>
<p><strong>부모 타입으로 참조 변수를 생성했으면</strong> 자식 클래스의 객체 인스턴스를 생성하더라도 <strong>부모 타입에 있는 필드와 메서드만 사용할 수 있다.</strong></p>
<p>하지만 현재 코드에서는 <code>field2</code>와 <code>method3</code>가 자식 클래스에만 있기 때문에 찾을 수 없다는 에러가 발생하게 되는 것이다.</p>
<p>해당 코드처럼 자식 클래스에만 있는 필드와 메서드를 사용하려면, <strong>강제 타입 변환</strong>을 해줘야 한다.</p>
<pre><code class="language-java">class Parent {
    String field1;

    void method1() {
        System.out.println(&quot;부모의 메소드1&quot;);
    }
    void method2() {
        System.out.println(&quot;부모의 메소드2&quot;);
    }
}

class Child extends Parent {
    String field2;

    void method3() {
        System.out.println(&quot;자식의 메소드3&quot;);
    }
}

public class ChildExample {
    public static void main(String[] args) {
        Parent parent = new Child();
        Child child = (Child) parent; // 강제 타입 변환

        parent.field2 = &quot;yyy&quot;;
        parent.method3();
    }
}</code></pre>
<p>위 코드와 같이 <code>Child child = (Child) parent;</code> 코드를 한 줄 추가해주면, <code>parent</code> 참조 변수가 <code>Child</code> 타입 참조 변수로 강제 변환 되어 <code>Child</code>에만 있는 필드와 메서드를 사용할 수 있게 된다.</p>
<p>혹은 다음과 같이 코드를 수정해도 된다.</p>
<pre><code class="language-java">class Parent {
    String field1;
    String field2;

    void method1() {
        System.out.println(&quot;부모의 메소드1&quot;);
    }
    void method2() {
        System.out.println(&quot;부모의 메소드2&quot;);
    }
    void method3() {
        System.out.println(&quot;부모의 메소드3&quot;);
    }
}

class Child extends Parent {
    String field2;

    void method3() {
        System.out.println(&quot;자식의 메소드3&quot;);
    }
}

public class ChildExample {
    public static void main(String[] args) {
        Parent parent = new Child();

        parent.field2 = &quot;yyy&quot;;
        parent.method3();
    }
}</code></pre>
<p>위와 같이 코드를 수정하면 <code>Child</code> 클래스는 부모 클래스인 <code>Parent</code> 클래스에서 필드와 메소드를 상속 받아 다시 정의한 것이기 때문에 타입 변환 없이 그대로 사용할 수 있게 된다.</p>
<p>이 때 부모 클래스에 있는 필드나 메서드를 그대로 자식 클래스에서 가져와 다시 정의하는 것을 <strong>재정의</strong>라고 하며 오버라이딩(Overriding)이라고 부른다.</p>
<p>이때 재정의된 필드나 메서드에 <code>@Override</code> 어노테이션을 붙이기도 한다.</p>
<h3 id="그러면-생성자의-호출-순서는-어떻게-될까">그러면 생성자의 호출 순서는 어떻게 될까?</h3>
<p>생성자의 호출 순서를 알기 전에 생성자가 무엇인지 알아야 한다.</p>
<p><strong>생성자란?</strong></p>
<p>생성자는 클래스의 인스턴스가 생성될 때 호출되는 특별한 메서드이다.</p>
<p>생성자의 이름은 클래스 이름과 같아야 하며, 반환 타입은 없다.</p>
<ul>
<li>생성자는 <code>new</code> 키워드를 통해 객체를 생성할 때 자동으로 호출된다.</li>
</ul>
<pre><code class="language-java">Parent parent = new Child(); // new Child()에서 Child()가 생성자이다.</code></pre>
<ul>
<li>클래스에 생성자를 정의하지 않으면, 자바는 컴파일할 때 자동으로 기본 생성자를 제공하게 된다.</li>
</ul>
<p>→ 생성자의 매개변수가 없으며, 내부 코드가 없는 몸체만 제공한다.</p>
<p>클래스간의 상속이 이루어질 때, 생성자에도 호출 순서가 있다.</p>
<p>생성자는 항상 <strong>부모 생성자가 먼저 실행</strong>되며, 그 후에 자식 생성자가 실행된다.</p>
<p>우리는 자바 코드에서 종종 이런 코드를 볼 수 있다.</p>
<pre><code class="language-java">Parent parent = new Child();</code></pre>
<p>이 코드를 뜯어 보면, <code>Parent</code> 타입으로 참조 변수를 선언하고, 참조 변수의 명을 <code>parent</code>로 정의했다. 그리고 <code>new</code> 연산자를 통해 <code>Child()</code>라는 생성자를 호출하고 있다. <em>Child는 Child 클래스의 생성자이다.</em></p>
<p>정리하자면 Parent 타입 참조 변수 parent에 Child() 생성자를 호출하여 초기화 하고 있는 것이다.</p>
<p>우리는 Child() 생성자를 호출했기에 Child() 생성자가 먼저 실행될 것이라고 생각하기 쉽다.</p>
<p>하지만 Java는 컴파일 될 때 항상 부모 클래스의 생성자를 먼저 실행시킨다.</p>
<p><strong>예시</strong></p>
<pre><code class="language-java">class Parent {
    Parent() {
        System.out.println(&quot;부모 생성자&quot;);
    }
}

class Child extends Parent {
    Child() {
        System.out.println(&quot;자식 생성자&quot;);
    }
}

public class ParentTest {
    public static void main(String[] args) {
        Parent p = new Child();
    }
}
</code></pre>
<p>위 코드를 실행시키게 되면,</p>
<pre><code class="language-java">부모 생성자
자식 생성자</code></pre>
<p>위와 같은 결과가 나온다.</p>
<p>이 코드의 결과로 부모 생성자가 먼저 실행된다는 것을 알 수 있다.</p>
<p>원리는 이렇다.</p>
<p>자식 클래스 생성자에는 위 코드와 같이 <code>super()</code>를 적지 않을 수도 있다.</p>
<p>여기서 <strong>super()란 부모 클래스의 메소드를 호출</strong>하는 키워드이다.</p>
<p>하지만 자바는 컴파일 될 시 자식 클래스에 <code>super()</code> 가 없으면 자동으로 생성해서 실행하기 때문에 항상 부모 클래스의 생성자가 먼저 실행되게 되는 것이다.</p>
<p>하지만 이런 생각이 들 수도 있다.</p>
<p><strong>코드에서 new Child()로 자식 클래스의 생성자를 호출했으니 자식 클래스 생성자가 먼저 실행된 것 아닌가요?</strong></p>
<p>좀 헷갈릴 수 있는 부분이지만 답은 <strong>아니다</strong> 이다.</p>
<p>이유는 <strong>호출</strong>과 <strong>실행</strong>의 차이점에 있다.</p>
<p>호출과 실행은 비슷한 개념이지만 서로 다른 의미를 가지고 있다.</p>
<p><strong>1, 호출</strong></p>
<p><strong>호출</strong>은 메서드나 생성자, 함수 등을 <strong>실행하라고 요청하는 것</strong>을 말한다. 다시 말해 “해당 코드를 실행해!”라고 컴퓨터에게 알려주는 동작인 것이다. 즉, 실행하는 것이 아닌 실행하라고 명령하는 <strong>신호</strong>인 것이다.</p>
<p><strong>2. 실행</strong></p>
<p><strong>실행</strong>은 호출된 메서드나 생성자 내부의 코드가 실제로 <strong>실행되는 과정</strong>을 말한다. 호출이 일어난 뒤, 그 메서드나 생성자 안에 있는 코드가 <strong>한 줄씩 순차적으로 실행</strong>되는 것이다.</p>
<p>따라서 코드로 살펴보면,</p>
<pre><code class="language-java">class Parent {
    Parent() {
        System.out.println(&quot;부모 생성자&quot;);
    }
}

class Child extends Parent {
    Child() {
        System.out.println(&quot;자식 생성자&quot;);
    }
}

public class ParentTest {
    public static void main(String[] args) {
        Parent p = new Child();
    }
}</code></pre>
<p>위 코드에서 <code>new Child()</code> 부분은 <code>Child</code> 생성자를 실행하라고 호출한 것이다.</p>
<p>그래서 컴퓨터가 실행하려고 <code>Child</code> 생성자를 봤더니, 이는 <code>Parent</code> 클래스에서 상속받은 클래스의 생성자인 것이다.</p>
<p>컴퓨터는 <code>Child</code> 생성자의 첫 줄에 <code>super()</code>를 자동으로 생성하고, <code>super()</code>는 부모 클래스 생성자를 호출하는 키워드이기에 <code>Child</code> 생성자가 실행되지 않고 <code>Parent</code> 생성자를 먼저 실행한 것이다.</p>
<p>이후 <code>Parent</code> 생성자의 실행이 끝난 뒤에 다시 <code>Child</code> 생성자로 돌아가 <code>Child</code> 생성자를 실행하게 되는 것이다.</p>
<p>요약하자면,</p>
<ol>
<li>Child() 생성자 호출</li>
<li>Child() 생성자 첫 줄에 super() 생성</li>
<li>super()에 의해 Parent() 실행</li>
<li>Parent() 실행</li>
<li>Child() 실행</li>
</ol>
<p><img src="https://velog.velcdn.com/images/kid_an/post/f16e56d6-9ada-4885-9057-79cf2ebf0e75/image.png" alt=""></p>
<p>그래서 아래와 같은 실행 결과가 나오는 것이다.</p>
<pre><code class="language-java">부모 생성자
자식 생성자</code></pre>
<p>추가로 자식 클래스 생성자에 <code>super</code> 키워드를 작성할 때는 항상 자식 생성자의 <strong>첫 줄</strong>에 작성해야한다.</p>
<p>그렇지 않으면 <code>super</code>  키워드가 자식 클래스 생성자의 첫 줄에 없다는 에러를 마주하게 될 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 예산]]></title>
            <link>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%98%88%EC%82%B0-ua3uxd5s</link>
            <guid>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%98%88%EC%82%B0-ua3uxd5s</guid>
            <pubDate>Fri, 18 Apr 2025 08:52:28 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-파악">문제 파악</h2>
<p>주어진 예산 안에서 최대로 지원할 수 있는 부서의 수를 구하라.</p>
<h2 id="접근-방법">접근 방법</h2>
<p>정해진 예산 안에서 최대한 많은 부서에 지원을 해야한다.</p>
<p>그렇다면 부서별 요청 금액이 들어 있는 배열을 오름차순으로 정렬해준다.</p>
<p>그 후 예산 범위 보다 작거나 같을 때까지 앞에서 부터 차례대로 더한 후 더한 횟수를 반환하면  된다.</p>
<h2 id="코드-구현">코드 구현</h2>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public int solution(int[] d, int budget) {
        int answer = 0;
        int sum = 0;

        Arrays.sort(d); // 주어진 배열을 오름차순 정렬

        // 배열을 하나씩 꺼내서 더한다.
        // 더한 값이 budget보다 커지면 반복문을 종료한다.
        // 문제에서는 budget보다 작거나 같은 경우를 원하기 때문에 더한 횟수에서 1을 뺀다.
        // budget보다 커진 경우는 한 번을 더 더했기 때문이다.
        for(int i = 0; i &lt; d.length; i++) {
            sum += d[i];
            answer++;

            if(sum &gt; budget) {
                answer--;
                break;
            }
        }

        return answer;
    }
}</code></pre>
<h2 id="배우게-된-점">배우게 된 점</h2>
<p>Arrays.sort() 메소드를 배웠습니다.</p>
<p>해당 메소드를 배우기 전에는 코드록 정렬을 직접 구현해서 사용했었는데, Arrays.sort()를 알게 된 뒤 코드가 훨씬 간결해져서 좋았습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드 풀이] 예산]]></title>
            <link>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%98%88%EC%82%B0</link>
            <guid>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%98%88%EC%82%B0</guid>
            <pubDate>Fri, 18 Apr 2025 08:51:45 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-파악">문제 파악</h2>
<h3 id="예산"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12982">예산</a></h3>
<p>주어진 예산 안에서 최대로 지원할 수 있는 부서의 수를 구하라.</p>
<h2 id="접근-방법">접근 방법</h2>
<p>정해진 예산 안에서 최대한 많은 부서에 지원을 해야한다.</p>
<p>그렇다면 부서별 요청 금액이 들어 있는 배열을 오름차순으로 정렬해준다.</p>
<p>그 후 예산 범위 보다 작거나 같을 때까지 앞에서 부터 차례대로 더한 후 더한 횟수를 반환하면  된다.</p>
<h2 id="코드-구현">코드 구현</h2>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public int solution(int[] d, int budget) {
        int answer = 0;
        int sum = 0;

        Arrays.sort(d); // 주어진 배열을 오름차순 정렬

        // 배열을 하나씩 꺼내서 더한다.
        // 더한 값이 budget보다 커지면 반복문을 종료한다.
        // 문제에서는 budget보다 작거나 같은 경우를 원하기 때문에 더한 횟수에서 1을 뺀다.
        // budget보다 커진 경우는 한 번을 더 더했기 때문이다.
        for(int i = 0; i &lt; d.length; i++) {
            sum += d[i];
            answer++;

            if(sum &gt; budget) {
                answer--;
                break;
            }
        }

        return answer;
    }
}</code></pre>
<h2 id="배우게-된-점">배우게 된 점</h2>
<p>Arrays.sort() 메소드를 배웠습니다.</p>
<p>해당 메소드를 배우기 전에는 코드록 정렬을 직접 구현해서 사용했었는데, Arrays.sort()를 알게 된 뒤 코드가 훨씬 간결해져서 좋았습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드 풀이] 소수 구하기]]></title>
            <link>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%86%8C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-hjeubbrq</link>
            <guid>https://velog.io/@kid_an/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%86%8C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-hjeubbrq</guid>
            <pubDate>Fri, 18 Apr 2025 08:49:12 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-파악">문제 파악</h2>
<p>주어진 숫자 중 서로 다른 3개를 골라 더했을 때, 나올 수 있는 소수의 개수를 구하라.</p>
<h2 id="접근-방법">접근 방법</h2>
<ul>
<li><strong>현재 코드에 적용된 방법</strong></li>
</ul>
<p><strong>소수란 무엇인가?</strong></p>
<ul>
<li><p>1과 자기 자신 만을 약수로 갖는 수이다.</p>
  <br>

</li>
</ul>
<p><strong>소수를 판단하는 방법</strong></p>
<ol>
<li>단순히 2부터 n-1까지 나머지 연산자로 연산한다.<pre><code> - 이 과정에서 나머지가 0이 되는 수가 없다면 이 수는 소수인 것이다.</code></pre>   → 하지만 이 방법은 2부터 n-1까지 반복 연산을 수행하므로 비효율적이다. 시간복잡도는 O(n-2)</li>
</ol>
<ul>
<li>소수의 특성</li>
</ul>
<p>어떤 수 N은 작은 수 * 큰 수 형태로 이루어져 있다.</p>
<p>N의 제곱근 보다 큰 수로 N을 나눈다면 그 몫은 이미 이전에 걸러져 있다.</p>
<pre><code class="language-java">24 = 2 × 12  
24 = 3 × 8  
24 = 4 × 6  
24 = 6 × 4 ← 이 부분부터는 순서만 바뀐다.
24 = 8 × 3
24 = 12 × 2</code></pre>
<p>24의 제곱근 = 약 4.89</p>
<p>4.89보다 큰 24의 약수는 6</p>
<p>하지만 6은 이미 4 * 6에서 걸러진다.</p>
<p>즉, 24의 제곱근 미만인 수만 확인하면 된다.</p>
<p>11이 소수인지 판별하려면?</p>
<p>11의 제곱근 = 약 3.31</p>
<p>3.31 미만인 수 1, 2</p>
<p>소수는 1과 자기 자신 만을 약수로 갖는 수이므로 1은 제외</p>
<p>2는 11의 약수인가? → ❌</p>
<p>그러므로 11은 소수이다.</p>
<p>Java에서 제곱근을 구하려면 Math.sqrt()를 사용하면 된다.</p>
<p>어떤 수 N이 소수인지 판별하려면?</p>
<pre><code class="language-java">for(int i = 2; i &lt; Math.sqrt(N); i++) {
    if(N % i == 0) {
        break;
    }
}</code></pre>
<p>이런 식으로 작성하면 된다.</p>
<ul>
<li><strong>서로 다른 숫자 3개를 뽑아야 한다.</strong><ol>
<li>배열의 시작 인덱스부터 3개의 숫자를 순차적으로 뽑는다.<ul>
<li>arr[0], arr[1], arr[2]<br></li>
</ul>
</li>
<li>그 후 arr[2]만 순차적으로 증가 시켜 더한다.</li>
<li>arr[2]가 배열의 끝(arr[n])에 도달했다면, arr[1]과 arr[2]의 인덱스를 1 증가시킨다.<ul>
<li>arr[0], arr[2], arr[3]<br></li>
</ul>
</li>
<li>2 - 3의 과정을 반복한다.</li>
<li>최종적으로 아래와 같은 형태가 되면 arr[0]의 인덱스를 1 증가시킨다.<ul>
<li>arr[0], arr[n-1], arr[n]
→ arr[1], arr[2], arr[3]<br></li>
</ul>
</li>
<li>그 후 2 - 5의 과정을 반복하면 주어진 배열에서 3가지의 수를 더하는 모든 경우의 수를 얻을 수 있다.</li>
</ol>
</li>
</ul>
<p>위의 방법을 사용하여 코드를 작성해 본다.</p>
<p>→ 3중 for문을 사용하자.</p>
<p>for문의 시간 복잡도: O(n)</p>
<p>2중 for문의 시간 복잡도: O(n^2)</p>
<p>3중 for문의 시간 복잡도: O(n^3)</p>
<p>문제의 제한사항</p>
<p>배열의 길이 n은 3 ≤ n ≤ 50이다.</p>
<p>최악의 경우 50^3까지 반복할 수 있다.</p>
<p>50^3 &lt; 10^8 이므로, 3중 for문을 사용해도 된다.</p>
<ul>
<li><p><strong>재귀 함수를 이용한 풀이</strong></p>
<pre><code class="language-java">  class Solution {
      int answer = 0;

      public int solution(int[] nums) {
          comb(nums, 0, 0, 0); // 조합 뽑기 시작
                                                   // 최초에는 아직 아무것도 뽑지 않았으므로 0, 0, 0
          return answer;
      }

          // count = 뽑은 횟수
          // sum = 뽑은 수의 합
          // start = 다음에 뽑을 인덱스
      void comb(int[] nums, int count, int sum, int start) {
              // 3회 뽑았으면 소수 판별 시작
          if(count == 3) {
                  // 합이 소수이면 개수 카운트
              if(isPrime(sum)) {
                  answer++;
              }

              return;
          }

                  // 반복문을 통한 재귀호출로 다음 숫자 뽑기
          for(int i = start; i &lt; nums.length; i++) {
              comb(nums, count + 1, sum + nums[i], i + 1);
          }
      }

      boolean isPrime(int n) {
          if(n &lt; 2) {
              return false;
             }

          for(int i = 2; i &lt;= Math.sqrt(n); i++) {
              if(n % i == 0) return false;
          }

          return true;
      }
  }</code></pre>
</li>
<li><p><strong>에라토스테네스의 체를 사용한 풀이</strong></p>
<ul>
<li><p><strong>에라토스테네스의 체</strong></p>
<p> 주어진 자연수 N이 소수이기 위한 필요 충분 조건은 N이 N의 제곱근보다 크지 않은 어떤 소수로도 나눠지지 않는다.</p>
<p> 어떠한 수1과 어떠한 수2를 나누면 몫이 발생하게 되는데 몫과 나누는 수, 둘 중 하나는 반드시 해당 수의 제곱근 이하이기 때문이다.</p>
<p> → 즉, 2부터 시작해서, 그 수의 배수를 모두 지워나간다. 그러면 남아 있는 수는 모두 소수가 된다.</p>
<p> <strong>예시: 1부터 30까지의 모든 소수 구하기</strong></p>
<p> <code>2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30</code></p>
<ol>
<li><p>2는 소수니까 제외한 후 2의 배수를 모두 제거한다.</p>
<p><code>2 3 X 5 X 7 X 9 X 11 X 13 X 15 X 17 X 19 X 21 X 23 X 25 X 27 X 29 X</code></p>
</li>
<li><p>3은 소수이므로 제외한 후 3의 모든 배수를 제거한다.</p>
<p><code>2 3 X 5 X 7 X X X 11 X 13 X X X 17 X 19 X X X 23 X 25 X X X 29 X</code></p>
</li>
<li><p>5도 소수이므로 제외한 후 5의 모든 배수를 제거한다.</p>
<p><code>2 3 X 5 X 7 X X X 11 X 13 X X X 17 X 19 X X X 23 X 25 X X X 29 X</code></p>
<p>최종적으로 소수만 남게 되었다.</p>
</li>
</ol>
<p> <strong>코드로 구현해보자</strong></p>
<pre><code class="language-java">  import java.util.Arrays;

  public class SieveExample {
      public static void main(String[] args) {
          int n = 30; // 1부터 30까지 소수 찾기
          boolean[] isPrime = new boolean[n + 1];
          Arrays.fill(isPrime, true); // 일단 전부 소수라고 가정
          isPrime[0] = isPrime[1] = false; // 0과 1은 소수가 아님

          for (int i = 2; i * i &lt;= n; i++) {
              if (isPrime[i]) {
                  for (int j = i * i; j &lt;= n; j += i) {
                      isPrime[j] = false; // i의 배수 제거
                  }
              }
          }

          System.out.println(&quot;소수 목록:&quot;);
          for (int i = 2; i &lt;= n; i++) {
              if (isPrime[i]) {
                  System.out.print(i + &quot; &quot;);
              }
          }
      }
  }</code></pre>
<p>  <strong>Arrays.fill(배열명, 값)</strong></p>
<p>  → 배열 내부의 모든 값을 하나로 초기화 하는 메소드.</p>
<p>  <code>Arrays.fill(isPrime, true);</code>  → isPrime의 모든 인덱스의 값을 true로 초기화 함.</p>
<p>  소수는 true, 소수가 아닌 수는 false → 초기에는 모든 수를 소수로 가정!</p>
<p>  for문을 <code>i * i</code>부터 시작하는 이유</p>
<p>  i * i 이전의 값은 이미 지워졌기 때문이다.</p>
<p>  <strong>예시</strong></p>
<p>  i = 2일 때:</p>
<ul>
<li><p>2의 배수는 <code>4, 6, 8, 10, 12, ...</code></p>
<p>i = 3일 때:</p>
</li>
<li><p>3의 배수는 <code>6, 9, 12, 15, ...</code></p>
<p><code>3 * 3</code> 이전의 수는 <code>3 * 2</code>이다.</p>
<p>하지만 이전에 2의 배수를 지우는 과정에서 <code>2 * 3</code>으로 인해 지워졌다.</p>
<p>4일 경우를 확인해 보면, <code>4 * 2</code>, <code>4 * 3</code>은 2와 3의 배수를 지우는 과정인 <code>2 * 4</code>, <code>3 * 4</code>에서 지워졌다.</p>
<p>5일 경우를 확인해 보면, <code>5 * 4</code>, <code>5 * 3</code>, <code>5 * 2</code> 는 모두 2와 3과 4의 배수를 지우는 과정인 <code>2 * 5</code>, <code>3 * 5</code>, <code>4 * 5</code> 에서 지워졌다.</p>
</li>
<li><p><em>결론*</em></p>
<p><code>i * i</code> 미만의 값은 모두 이전 과정에서 지워졌기 때문에 반복문의 시작 값을 <code>i * i</code>로 설정한다.</p>
</li>
<li><p><em>시간복잡도: O(Nlog(log N))*</em></p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>**✅위의 에라토스테네스의 체를 가지고 코드를 구현해보자**

```java
import java.util.Arrays;

class Solution {
    public int solution(int[] nums) {
        int answer = 0;

        // 0. 오름차순 정렬
        Arrays.sort(nums);

        // 1. 합의 최댓값 구하기
        int n = nums.length;
        int maxSum = nums[n - 1] + nums[n - 2] + nums[n - 3];

        // 2. 에라토스테네스의 체로 소수 판별 배열 만들기
        boolean[] isPrime = new boolean[maxSum + 1];
        Arrays.fill(isPrime, true); // 일단 전부 소수라고 가정
        isPrime[0] = isPrime[1] = false; // 0과 1은 소수가 아님

        for (int i = 2; i * i &lt;= maxSum; i++) {
            if (isPrime[i]) {
                for (int j = i * i; j &lt;= maxSum; j += i) {
                    isPrime[j] = false;
                }
            }
        }

        // 3. 3개 조합 만들기 + 소수 판별
        for (int i = 0; i &lt; n - 2; i++) {
            for (int j = i + 1; j &lt; n - 1; j++) {
                for (int k = j + 1; k &lt; n; k++) {
                    int sum = nums[i] + nums[j] + nums[k];
                    if (isPrime[sum]) {
                        answer++;
                    }
                }
            }
        }

        return answer;
    }
}

```

**기존 코드와 시간 복잡도 비교**

1. 기존 코드
    - 3중첩 for문: **O(N^3)**
    - 소수 판별: **O(√N)**

1. 에라토스테네스의 체를 사용한 코드
    - 3중첩 for문: **O(N^3)**
    - 에라토스테네스의 체 만들기: **O(Nlog(log N))**
    - 소수 판별: **O(1)**

**N이 커지게 되면 에라토스테네스의 체 방식이 시간 복잡도가 효율적이다.**</code></pre><h2 id="코드-구현">코드 구현</h2>
<pre><code class="language-java">class Solution {
    public int solution(int[] nums) {
        int answer = 0;
        int sum = 0;

        for(int i = 0; i &lt; nums.length - 2; i++) {
            for(int j = i + 1; j &lt; nums.length - 1; j++) {
                for(int k = j + 1; k &lt; nums.length; k++) {
                    sum = nums[i] + nums[j] + nums[k];

                    boolean isBreak = false;

                    // 소수 판단
                    for(int l = 2; l &lt;= Math.sqrt(sum); l++) {
                        if(sum % l == 0) {
                            isBreak = true;
                            break;
                        }
                    }

                    if(!isBreak) {
                        answer++;
                    }
                }
            }
        }

        return answer;
    }
}</code></pre>
<h2 id="배우게-된-점">배우게 된 점</h2>
<ol>
<li>Math.sqrt() 사용법에 대해 알 수 있었다.</li>
<li>소수를 판별하는 에라토스테네스의 체를 익힐 수 있었다.</li>
<li>문제에 접근하고 떠올린 방법을 코드로 구현하는 능력을 기를 수 있었다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 참조 타입]]></title>
            <link>https://velog.io/@kid_an/%EC%9E%90%EB%B0%94-%EC%B0%B8%EC%A1%B0</link>
            <guid>https://velog.io/@kid_an/%EC%9E%90%EB%B0%94-%EC%B0%B8%EC%A1%B0</guid>
            <pubDate>Thu, 17 Apr 2025 07:28:20 GMT</pubDate>
            <description><![CDATA[<h2 id="참조형-타입에-대해">참조형 타입에 대해</h2>
<p>객체의 메모리 주소를 참조하는 타입이다.
배열, 열거, 클래스, 인터페이스 타입이 있다.</p>
<hr>
<br>

<h3 id="기본-타입과-참조-타입의-차이">기본 타입과 참조 타입의 차이</h3>
<p><strong>기본 타입</strong>
기본타입으로 선언된 <strong>변수는 값 자체를 저장</strong>한다.
스택에 값 자체를 저장한다.</p>
<p><strong>참조 타입</strong>
참조 타입으로 선언된 변수는 <strong>객체가 생성된 메모리 주소를 저장</strong>한다.
스택에 객체가 생성된 메모리 주소를 저장한다.
해당 메모리 주소를 참조하여 <strong>힙에 저장된 객체에 접근</strong>한다.</p>
<hr>
<br>

<h3 id="메모리-사용-영역">메모리 사용 영역</h3>
<p><strong>메소드, 힙, 스택 영역</strong></p>
<ul>
<li><p>JVM은 운영체제에서 할당받은 메모리 영역을 메소드 영역, 힙 영역, 스택 영역으로 구분해서 사용</p>
</li>
<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>
</ul>
<hr>
<br>

<h3 id="참조-타입-변수의---연산">참조 타입 변수의 ==, != 연산</h3>
<ul>
<li>==, != 연산자는 객체의 번지를 비교해 변수의 값이 같은지, 다른지를 조사한다.</li>
<li>번지가 같다면 동일한 객체를 참조하는 것이고, 다르다면 다른 객체를 참조하는 것이다.</li>
</ul>
<pre><code class="language-java">public static void main(String[] args) {
    int[] arr1; //배열 변수 arr1 선언
    int[] arr2; //배열 변수 arr2 선언
    int[] arr3; //배열 변수 arr3 선언

    arr1 = new int[] { 1, 2, 3 }; //배열 { 1, 2, 3 }을 생성하고 arr1 변수에 대입
    arr2 = new int[] { 1, 2, 3 }; //배열 { 1, 2, 3 }을 생성하고 arr2 변수에 대입
    arr3 = arr2; //배열 변수 arr2의 값을 배열 변수 arr3에 대입

    System.out.println(arr1 == arr2); // arr1과 arr2 변수가 같은 배열을 참조하는지 검사
    System.out.println(arr2 == arr3); // arr2와 arr3 변수가 같은 배열을 참조하는지 검사
}</code></pre>
<br>

<p><strong>결과</strong></p>
<pre><code>false
true</code></pre><p><code>arr1</code>과 <code>arr2</code>는 각각 선언 되었기에 서로 다른 객체의 메모리 주소를 참조한다.
<code>arr3</code>에 <code>arr2</code>를 대입했기 때문에 <code>arr3</code>는 <code>arr2</code>의 메모리 주소를 참조하고 있다. 따라서 <code>arr2</code>와 <code>arr3</code>는 <code>true</code>가 나온다.</p>
<hr>
<br>

<h3 id="문자열-타입">문자열 타입</h3>
<p>문자열은 Stirng 객체로 생성
String은 메모리 주소값을 참조하는 참조형 변수이다.</p>
<p>String 값을 비교하려면 equals로 비교해야한다.</p>
<pre><code class="language-java">String name1 = &quot;홍길동&quot;
String name2 = &quot;홍길동&quot;
String name3 = new String(&quot;홍길동&quot;);

name1 == name2
name1 == name3</code></pre>
<p><strong>결과</strong></p>
<pre><code>true
false</code></pre><br>

<p><code>String</code>은 서로 같은 값을 가지고 있으면 같은 참조로 본다.</p>
<p>하지만 <code>String name3</code>는 <code>new String(&quot;홍길동&quot;);</code> 으로 값은 같지만 새로 선언했기에 다른 참조를 가지고 있다.</p>
<p><strong>그럼 참조가 아닌 값을 비교하려면 어떻게 해야할까?</strong></p>
<p><code>name1.equals(name3);</code>로 값 자체가 같은지 비교하면 된다.</p>
<br>

<pre><code class="language-java">public static void main(String[] args) {
    String strVar1 = &quot;홍길동&quot;;
    String strVar2 = &quot;홍길동&quot;;

    if(strVar1 == strVar2) {
        System.out.println(&quot;strVar1과 strVar2는 참조가 같음&quot;);
    } else {
        System.out.println(&quot;strVar1과 strVar2는 참조가 다름&quot;);
    }

    if(strVar1.equals(strVar2)) {
        System.out.println(&quot;strVar1과 strVar2는 문자열이 같음&quot;);
    }

    String strVar3 = new String(&quot;홍길동&quot;);
    String strVar4 = new String(&quot;홍길동&quot;);

    if(strVar3 == strVar4) {
        System.out.println(&quot;strVar3과 strVar4는 참조가 같음&quot;);
    } else {
        System.out.println(&quot;strVar3과 strVar4는 참조가 다름&quot;);
    }

    if(strVar3.equals(strVar4)) {
        System.out.println(&quot;strVar3과 strVar4는 문자열이 같음&quot;);
    }
}</code></pre>
<br>

<p><strong>결과</strong></p>
<pre><code>strVar1과 strVar2는 참조가 같음
strVar1과 strVar2는 문자열이 같음
strVar3과 strVar4는 참조가 다름
strVar3과 strVar4는 문자열이 같음</code></pre><br>

<p><strong>문자열 추출</strong></p>
<ul>
<li>charAt() 메소드로 문자열에서 매개값으로 주어진 인덱스의 문자를 추출한다.</li>
</ul>
<pre><code class="language-java">String subject = &quot;자바 프로그래밍&quot;;

char charValue = subject.charAt(3);

System.out.print(charValue);</code></pre>
<p><strong>결과</strong></p>
<pre><code>프</code></pre><p>charAt은 문자열의 앞에서부터 위치를 매겨 특정 위치의 문자를 추출할 수 있다.
<em>0부터 시작한다.</em></p>
<table>
<thead>
<tr>
<th align="center">자</th>
<th align="center">바</th>
<th align="center"></th>
<th align="center">프</th>
<th align="center">로</th>
<th align="center">그</th>
<th align="center">래</th>
<th align="center">밍</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
<td align="center">5</td>
<td align="center">6</td>
<td align="center">7</td>
</tr>
</tbody></table>
<br>

<p><strong>문자열 길이</strong>
문자열에서 문자의 개수를 얻고 싶다면 <code>length()</code> 메소드를 사용한다.
<em>공백도 포함해서 계산된다.</em></p>
<br>

<p><strong>문자열 대체</strong>
<code>replace()</code> 메소드는 기존 무자열은 그대로 두고, 대체한 새로운 문자열을 리턴한다.</p>
<pre><code class="language-java">String oldStr = &quot;자바 프로그래밍&quot;;
String newStr = oldStr.replace(&quot;자바&quot;, &quot;JAVA&quot;);

System.out.print(newStr);</code></pre>
<br>

<p><strong>결과</strong></p>
<pre><code>JAVA 프로그래밍</code></pre><br>

<p><strong>문자열 잘라내기</strong>
문자열에서 특정 위치의 문자열을 잘라내어 가져오고 싶다면 <code>substring(시작 위치, 종료 위치)</code> 메소드를 사용한다.</p>
<p><em>종료 위치의 -1까지 잘라낸다.</em>
<em>종료 위치를 작성하지 않으면 시작 위치부터 문자열의 끝까지 잘라낸다.</em></p>
<pre><code class="language-java">String ssn = &quot;880815-1234567&quot;;
String firstNum = ssn.substring(0, 6);
String secondNum = ssn.substring(7);

System.out.println(firstNum);
System.out.print(secondNum);</code></pre>
<br>

<p><strong>결과</strong></p>
<pre><code>880815
1234567</code></pre><table>
<thead>
<tr>
<th align="center">8</th>
<th align="center">8</th>
<th align="center">0</th>
<th align="center">8</th>
<th align="center">1</th>
<th align="center">5</th>
<th align="center">-</th>
<th align="center">1</th>
<th align="center">2</th>
<th align="center">3</th>
<th align="center">4</th>
<th align="center">5</th>
<th align="center">6</th>
<th align="center">7</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
<td align="center">5</td>
<td align="center">6</td>
<td align="center">7</td>
<td align="center">8</td>
<td align="center">9</td>
<td align="center">10</td>
<td align="center">11</td>
<td align="center">12</td>
<td align="center">13</td>
</tr>
</tbody></table>
<br>

<p><strong>문자열 찾기</strong>
문자열에서 특정 문자열의 위치를 찾고자 할 때는 indexOf() 사용한다.</p>
<pre><code class="language-java">String subject = &quot;자바 프로그래밍&quot;;

int index = subject.indexOf(&quot;프로그래밍&quot;);
// 포함되어 있지 않으면 -1을 리턴한다.</code></pre>
<p>포함 여부 결과만 알고 싶은 경우 <code>constains()</code> 메소드를 사용한다.</p>
<pre><code class="language-java">boolean result = subject.contains(&quot;프로그래밍&quot;);</code></pre>
<br>

<p><strong>문자열 분리</strong>
구분자가 있는 여러 개의 문자열을 분리할 때 <code>split()</code> 메소드를 사용한다.</p>
<pre><code class="language-java">String board = &quot;번호,제목,내용,글쓴이&quot;;

String[] arr = board.split(&quot;,&quot;);</code></pre>
<hr>
<br>

<h3 id="배열-타입">배열 타입</h3>
<p><strong>배열의 선언 방법</strong></p>
<pre><code class="language-java">자료형 배열명 = new 자료형[배열의 크기]; // 동적 초기화
자료형[] 배열명 = {값1, 값2, 값3, ...}; // 정적 초기화</code></pre>
<br>

<p><strong>배열의 길이</strong>
배열의 길이는 문자열과 비슷하게 <code>length</code>로 확인한다.</p>
<p><em>문자열과는 ()의 유무의 차이가 있다</em>
<em>문자열: length();</em>
<em>배열: length;</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[정보처리기사] 제품 소프트웨어 패키징]]></title>
            <link>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%A0%9C%ED%92%88-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%ED%8C%A8%ED%82%A4%EC%A7%95</link>
            <guid>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%A0%9C%ED%92%88-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%ED%8C%A8%ED%82%A4%EC%A7%95</guid>
            <pubDate>Thu, 17 Apr 2025 02:18:51 GMT</pubDate>
            <description><![CDATA[<h2 id="릴리즈-노트-작성-항목">릴리즈 노트 작성 항목</h2>
<p>릴리즈 노트는 소프트웨어 개발 과정에서 정리된 릴리즈 정보를 최종 사용자인 고객과 공유하기 위한 문서이다.</p>
<p><strong>Header(머릿말)</strong>
릴리즈 노트 이름, 소프트웨어 이름, 릴리즈 버전, 릴리즈 날짜, 릴리즈 노트 날짜, 릴리즈 노트 버전 등</p>
<p><strong>개요</strong>
소프트웨어 및 변경사항 전체에 대한 간략한 내용</p>
<p><strong>목적</strong>
해당 릴리즈 버전에서의 새로운 기능이나 수정된 기능의 목록과 릴리즈 노트의 목적에 대한 간략한 개요</p>
<p><strong>문제 요약</strong>
수정된 버그에 대한 간략한 설명 또는 릴리즈 추가 항목에 대한 요약</p>
<p><strong>재현 항목</strong>
버그 발견에 대한 과정 설명</p>
<p><strong>수정/개선 내용</strong>
버그를 수정/개선한 내용을 간단히 설명</p>
<p><strong>사용자 영향도</strong>
사용자가 다른 기능들을 사용하는데 있어 해당 릴리즈 버전에서의 기능 변화가 미칠 수 있는 영향에 대한 설명</p>
<p><strong>SW 지원 영향도</strong>
해당 릴리즈 버전에서의 기능 변화가 다른 응용 프로그램들을 지원하는 프로세스에 미칠 수 있는 영향에 대한 설명</p>
<p><strong>노트</strong>
SW/HW 설치 항목, 업그레이드, 소프트웨어 문서화에 대한 참고 항목</p>
<p><strong>면책 조항</strong>
회사 및 소프트웨어와 관련하여 참조할 사항</p>
<p><strong>연락처</strong>
사용자 지원 및 문의 응대를 위한 연락처 정보</p>
<br>

<h2 id="디지털-저작권-관리의-구성-요소">디지털 저작권 관리의 구성 요소</h2>
<p><strong>클리어링 하우스(Clearing House)</strong>
저작권에 대한 사용 권한, 라이선스 발급, 암호화된 키 관리, 사용량에 따른 결제 관리 등을 수행하는 곳</p>
<p><strong>콘텐츠 제공자(Contents Provider)</strong>
콘텐츠를 제공하는 저작권자</p>
<p><strong>패키저(Packager)</strong>
콘텐츠를 메타 데이터와 함께 배포 가능한 형태로 묶어 암호화하는 프로그램</p>
<p><strong>콘텐츠 분배자(Contents Distributor)</strong>
암호화된 콘텐츠를 유통하는 곳이나 사람</p>
<p><strong>콘텐츠 소비자(Customer)</strong>
콘텐츠를 구매해서 사용하는 주체</p>
<p><strong>DRM 컨트롤러(DRM Controller)</strong>
배포된 콘텐츠의 이용 권한을 통제하는 프로그램</p>
<p><strong>보안 컨테이너(Security Container)</strong>
콘텐츠 원본을 안전하게 유통하기 위한 전자적 보안 장치</p>
<br>

<h2 id="디지털-저작권-관리의-기술-요소">디지털 저작권 관리의 기술 요소</h2>
<p><strong>암호화(Encryption)</strong>
콘텐츠 및 라이선스를 암호화하고 전자 서명을 할 수 있는 기술</p>
<p><strong>키 관리(Key Management)</strong>
콘텐츠를 암호화한 키에 대한 저장 및 분배 기술</p>
<p><strong>암호화 파일 생성</strong>
콘텐츠를 암호화된 콘텐츠로 생성하기 위한 기술</p>
<p><strong>식별 기술(Identification)</strong>
콘텐츠에 대한 식별 체계 표현 기술</p>
<p><strong>저작권 표현(Right Expression)</strong>
라이선스의 내용 표현 기술</p>
<p><strong>정책 관리(Policy Management)</strong>
라이선스 발급 및 사용에 대한 정책 표현 및 관리 기술</p>
<p><strong>크랙 방지(Tamper Resistance)</strong>
크랙에 의한 콘텐츠 사용 방지 기술</p>
<p><strong>인증(Authentication)</strong>
라이선스 발급 및 사용의 기준이 되는 사용자 인증 기술</p>
<br>

<h2 id="소프트웨어-설치-메뉴얼">소프트웨어 설치 메뉴얼</h2>
<ul>
<li>소프트웨어 설치 메뉴얼은 개발 초기에서부터 적용된 기준이나 사용자가 소프트웨어를 설치하는 과정에 필요한 내용을 기록한 설명서와 안내서이다.</li>
<li>설치 메뉴얼은 사용자 기준으로 작성한다.</li>
<li>설치 시작부터 완료할 때까지의 전 과정을 빠짐없이 순서대로 설명한다.</li>
<li>설치 과정에서 표시될 수 있는 오류 메시지 및 예외 상황에 관한 내용을 별도로 분류하여 설명한다.</li>
</ul>
<br>

<h2 id="소프트웨어-패키징의-형상-관리">소프트웨어 패키징의 형상 관리</h2>
<ul>
<li>형상 관리(SCM; Software Configuration Management)는 <strong>개발 과정에서 소프트웨어의 변경 사항을 관리하기 위해 개발된 일련의 활동</strong>이다.</li>
<li>형상 관리는 소프트웨어 개발의 전 단계에 적용되는 활동이며, 유지보수 단계에서도 수행된다.</li>
<li>형상 관리는 소프트웨어 개발의 전체 비용을 줄이고, 개발 과정의 여러 방해 요인이 최소화되도록 보증하는 것을 목적으로 한다.</li>
<li>대표적인 형상 관리 도구에는 Git, SVN, CVS 등이 있다.</li>
</ul>
<br>

<h2 id="형상-관리-기능">형상 관리 기능</h2>
<p><strong>형상 식별</strong>
형상 관리 대상에 이름과 관리 번호를 부여하고, 계층(Tree) 구조로 구분하여 수정 및 추적이 용이하도록 하는 작업</p>
<p><strong>버전 제어</strong>
소프트웨어 업그레이드나 유지 보수 과정에서 생성된 다른 버전의 형상 항목을 관리하고, 이를 위해 특정 절차와 도구(Tool)를 결합시키는 작업</p>
<p><strong>형상 통제</strong>
식별된 형상 항목에 대한 변경 요구를 검토하여 현재의 기준선(Base Line)이 잘 반영될 수 있도록 조정하는 작업</p>
<p><strong>형상 검사</strong>
기준선의 무결성을 평가하기 위해 확인, 검증, 검열 과정을 통해 공식적으로 승인하는 작업</p>
<p><strong>형상 기록</strong>
형상의 식별, 통제, 감사 작업의 결과를 기록/관리하고 보고서를 작성하는 작업</p>
<h2 id="소프트웨어의-버전-등록-관련-주요-기능">소프트웨어의 버전 등록 관련 주요 기능</h2>
<p><strong>저장소(Repository)</strong>
최신 버전의 파일들과 변경 내역에 대한 정보들이 저장되어 있는 곳</p>
<p><strong>가져오기(Import)</strong>
버전 관리가 되고 있지 않은 아무것도 없는 저장소에 처음으로 파일을 복사함</p>
<p><strong>체크아웃(Check-Out)</strong>
프로그램을 수정하기 위해 저장소에서 파일을 받아옴</p>
<p><strong>체크인(Check-In)</strong>
체크아웃 한 파일의 수정을 완료한 후 저장소의 파일을 새로운 버전으로 갱신함</p>
<p><strong>커밋(Commit)</strong>
체크인을 수행할 때 이전에 갱신된 내용이 있는 경우에는 충돌(Conflict)을 알리고 diff 도구를 이용해 수정한 후 갱신을 완료함</p>
<p><strong>동기화(Update)</strong>
저장소에 있는 최신 버전으로 자신의 작업 공간을 동기화함</p>
<br>

<h2 id="소프트웨어-버전-관리-도구---분산-저장소-방식">소프트웨어 버전 관리 도구 - 분산 저장소 방식</h2>
<ul>
<li>분산 저장소 방식은 버전 관리 자료가 하나의 <strong>원격 저장소와 분산된 개발자 PC의 지역 저장소에 함께 저장되어 관리되는 방식</strong>이다.</li>
<li>지역 저장소에서 버전 관리가 가능하므로 원격 저장소에 문제가 생겨도 지역 저장소의 자료를 이용하여 작업할 수 있다.</li>
<li>종류: Git, GNU arch, DCVS, Bazarr, Mercurial, TeamWare, Bitkeeper, Plastic SCM 등</li>
</ul>
<br>

<h2 id="빌드-자동화-도구">빌드 자동화 도구</h2>
<ul>
<li>빌드 자동화 도구는 <strong>빌드를 포함하여 테스트 및 배포를 자동화하는 도구</strong>이다.</li>
<li>애자일과 같은 지속적인 통합 개발 환경에서 유용하게 활용된다.</li>
<li>빌드 자동화 도구 종류: Jenkins, Gradle, Ant, Maven, Make 등</li>
</ul>
<br>

<h2 id="gradle">Gradle</h2>
<ul>
<li>Gradle은 Groovy를 기반으로 한 오픈 소스 형태의 자동화 도구이다.</li>
<li>안드로이드 앱 개발 환경에서 사용된다.</li>
<li>안드로이드뿐만 아니라 플러그인을 설정하면, JAVA, C/C++, Python 등의 언어도 빌드할 수 있다.</li>
<li>Groovy를 사용해서 만든 DSL(Domain Specific Language)을 스크립트 언어로 사용한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[정보처리기사] 네트워크, SW, HW, DB 관련 신기술]]></title>
            <link>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-SW-HW-DB-%EA%B4%80%EB%A0%A8-%EC%8B%A0%EA%B8%B0%EC%88%A0</link>
            <guid>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-SW-HW-DB-%EA%B4%80%EB%A0%A8-%EC%8B%A0%EA%B8%B0%EC%88%A0</guid>
            <pubDate>Wed, 16 Apr 2025 05:26:41 GMT</pubDate>
            <description><![CDATA[<h2 id="네트워크-관련-신기술">네트워크 관련 신기술</h2>
<p><strong>메시 네트워크(Mesh Network)</strong></p>
<ul>
<li>차세대 이동통신, 홈네트워킹, 공공 안정 등 특수 목적을 위한 새로운 방식의 네트워크 기술이다.</li>
<li>대규모 디바이스의 네트워크 생성에 최적화되어 있다.</li>
</ul>
<p><strong>피코넷(PICONET)</strong>
여러 개의 독립된 통신장치가 블루투스 기술이나 UWB 통신 기술을 사용하여 통신망을 형성하는 무선 네트워크 기술이다.</p>
<p><strong>애드 혹 네트워크(Ad-hoc Network)</strong></p>
<ul>
<li>재난 현장과 같이 별도의 고정된 유선망을 구축할 수 없는 장소에서 모바일 호스트(Mobile Host)만을 이용하여 구성한 네트워크이다.</li>
<li>망을 구성한 후 단기간 사용되는 경우나 유선망을 구성하기 어려운 경우에 적합하다.</li>
</ul>
<p><strong>파장 분할 다중화(WDM; Wavelength Division Multiplexing)</strong>
광섬유를 이용한 통신기술의 하나로, 파장이 서로 다른 복수의 신호를 보냄으로써 여러 대의 단말기가 동시에 통신 회선을 사용할 수 있도록 하는 기술이다.</p>
<p><strong>소프트웨어 정의 데이터센터(SDDC; Software Defined Data Center)</strong></p>
<ul>
<li>데이터 센터의 모든 자원을 가상화하여 인력의 개입 없이 소프트웨어 조작만으로 관리 및 제어되는 데이터 센터를 의미한다.</li>
<li>컴퓨팅, 네트워킹, 스토리지, 관리 등을 모두 소프트웨어로 정의한다.</li>
</ul>
<p><strong>개방형 링크드 데이터(LOD, Linked Open Data)</strong></p>
<ul>
<li>Linked Data와 Open Data의 합성어로, 누구나 사용할 수 있도록 웹상에 공개된 연계 데이터를 의미한다.</li>
<li>웹상에 존재하는 데이터를 개별 URI(인터넷 식별자)로 식별하고, 각 URI에 링크 정보를 부여함으로써 상호 연결된 웹을 지향하는 모형이다.</li>
</ul>
<p><strong>IoT(Internet of Things, 사물 인터넷)</strong>
정보 통신 기술을 기반으로 실세계와 가상 세계의 다양한 사물들을 인터넷으로 서로 연결하여 진보된 서비스를 제공하기 위한 서비스 기반 기술이다.</p>
<p><strong>클라우드 컴퓨팅(Cloud Computing)</strong>
각종 컴퓨팅 자원을 중앙 컴퓨터에 두고 인터넷 기능을 갖는 단말기로 언제 어디서나 인터넷을 통해 컴퓨터 작업을 수행할 수 있는 가상화된 환경을 의미한다.</p>
<p><strong>USN(Ubiquitous Sensor Network)</strong></p>
<ul>
<li>각종 센서로 수집한 정보를 무선으로 수집할 수 있도록 구성한 네트워크이다.</li>
<li>필요한 모든 것에 RFID 태그를 부착하고, 이를 통하여 사물의 인식정보는 물론 주변의 환경정보까지 탐지하여 이를 네트워크에 연결하여 정보를 관리한다.</li>
</ul>
<p><strong>SSO(Single Sign On)</strong></p>
<ul>
<li>한 번의 로그인으로 개인이 가입한 모든 사이트를 이용할 수 있게 해주는 시스템이다.</li>
<li>개인정보를 각 사이트마다 일일이 기록해야 하던 불편함을 해소할 수 있다.</li>
<li>기업에서는 회원에 대한 통합관리가 가능해 마케팅을 극대화시킬 수 있다.</li>
</ul>
<br>

<h2 id="sw-관련-신기술">SW 관련 신기술</h2>
<p><strong>블록체인(Blockchain)</strong>
P2P(Peer-to-Peer) 네트워크를 이용하여 온라인 금융 거래 정보를 온라인 네트워크 참여자(Peer)의 디지털 장비에 분산 저장하는 기술이다.</p>
<p><strong>메시업(Mashup)</strong>
웹에서 제공하는 정보 및 서비스를 이용하여 새로운 소프트웨어나 서비스, 데이터베이스 등을 만드는 기술로, 다수의 정보원이 제공하는 콘텐츠를 조합하여 하나의 서비스로 제공하는 웹 사이트 또는 애플리케이션을 말한다.</p>
<p><strong>서비스 지향 아키텍처(SOA; Service Oriented Architecture)</strong></p>
<ul>
<li>기업의 소프트웨어 인프라인 정보시스템을 공유와 재사용이 가능한 서비스 단위나 컴포넌트 중심으로 구축하는 정보기술 아키텍처이다.</li>
<li>SOA 기반 애플리케이션 구성 계층: 표현, 업무 프로세스, 서비스 중간, 애플리케이션, 데이터 저장 계층</li>
</ul>
<p><strong>디지털 트윈(Digital Twin)</strong></p>
<ul>
<li>현실속의 사물을 소프트웨어로 가상화한 모델이다.</li>
<li>실제 물리적인 자산을 소프트웨어로 가상화함으로써 실제 자산의 특성에 대한 정확한 정보를 얻을 수 있다.</li>
</ul>
<p><strong>그레이웨어(Grayware)</strong>
소프트웨어를 제공하는 입장에서는 악의적이지 않은 유용한 소프트웨어라고 주장할 수 있지만 사용자 입장에서는 유용할 수도 있고 악의적일 수도 있는 애드웨어, 트랙웨어, 기타 악성 코드나 악성 공유웨어를 말한다.</p>
<p><strong>양자 암호키 분배(QKD; Quantum Key Distribution)</strong></p>
<ul>
<li>양자 통신을 위해 비밀키를 분배하여 관리하는 기술이다.</li>
<li>두 시스템이 암호 알고리즘 동작을 위한 비밀키를 안전하게 공유하기 위해 양자 암호키 분배 시스템을 설치하여 운용하는 방식으로 활용된다.</li>
</ul>
<p><strong>서비스형 소프트웨어(SaaS; Software as a Service)</strong>
소프트웨어의 여러 기능 중에서 사용자가 필요로 하는 서비스만 이용할 수 있도록 한 소프트웨어이다.</p>
<p><strong>시멘틱 웹(Semantic Web)</strong>
컴퓨터가 사람을 대신하여 정보를 읽고 이해하고 가공하여 새로운 정보를 만들어 낼 수 있도록 이해하기 쉬운 의미를 가진 차세데 지능형 웹을 의미한다.</p>
<p><strong>리치 인터넷 애플리케이션(RIA; Rich Internet Application)</strong>
플래시 애니메이션 기술과 웹 서버 애플리케이션 기술을 통합하여 기존 HTML 보다 역동적이고 인터랙티브한 웹 페이지를 제공하는 신개념의 플래시 웹 페이지 제작 기술이다.</p>
<br>

<h2 id="hw-관련-신기술">HW 관련 신기술</h2>
<p><strong>앤 스크린(N-Screen)</strong>
N개의 서로 다른 단말기에서 동일한 콘텐츠를 자유롭게 이용할 수 있는 서비스이다.</p>
<p><strong>신 클라이언트 PC</strong></p>
<ul>
<li>하드디스크나 주변장치 없이 기본적인 메모리만 갖추고 서버와 네트워크로 운용되는 개인용 컴퓨터이다.</li>
<li>서버 기반 컴퓨팅과 관계가 깊다.</li>
</ul>
<p><strong>엠디스크(M-DISC; Millennial DISC)</strong></p>
<ul>
<li>한 번의 기록만으로 자료를 영구 보관할 수 있는 광저장장치이다.</li>
<li>디스크 표면의 무기물층에 레이저를 이용해 자료를 조각해서 기록한다.</li>
</ul>
<p><strong>멤스(MEMS; Micro-Electro Mechanical Systems)</strong>
초정밀 반도체 제조 기술을 바탕으로 센서, 액추에이터 등 기계 구조를 다양한 기술로 미세 가공하여 전기기계적 동작을 할 수 있도록 한 초미세 장치이다.</p>
<p><strong>멤리스터(Memristor)</strong>
메모리와 레지스터의 합성어로 전류의 방향과 양 등 기존의 경험을 모두 기억하는 특별한 소자이다.</p>
<p><strong>트러스트존 기술(TrustZone Technology)</strong>
하나의 프로세서 내에 일반 애플리케이션을 처리하는 일반 구역과 보안이 필요한 애필리케이션을 처리하는 보안 구역으로 분할하여 관리하는 하드웨어 기반의 보안 기술이다.</p>
<br>

<h2 id="db-관련-신기술">DB 관련 신기술</h2>
<p><strong>하둡(Hadoop)</strong></p>
<ul>
<li>오픈 소스를 기반으로 한 분산 컴퓨팅 플랫폼이다.</li>
<li>더그 커팅과 마이크 캐퍼렐라가 개발했으며, 구글의 맵리듀스 엔진을 사용하고 있다.</li>
<li>일반 PC급 컴퓨터들로 가상화된 대형 스토리지를 형성하고 그 안에 보관된 거대한 데이터 세트를 병렬로 처리할 수 있도록 개발된 자바 소프트웨어 프레임워크이다.</li>
</ul>
<p><strong>맵리듀스(MapReduce)</strong></p>
<ul>
<li>대용량 데이터를 분산 처리하기 위한 목적으로 개발된 프로그래밍 모델이다.</li>
<li>흩어져 있는 데이터를 연관성 있는 데이터 분류로 묶는 Map 작업을 수행한 후 중복 데이터를 제거하고 원하는 데이터를 추출하는 Reduce 직업을 수행한다.</li>
</ul>
<p><strong>데이터 마이닝(Data Mining)</strong>
대량의 데이터를 분석하여 데이터에 내재된 변수 사이의 상호관계를 규명하여 일정한 패턴을 찾아내는 기법이다.</p>
<p><strong>타조(Tajo)</strong>
오픈 소스 기반 분산 컴퓨팅 플랫폼인 아파치 하둡 기반의 분산 데이터 웨어하우스 프로젝트이다.</p>
<p><strong>OLAP(Online Analytical Processing)</strong></p>
<ul>
<li>다차원으로 이루어진 데이터로부터 통계적인 요약 정보를 분석하여 의사결정에 활용하는 방식이다.</li>
<li>OLAP 연산: Roll-up, Drill-down, Drill though, Drillacross, Pivoting, Slicing, Dicing</li>
</ul>
<p><strong>브로드 데이터(Broad Data)</strong>
다양한 채널에서 소비자와 상호 작용을 통해 생성된 것으로, 기업 마케팅에 있어 효율적이고 다양한 데이터이며, 이전에 사용하지 않거나 알지 못했던 새로운 데이터나 기존 데이터에 새로운 가치가 더해진 데이터이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[정보처리기사] 응용 SW기초 기술 활용]]></title>
            <link>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%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/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%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>Wed, 16 Apr 2025 04:54:32 GMT</pubDate>
            <description><![CDATA[<h2 id="운영체제">운영체제</h2>
<ul>
<li>운영체제(OS; Operating System)는 <strong>컴퓨터 시스템의 자원들을 효율적으로 관리</strong>하며, 사용자가 컴퓨터를 <strong>편리하고 효과적으로 사용할 수 있도록 환경을 제공하는 여러 프로그램 모임</strong>이다.</li>
<li>컴퓨터 사용자와 컴퓨터 하드웨어 간의 인터페이스로 동작하는 시스템 소프트웨어의 일종이다.</li>
<li>프로세서, 기억장치, 입/출력장치, 파일 및 정보 등의 자원을 관리한다.</li>
</ul>
<br>

<h2 id="unix">UNIX</h2>
<ul>
<li>UNIX는 1960년대 <strong>AT&amp;T 벨 연구소, MIT, General Electric이 공동 개발한 운영체제</strong>이다.</li>
<li>시분할 시스템을 위해 설계된 대화식 운영체제이다.</li>
<li>대부분 C 언어로 작성되어 있어 이식성이 높으며 장치, 프로세스 간의 호환성이 높다.</li>
<li>트리 구조의 파일 시스템을 갖는다.</li>
</ul>
<br>

<h2 id="unix-시스템의-구성">UNIX 시스템의 구성</h2>
<p><strong>커널</strong></p>
<ul>
<li>UNIX의 가장 핵심적인 부분으로 하드웨어를 보호하고, 프로그램과 하드웨어 간의 인터페이스 역할을 담당한다</li>
<li>프로세스 관리, 기억장치 관리, 파일 관리, 입/출력 관리, 프로세스간 통신, 데이터 전송 및 변환 등 여러가지 기능을 수행한다.</li>
</ul>
<p><strong>쉘</strong></p>
<ul>
<li>사용자의 명령어를 인식하여 프로그램을 호출하고 명령을 수행하는 명령어 해석기이다.</li>
<li>시스템과 사용자 간의 인터페이스를 담당한다.</li>
</ul>
<br>

<h2 id="android">Android</h2>
<ul>
<li>Android는 <strong>구글 사에서 개발한</strong> 리눅스 커널 기반의 <strong>개방형 모바일 운영체제</strong>이다.</li>
<li>모든 코드가 공개된 개방형 소프트웨어이다.</li>
<li>자바와 코틀린으로 애플리케이션을 작성한다.</li>
</ul>
<br>

<h2 id="기억장치---배치-전략">기억장치 - 배치 전략</h2>
<ul>
<li>배치 전력은 새로 반입되는 <strong>프로그램이나 데이터를 주기억장치의 어디에 위치시킬 것인지를 결정하는 전략</strong>이다.</li>
<li><strong>최초 적합(First Fit)</strong>: 프로그램이나 데이터가 들어갈 수 있는 크기의 빈 영역 중에서 첫 번쨰 분할 영역에 배치시키는 방법</li>
<li><strong>최적 적합(Best Fit)</strong>: 프로그램이나 데이터가 들어갈 수 있는 크기의 빈 영역 주에서 단편화를 가장 작게 남기는 분할 영역에 배치시키는 방법</li>
<li><strong>최악 적합(Worst Fit)</strong>: 프로그램이나 데이터가 들어갈 수 있는 크기의 빈 영역 중에서 단편화를 가장 많이 남기는 분할 영역에 배치시키는 방법</li>
</ul>
<br>

<h2 id="가상기억장치-구현-기법">가상기억장치 구현 기법</h2>
<p><strong>페이징(Paging) 기법</strong></p>
<ul>
<li>가상기억장치에 보관되어 있는 <strong>프로그램과 주기억장치의 영역을 동일한 크기로 나눈 후</strong> 나눠진 프로그램을 동일하게 나눠진 <strong>주기억장치의 영역에 적재시켜 실행하는 기법</strong>이다.</li>
<li>프로그램을 일정한 크기로 나눈 단위를 페이지라고 하고, 페이지 크기로 일정하게 나누어진 주기억장치의 단위를 페이지 프레임이라고 한다.</li>
</ul>
<p><strong>세그먼테이션(Segmentation)기법</strong></p>
<ul>
<li>가상기억장치에 보관되어 있는 <strong>프로그램을 다양한 크기의 논리적인 단위로 나눈 후 주기억장치에 적재시켜 실행시키는 기법</strong>이다.</li>
<li>프로그램을 배열이나 함수 등과 같은 논리적인 크기로 나눈 단위를 세그먼트라고 하며, 각 세그먼트는 고유한 이름과 크기를 갖는다.</li>
</ul>
<br>

<h2 id="페이지-교체-알고리즘">페이지 교체 알고리즘</h2>
<ul>
<li><strong>페이지 부재(Page Fault)가 발생하면</strong> 가상기억장치에서 필요한 페이즈를 찾아 주기억장치에 적재해야 하는데, 이때 주기억장치의 모든 페이지 프레임이 사용중이면 <strong>어떤 페이지 프레임을 선택하여 교체할 것인지를 결정하는 기법</strong>이 페이지 교체 알고리즘이다.</li>
<li>종류: OPT, FIFO, LRU, LFU, NUR, SCR 등</li>
</ul>
<br>

<h2 id="fifo">FIFO</h2>
<p>FIFO(First In First Out)는 각 페이지가 주기억장치에 적재될 때마다 그떄의 시간을 기억시켜 <strong>가장 먼저 들어와서 가장 오래 있었던 페이지를 교체하는 기법</strong>이다.</p>
<br>

<h2 id="lru">LRU</h2>
<p>LRU(Least Recently Used)는 <strong>최근에 가장 오랫동안 사용하지 않은 페이지를 교체하는 기법</strong>이다.</p>
<br>

<h2 id="lfu">LFU</h2>
<ul>
<li>LFU(Least Frequently Used)는 <strong>사용 빈도가 가장 적은 페이지를 교제하는 기법</strong>이다.</li>
<li>활발하게 사용되는 페이지는 사용 횟수가 많아 교체되지 않고 사용된다.</li>
</ul>
<br>

<h2 id="locality">Locality</h2>
<ul>
<li>Locality(국부성, 지역성, 구역성, 국소성)는 <strong>프로세스가 실행되는 동안 주기억장치를 참조할 때 일부 페이지만 집중적으로 참조하는 성질</strong>이 있다는 이론이다.</li>
<li>스래싱을 방지하기 위한 워킹 셋 이론의 기반이 되었다.</li>
<li><strong>시간 구역성(Temporal Locality)</strong>: 프로세스가 실행되면서 하나의 페이지를 일정 시간 동안 집중적으로 액세스하는 현상</li>
<li><strong>공간 구역성(Spatial Locality)</strong>: 프로세스 실행 시 일정 위치의 페이지를 집중적으로 액세스하는 현상</li>
</ul>
<br>

<h2 id="워킹-셋">워킹 셋</h2>
<ul>
<li>워킹 셋(Working Set)은 <strong>프로세스가 일정 시간 동안 자주 참조하는 페이지들의 집합</strong>이다.</li>
<li>자주 참조되는 워킹 셋을 주기억장치에 상주시킴으로써 페이지 부재 및 페이지 교체 현상이 줄어들어 프로세스의 기억장치 사용이 안정된다.</li>
</ul>
<br>

<h2 id="스래싱">스래싱</h2>
<ul>
<li>스래싱(Thrashing)은 <strong>프로세스의 처리 시간보다 페이지 교체에 소요되는 시간이 더 많아지는 현상</strong>이다.</li>
<li>다중 프로그래밍 시스템이나 가상기억장치를 사용하는 시스템에서 하나의 프로세스 수행 과정 중에 자주 페이지 부재가 발생함으로써 나타나며, 전테 시스템의 성능이 저하된다.</li>
</ul>
<br>

<h2 id="프로세스-상태-전이">프로세스 상태 전이</h2>
<p>프로세스 상태 전이는 프로세스가 시스템 내에 존재하는 동안 프로세스의 상태가 변하는 것을 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/kid_an/post/82d6a07d-d135-4866-ace8-835f24206e2a/image.png" alt=""></p>
<br>

<h2 id="프로세스-상태-전이-관련-용어">프로세스 상태 전이 관련 용어</h2>
<p><strong>Dispatch(디스패치)</strong>
준비 상태에서 대기하고 있는 프로세스 중 하나가 프로세서를 할당받아 실행 상태로 전이되는 과정이다.</p>
<br>

<p><strong>Wake Up</strong>
입/출력 작업이 완료되어 프로세스가 대기 상태에서 준비 상태로 전이 되는 과정이다.</p>
<br>

<p><strong>Spooling(스풀링)</strong>
입/출력장치의 공유 및 상대적으로 느린 입/출력장치의 처리 속도를 보완하고 다중 프로그래밍 시스템의 성능을 향상시키기 위해 입/출력할 데이터를 직접 입/출력장치에 보내지 않고 나중에 한꺼번에 입/출력하기 위해 디스크에 저장하는 과정이다.</p>
<br>

<h2 id="스레드">스레드</h2>
<ul>
<li>스레드(Thread)는 <strong>시스템의 여러 자원을 할당받아 실행하는 프로그램의 단위</strong> 또는 프로세스 내에서의 작업 단위로 사용된다.</li>
<li>프로세스의 일부 특성을 갖고 있기 때문에 경량(Light Weight) 프로세스라고도 한다.</li>
</ul>
<br>

<h2 id="sjf">SJF</h2>
<ul>
<li><strong>SJF(Shortest Job First, 단기 작업 우선)</strong>는 <strong>준비상태 큐에서</strong> 기다리고 있는 프로세스들 중에서 <strong>실행 시간이 가장 짧은 프로세스에게 먼저 CPU를 할당하는 기법</strong>이다.</li>
<li>가장 적은 평균 대기 시간을 제공하는 최적 알고리즘이다.</li>
</ul>
<br>

<h2 id="hrn">HRN</h2>
<ul>
<li><strong>HRN(Highest Response-ratio Next)은 대기 시간과 서비스(실행) 시간을 이용하는 기법</strong>이다.</li>
<li>우선순위를 계산하여 그 숫자가 가장 높은 것부터 낮은 순으로 우선순위가 부여된다.</li>
<li><strong>우선순위 계산식</strong></li>
<li>우선순위 계산식 = (대기 시간 + 서비스 시간)/서비스 시간*</li>
</ul>
<br>

<h2 id="rr">RR</h2>
<ul>
<li><strong>RR(Round Robin)</strong>은 각 프로세스를 <strong>시간 할당량(Time Slice, Quantum) 동안만 실행한 후</strong> 실행이 완료되지 않으면 <strong>다음 프로세스에게 CPU를 넘겨주는 기법</strong>이다.</li>
<li>시분할 시스템을 위해 고안된 방식으로, 할당되는 시간의 크기가 작으면 작은 프로세스들에게 유리하다.</li>
<li>할당되는 시간이 클 경우 FCFS 기법과 같아지고, 할당되는 시간이 작을 경우 문맥 교환 및 오버헤드가 자주 발생되어 요청된 작업을 신속히 처리할 수 없다.</li>
</ul>
<br>

<h2 id="srt">SRT</h2>
<ul>
<li><strong>SRT(Shortest Remaining Time)는 현재 실행주인 프로세스의 남은 시간과</strong> 준비상태 큐에 <strong>새로 도착한 프로세스의 실행 시간을 비교하여 가장 짧은 실행 시간을 요구하는 프로세스에게</strong> CPU를 <strong>할당하는 기법</strong>이다.</li>
<li>시분할 시스템에 유용하며, 준비상태 큐에 있는 각 프로세스의 실행 시간을 추적하여 보유하고 있어야하므로 오버헤드가 증가한다.</li>
</ul>
<br>

<h2 id="환경변수">환경변수</h2>
<ul>
<li>환경변수란 <strong>시스템 소프트웨어의 동작에 영향을 미치는 동적인 값들의 모임</strong>을 의미한다.</li>
<li>환경 변수는 변수명과 값으로 구성된다.</li>
<li>Windows에서 set을 입력하면 모든 환경 변수와 값을 출력한다.</li>
<li>UNIX나 LINUX에서는 setm envm printenv, setenv 중 하나를 입력하면 모든 환경 변수와 값을 표시한다.</li>
</ul>
<br>

<h2 id="unixlinux-기본-명령어">UNIX/LINUX 기본 명령어</h2>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">cat</td>
<td align="left">파일 내용을 화면에 표시함</td>
</tr>
<tr>
<td align="center">cd</td>
<td align="left">디렉터리의 위치를 변경함</td>
</tr>
<tr>
<td align="center">chown</td>
<td align="left">파일 소유자와 그룹을 변경함</td>
</tr>
<tr>
<td align="center">cp</td>
<td align="left">파일을 복사함</td>
</tr>
<tr>
<td align="center">rm</td>
<td align="left">파일을 삭제함</td>
</tr>
<tr>
<td align="center">find</td>
<td align="left">파일을 찾음</td>
</tr>
<tr>
<td align="center">kill</td>
<td align="left">PID(프로세스 고유 번호)를 이용하여 프로세스를 종료함</td>
</tr>
<tr>
<td align="center">fork</td>
<td align="left">새로운 프로세스를 생성함</td>
</tr>
<tr>
<td align="center">ls</td>
<td align="left">현재 디렉터리의 파일 목록을 표시함</td>
</tr>
<tr>
<td align="center">uname</td>
<td align="left">시스템의 이름과 버전, 네트워크 호스트명 등의 시스템 정보를 표시함</td>
</tr>
<tr>
<td align="center">mv</td>
<td align="left">파일을 이동함</td>
</tr>
<tr>
<td align="center">ps</td>
<td align="left">현재 실행중인 프로세스를 표시함</td>
</tr>
<tr>
<td align="center">pwd</td>
<td align="left">현재 작업중인 디렉터리 경로를 화면에 표시함</td>
</tr>
<tr>
<td align="center">who</td>
<td align="left">현재 시스템에 접속해 있는 사용자를 표시함</td>
</tr>
</tbody></table>
<br>

<h2 id="chmod">chmod</h2>
<ul>
<li>chmod는 <strong>파일의 보호 모드를 설정하여 파일의 사용 허가를 지정하는 UNIX 명렁어</strong>이다.</li>
<li>8진법 숫자를 이용한 방법으로도 파일의 보호 모드를 설정할 수 있다.</li>
</ul>
<br>

<h2 id="ip-주소">IP 주소</h2>
<p>IP 주소(Internet Protocol Address)는 <strong>인터넷에 연결된 모든 컴퓨터 자원을 구분하기 위한 고유한 주소</strong>이다.</p>
<p><strong>IPv4(Internet Protocol version 4)</strong></p>
<ul>
<li><strong>8비트씩 4부분, 총 32비트</strong>로 구성되어 있다.</li>
<li>네트워크 부분의 길이에 따라 A 클래스에서 E 클래스까지 총 5단계로 구성되어 있다.</li>
</ul>
<p><strong>IPv6(Internet Protocol version 6)</strong></p>
<ul>
<li>IPv6은 현재 사용하고 있는 IP 주소 체계인 IPv4의 주소 부족 문제를 해결하기 위해 개발되었다.</li>
<li>16비트씩 8부분, 총 128비트로 구성되어 있다.</li>
<li>각 부분을 16진수로 표현하고, 콜론(:)으로 구분한다.</li>
<li>인증성, 기밀성, 데이터 무결성의 지원으로 보안 문제를 해결할 수 있다.</li>
</ul>
<br>

<h2 id="ipv6의-주소-체계">IPv6의 주소 체계</h2>
<ul>
<li>유니캐스트(Unicast): 단일 송신자와 단일 수신자 간의 통신(1 대 1)</li>
<li>멀티캐스트(Multicast): 단일 송신자와 다중 수신자 간의 통신(1 대 다)</li>
<li>애니캐스트(Anycast): 단일 송신자와 가장 가까이 있는 단일 수신자 간의 통신(1 대 1)</li>
</ul>
<br>

<h2 id="서브네팅subnetting의-예">서브네팅(Subnetting)의 예</h2>
<p>192.168.1.0/24 네트워크를 FLSM 방식을 이용하여 3개의 Subnet으로 나누시오. (단 IP Subnet-Zero를 적용했다.)</p>
<p>192.168.1.0/24 네트워크의 서브넷 마스크는 1의 개수가 24개 즉 C 클래스에 속하는 네트워크이다.</p>
<table>
<thead>
<tr>
<th align="center">11111111</th>
<th align="center">11111111</th>
<th align="center">11111111</th>
<th align="center">00000000</th>
</tr>
</thead>
<tbody><tr>
<td align="center">255</td>
<td align="center">255</td>
<td align="center">255</td>
<td align="center">0</td>
</tr>
</tbody></table>
<p>서브넷 마스크를 Subnet으로 나눌 때는 서브넷 마스크가 0인 부분, 즉 마지막 8비트를 이용하면 된다.</p>
<p>Subnet으로 나눌 때 &quot;3개의 Subnet으로 나눈다&quot;는 것처럼 네트워크가 기준일 떄는 왼쪽을 기준으로 나눌 네트워크 수에 필요한 비트를 할당하고 나머지 비트로 호스트를 구성하면 된다.</p>
<p>3개의 Subnet으로 구성하라 했으니 8비트 중 3을 표현하는데 필요한 2비트를 제외하고 나머지 6비트를 호스트로 구성하면 된다.</p>
<table>
<thead>
<tr>
<th align="center">11111111</th>
<th align="center">11111111</th>
<th align="center">11111111</th>
<th align="center">00/000000</th>
</tr>
</thead>
<tbody><tr>
<td align="center">255</td>
<td align="center">255</td>
<td align="center">255</td>
<td align="center">0</td>
</tr>
</tbody></table>
<p>호스트 ID가 6Bit로 설정되었고, 문제에서 FLSM(Fixed Length Subnet Mask), 즉 고정된 크기로 주소를 할당하라고 했으므로 3개의 네트워크에 64개(2의 6승 = 64)씩 고정된 크기로 할당하면 다음과 같다.</p>
<table>
<thead>
<tr>
<th align="center">네트워크(ID)</th>
<th align="center">호스트 수</th>
<th align="center">IP 주소 범위</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1(00)</td>
<td align="center">64</td>
<td align="center">192.168.1.0(00000000) ~ 63(00111111)</td>
</tr>
<tr>
<td align="center">2(01)</td>
<td align="center">64</td>
<td align="center">192.168.1.64(01000000) ~ 127(01111111)</td>
</tr>
<tr>
<td align="center">3(10)</td>
<td align="center">64</td>
<td align="center">192.168.1.128(10000000) ~ 191(10111111)</td>
</tr>
</tbody></table>
<br>

<h2 id="osi-참조-모델">OSI 참조 모델</h2>
<p>OSI 참조 모델은 다른 시스템 간의 원활한 통신을 위해 <strong>ISO(국제표준화기구)에서 제안한 통신 규약(Protocol)</strong>이다.</p>
<p><strong>물리 계층(Physical Layer)</strong>
전공에 필요한 두 장치 간의 실제 접속과 절단 등 기계적, 전기정, 기능적, 절차적 특성에 대한 규칙을 정의한다.</p>
<p><strong>데이터 링크 계층(Data Link Layer)</strong>
두 개의 인접한 개방 시스템들 간에 신뢰성 있고 효율적인 정보 전송을 할 수 있도록 시스템 간 연결 설정과 유지 및 종료를 담당한다.</p>
<p><strong>네트워크 계층(Network Layer, 망계층)</strong>
개방 시스템들 간의 네트워크 연결을 관리하는 기능과 데이터의 교환 및 중계 기능을 한다.</p>
<p><strong>전송 계층(Transport Layer)</strong>
논리적 안정과 균일한 데이터 전송 서비스를 제공함으로써 종단 시스템(End-to-End) 간에 투명한 데이터 전송을 가능하게 한다.</p>
<p><strong>세션 계층(Session Layer)</strong>
송/수신 측 간의 관련성을 유지하고 대화 제어를 담당한다.</p>
<p><strong>표현 계층(Presentation Layer)</strong>
서로 다른 데이터 표현 형태를 갖는 시스템 간의 상호 접속을 위해 필요한 계층으로, 코드 변환, 데이터 암호화, 데이터 압축, 구문 검색 등의 기능을 수행한다.</p>
<p><strong>응용 계층(Application Layer)</strong>
사용자(응용 프로그램)가 OSI 환경에 접근할 수 있도록 서비스를 제공한다.</p>
<br>

<h2 id="네트워크-관련-장비">네트워크 관련 장비</h2>
<p><strong>라우터(Router)</strong></p>
<ul>
<li>브리지와 같이 LAN과 LAV의 연결 기능에 데이터 전송의 최적 경로를 선택하는 기능이 추가된 장치이다.</li>
<li>서로 다른 LAN 또는 LAN과 WAN을 연결하는 기능도 한다.</li>
</ul>
<p><strong>리피티(Repeater)</strong>
거리가 증가할수록 감쇠하는 디지털 신호의 장거리 전송을 위해 수신한 신호를 재생시키거나 출력 전압을 높여 전송하는 장치이다.</p>
<p><strong>허브(Hub)</strong></p>
<ul>
<li>한 사무실이나 가까운 거리의 컴퓨터들을 연결하는 장치로, 각각의 회선을 통합하여 관리한다.</li>
<li>신호 증폭 기능을 하는 리피터의 역할을 포함한다.</li>
</ul>
<p><strong>브리지(Bridge)</strong></p>
<ul>
<li>LAN과 LAN을 연결하거나 LAN 안에서의 컴퓨터 그룹을 연결하는 장치이다.</li>
<li>브리지를 이용한 서브넷(Subnet) 구성 시 전송 가능한 회선 수는 브리지가 n개일 때, n(n-1)/2개이ek.</li>
</ul>
<p><strong>게이트웨이(Gateway)</strong></p>
<ul>
<li>OSI 전 계층의 프로토콜 구조가 다른 네트워크를 연결하는 장치이다.</li>
<li>LAN에서 다른 네트워크에 데이터를 보내거나 다른 네트워크로부터 데이터를 받아들이는 출입구 역할을 한다.</li>
</ul>
<br>

<h2 id="프로토콜">프로토콜</h2>
<ul>
<li>프로토콜은 서로 다른 기기들 간의 <strong>데이터 교환을 원활하게 수행할 수 있도록 표준화시켜 놓은 통신 규약</strong>이다.</li>
<li>1965년 톰 마릴이 컴퓨터가 메시지를 전달하고, 메시지가 제대로 도착했는지 확인하며, 도착하지 않았을 경우 메시지를 재전송하는 일련의 방법을 &#39;기술적 은어&#39;란 뜻의 프로토콜로 정의한 바 있다.</li>
</ul>
<br>

<h2 id="프로토콜의-기본-요소">프로토콜의 기본 요소</h2>
<ul>
<li><strong>구문(Syntax)</strong>: 전송하고자 하는 데이터의 형식, 부호화, 신호 레벨 등을 규정함</li>
<li><strong>의미(Semantics)</strong>: 두 기기 간의 효율적이고 정확한 정보 전송을 위한 협조 사항과 오류 관리를 위한 제어 정보를 규정함</li>
<li><strong>시간(Timing)</strong>: 두 기기 간의 통신 속도, 메시지의 순서 제어 등을 규정함</li>
</ul>
<br>

<h2 id="패킷-교환-방식">패킷 교환 방식</h2>
<p>패킷 교환 방식은 <strong>메시지를 일정한 길이의 패킷으로 잘라서 전송하는 방식</strong>으로, 가상 회선 방식과 데이터그램 방식이 있다.</p>
<p><strong>가상 회선 방식</strong></p>
<ul>
<li>단말기 상호 간에 논리적인 가상 통신 회선을 미리 설정하여 송신지와 수신지 사이의 연결을 확립한 후에 설정된 경로를 따라 패킷들을 순서적으로 운반하는 방식이다.</li>
<li>정보 전송 전에 제어 패킷에 의해 경로가 설정된다.</li>
<li>모든 패킷은 같은 경로로 발생 순서대로 전송된다.
즉, 패킷의 송/수신 순서가 같다.</li>
</ul>
<p><strong>데이터그램 방식</strong></p>
<ul>
<li>연결 경로를 설정하지 않고 인접한 노드들의 트래픽(전송량) 상황을 감안하여 각각의 패킷들을 순서에 상관없이 독립적으로 운반하는 방식이다.</li>
<li>패킷마다 전송 경로가 다르므로, 패킷은 목적지의 완전한 주소를 가져야 한다.</li>
<li>순서에 상관없이 여러 경로를 통해 도착한 패킷들은 수신 측에서 순서를 재정리한다.</li>
</ul>
<br>

<h2 id="tcpip">TCP/IP</h2>
<p>TCP/IP(Transmission Control Protocol/Internet Protocol)는 인터넷에 연결된 <strong>서로 다른 기종의 컴퓨터들이 데이터를 주고받을 수 있도록 하는 표준 프로토콜</strong>이다.</p>
<p><strong>TCP(Transmission Control Protocol)</strong></p>
<ul>
<li>OSI 7계층의 전송 계층에 해당한다.</li>
<li>가상 회선 방식을 기반으로 하는 양방향 연결 서비스를 제공한다.</li>
<li>패킷의 다중화, 순서 제어, 오류 제어, 흐름 제어 기능을 제공한다.</li>
</ul>
<p><strong>IP(Internet Protocol)</strong></p>
<ul>
<li>OSI 7계층의 네트워크 계층에 해당한다.</li>
<li>데이터그램 방식을 기반으로 하는 비연결형 서비스를 제공한다.</li>
<li>패킷의 분해/조립, 주소 지정, 경로 선택 기능을 제공한다.</li>
</ul>
<br>

<h2 id="udp">UDP</h2>
<ul>
<li>UDP(User Datagram Protocol)는 <strong>데이터 전송 전에 연결을 설정하지 않는 비연결형 서비스를 제공하는 프로토콜</strong>이다.</li>
<li>TCP에 비해 상대적으로 단순한 헤더 구조를 가지므로, 오버헤드가 적고, 흐름 제어나 순서 제어가 없어 전송 속도가 빠르다.</li>
<li>실시간 전송에 유리하며, 신뢰성보다는 속도가 중요시되는 네트워크에서 사용된다.</li>
</ul>
<br>

<h2 id="l2tp">L2TP</h2>
<ul>
<li>L2TP(Layer 2 Tunneling Protocol)는 <strong>PPTP와 L2F의 기술적 장점들을 결합하여 만들어진 터널링 프로토콜</strong>이다.</li>
<li>데이터 링크 계층에서 구현되는 터널링 프로토콜이다.</li>
<li>자체적으로 암호화 및 인증 기능을 제공하지 않아 다른 보안 프로토콜과 함께 사용되는 경우가 많다.</li>
<li><strong>PPTP(Point to Point Tunneling Protocol)</strong>: PPP패킷을 IP 패킷에 캡슐화하여 통과시키기 위한 터널링 프로토콜</li>
<li><strong>L2F(Layer 2 Forwarding)</strong>: 인터넷을 통한 VPN(가상 사설망) 연결을 위해 개발된 터널링 프로토콜</li>
</ul>
<br>

<h2 id="icmp">ICMP</h2>
<ul>
<li>ICMP(Internet Control Message Protocol, 인터넷 제어 메시지 프로토콜)는 <strong>IP와 조합하여 통신중에 발생하는</strong> 오류의 처리와 전송 경로 변경 등을 위한 <strong>제어 메시지를 관리하는 역할</strong>을 한다.</li>
<li>헤더는 8Byte로 구성된다.</li>
</ul>
<br>

<h2 id="arp--rarp">ARP / RARP</h2>
<p><strong>ARP(Address Resolution Protocol, 주소 분석 프로토콜)</strong>
호스트의 IP 주소를 호스트와 연결된 네트워크 접속 장치의 물리적 주소(MAC Address)로 변환하는 기능을 수행하는 프로토콜이다.</p>
<p><strong>RARP(Reverse Address Resolution Protocol)</strong>
ARP와 반대로 물리적 주소를 IP 주소로 변환하는 기능을 수행하는 프로토콜로, 역순 주소 결정 프로토콜이라 불린다.</p>
<br>

<h2 id="네트워크-구축">네트워크 구축</h2>
<p>네트워크는 <strong>두 대 이상의 컴퓨터를</strong> 전화선이나 케이블 등으로 <strong>연결하여 자원을 공유하는 것</strong>을 말한다.</p>
<p><strong>성형(Star, 중앙 집중형)</strong>
중앙에 중앙 컴퓨터가 있고, 이를 중심으로 단말장치들이 연결되는 중앙 짖ㅂ중식의 네트워크 구성 형태이다.</p>
<p><strong>링형(Ring, 루프형)</strong>
컴퓨터와 단말장치들을 서로 이웃하는 것끼리 연결시킨 포인트 투 포인트9Point-to-Point) 방식의 구성 형태이다.</p>
<p><strong>버스형(Bus)</strong>
한 개의 통신 회선에 여러 대의 단말장치가 연결되어 있는 형태이다.</p>
<p><strong>계층형(Tree, 분산형)</strong>
중앙 컴퓨터와 일정 지역의 단말장치까지는 하나의 통신 회선으로 연결시키고, 이웃하는 단말장치는 일정 지역 내에 설치된 중간 단말장치로부터 다시 연결시키는 형태이다.</p>
<p><strong>망형(Mesh)</strong></p>
<ul>
<li>모든 지점의 컴퓨터와 단말장치를 서로 연결한 형태로, 노드의 연결성이 높다.</li>
<li>모든 노드를 망형으로 연결하려면 노드의 수가 n개일 때, n(n-1)/2개의 회선이 필요하고 노드당 n-1개의 포트가 필요하다.</li>
</ul>
<br>

<h2 id="ieee-802의-주요-표준-규격">IEEE 802의 주요 표준 규격</h2>
<p>IEEE 802는 KAN의 표준안이다.</p>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">802.1</td>
<td align="left">전체의 구성, OSI 참조 모델과의 관계, 통신망 관리 등에 관한 규약</td>
</tr>
<tr>
<td align="center">802.2</td>
<td align="left">논리 링크 제어(LLC) 계층에 관한 규약</td>
</tr>
<tr>
<td align="center">802.3</td>
<td align="left">CSMA/CD 방식의 매체 접근 제어 계층에 관한 규약</td>
</tr>
<tr>
<td align="center">802.4</td>
<td align="left">토큰 버스 방식의 매체 접근 제어 계층에 관한 규약</td>
</tr>
<tr>
<td align="center">802.5</td>
<td align="left">토큰 링 방식의 매체 접근 제어 계층에 관한 규약</td>
</tr>
<tr>
<td align="center">802.6</td>
<td align="left">도시형 통신망(MAN)에 관한 규약</td>
</tr>
<tr>
<td align="center">802.9</td>
<td align="left">종합 음성/데이터 네트워크에 관한 규약</td>
</tr>
<tr>
<td align="center">802.11</td>
<td align="left">무선 LAN에 관한 규약</td>
</tr>
</tbody></table>
<br>

<h2 id="ieee-802의-주요-표준-규격-1">IEEE 802의 주요 표준 규격</h2>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">802.11</td>
<td align="left">2.4GHz 대역 전파와 CSMA/CA 기술을 사용해 최고 2Mbps까지의 전송 속도를 지원함</td>
</tr>
<tr>
<td align="center">802.11a</td>
<td align="left">5GHz 대역의 전파를 사용하며, OFDM 기술을 사용해 최고 54Mbps까지의 전송 속도를 지원함</td>
</tr>
<tr>
<td align="center">802.11b</td>
<td align="left">802.11 초기 버전의 개선안으로 등장하였으며, 초기 버전의 대역 전파와 기술을 사용해 최고 11Mbps의 전송 속도로 기존에 비해 5배 이상 빠르게 개선되었음</td>
</tr>
<tr>
<td align="center">802.11e</td>
<td align="left">802.11의 부가 기능 표준으로, Qos 기능이 지원되도록 하기 위해 매체 접근 제어(MAC) 계층에 해당하는 부분을 수정하였음</td>
</tr>
<tr>
<td align="center">802.11g</td>
<td align="left">2.4GHz 대역의 전파를 사용하지만 5GHz 대역의 전파를 사용하는 802.11a와 동일한 최고 54Mbps까지의 전송 속도를 지원함</td>
</tr>
<tr>
<td align="center">802.11n</td>
<td align="left">2.4GHz 대역과 5GHz 대역을 사용하는 규격으로, 최고 600Mbps까지의 전송 속도를 지원함</td>
</tr>
</tbody></table>
<br>

<h2 id="nat">NAT</h2>
<ul>
<li>NAT(Network Address Translation, 네트워크 주소 변환)은 <strong>한 개의 정식 IP 주소에 대량의 가상 사설 IP 주소를 할당 및 연결하는 기능</strong>이다.</li>
<li>한 개의 IP 주소를 사용해서 외부에 접속할 수 있는 노드는 어느 시점에서 한 개로 제한되는 문제가 있지만 IP 마스커레이드를 이용하여 해결할 수 있다.</li>
</ul>
<br>

<h2 id="igp">IGP</h2>
<p>IGP(Interior Gateway Protocol, 내부 게이트웨이 프로토콜)는 <strong>하나의 자율 시스템(AS) 내의 라우팅에 사용되는 프로토콜</strong>이다.</p>
<p><strong>RIP(Routing Information Protocol)</strong></p>
<ul>
<li>현재 가장 널리 사용되는 라우팅 프로토콜로 거리 벡터 라우팅 프로토콜이라고도 불린다.</li>
<li>최단 경로 탐색에 Bellman-Ford 알고리즘을 사용한다.</li>
<li>소규모 동종의 네트워크(자율 시스템, AS) 내에서 효율적인 방법이다.</li>
</ul>
<p><strong>OSFP(Open Shortest Path First protocol)</strong></p>
<ul>
<li>RIP의 단점을 해결하여 새로운 기능을 지원하는 인터넷 프로토콜로, 대규모 네트워크에서 많이 사용된다.</li>
<li>최단 경로 탐색에 다익스트라 알고리즘을 사용한다.</li>
</ul>
<br>

<h2 id="egp--bgp">EGP / BGP</h2>
<p><strong>EGP(Exterior Gateway Protocol)</strong>
자율 시스템(AS) 간의 라우팅, 즉 게이트웨이 간의 라우팅에 사용되는 프로토콜이다.</p>
<p><strong>BGP(Border Gateway Protocol)</strong></p>
<ul>
<li>자율 시스템(AS) 간의 라우팅 프로토콜로, EGP의 단점을 보완하기 위해 맘ㄴ들어진 프로토콜이다.</li>
<li>초기에 BGP 라우터들이 연결될 때에는 전체 경로 제어표(라우팅 테이블)를 교환하고, 이후에는 변화된 정보만을 교환한다.</li>
</ul>
<br>

<h2 id="흐름-제어">흐름 제어</h2>
<p>흐름 제어(Flow Control)란 네트워크 내의 원활한 흐름을 의해 <strong>송/수신 측 사이에 전송되는 패킷의 양이나 속도를 규제하는 기능</strong>이다.</p>
<p><strong>정지-대기</strong></p>
<ul>
<li>수신 측의 확인 신호(ACK)를 받은 후에 다음 패킷을 전송하는 방식이다.</li>
<li>한 번에 하나의 패킷만을 전송할 수 있다.</li>
</ul>
<p><strong>슬라이딩 윈도우(Sliding Window)</strong></p>
<ul>
<li>확인 신호, 즉 수신 통지를 이용하여 송신 데이터의 양을 조절하는 방식이다.</li>
<li>수신 측의 확인 신호를 받지 않더라도 미리 정해진 패킷의 수만큼 연속적으로 전송하는 방식으로, 한 번에 여러개의 패킷을 전송할 수 있어 전송 효율이 좋다.</li>
<li>송신 측은 수신 측으로부터 확인 신호(ACK) 없이도 보낼 수 있는 패킷의 최대치를 미리 약속받는데, 이 패킷의 최대치가 윈도우 크기(Window Size)를 의미한다.</li>
</ul>
<br>

<h2 id="raid">RAID</h2>
<p>RADI(Redudeant Array of Independent Disk)는 2개 이상의 하드디스크로 디스크 배열을 구성하고, 파일을 구성하는 데이터 블록들을 서로 다른 디스크에 분산 저장하거나 다중화하는 저장 기술로, 구현된 기술에 따라 다음과 같이 레벨로 구분한다.</p>
<p><strong>RAID 0</strong></p>
<ul>
<li>스트라이핑이라고 불린다.</li>
<li>디스크를 병렬로 연결하여 디스크의 개수만큼 용량과 속도가 배로 증가한다.</li>
<li>하나의 디스크만 손상되어도 전체 데이터가 파손 된다.</li>
</ul>
<p><strong>RAID 1</strong></p>
<ul>
<li>미러링이라고 불린다.</li>
<li>같은 데이터를 다른 디스크에 동일하게 복사하는 방식이다.</li>
</ul>
<p><strong>RAID 2 ~ 4</strong></p>
<ul>
<li>하나의 디스크에 오류 정정 부호를 비트, 바이트, 워드 단위로 저장하고, 나머지 디스크는 RAID 0과 같이 활용하여 안정성을 높인 모드이다.</li>
<li>하나의 디스크가 손상되어도 정상 가동이 가능하며 최소 3개의 디스크가 필요하다.</li>
</ul>
<p><strong>RAID 5</strong></p>
<ul>
<li>오류 정정 부호를 블록 단위로 여러 디스크에 분산 저장한 방식이다.</li>
<li>하나의 디스크가 손상되어도 정상 가동이 가능하며 최소 3개의 디스크가 필요하다.</li>
</ul>
<p><strong>RAID 6</strong></p>
<ul>
<li>RAID 5와 원리는 같으나 오류 정정 부호 2개를 저장하는 방식이다.</li>
<li>두 개의 디스크가 손상되어도 정상 가동이 가능하며 최소 4개의 디스크가 필요하다.</li>
</ul>
<br>

<h2 id="secure-os">Secure OS</h2>
<ul>
<li>Secure OS는 기존의 운영체제에 내제된 보안 취약점을 해소하기 위해 <strong>보안 기능을 갖춘 커널을 이식하여 외부의 침입으로부터 시스템 자원을 보호하는 운영체제</strong>를 의미한다.</li>
<li>보안 커널은 보안 기능을 갖춘 커널을 의미하며, TCB를 기반으로 참조 모니터의 개념을 구현하고 집행한다.</li>
<li><strong>Secure OS</strong>의 보안 기능: 식별 및 인증, 임의적/강제적 접근통제, 객체 재사용 보호, 완전한 조정, 신뢰 경로, 감사 및 감사기록 축소 등</li>
</ul>
<br>

<h2 id="회복">회복</h2>
<ul>
<li>회복(Recovery)은 트랜잭션들을 수행하는 도중 장애가 발생하여 <strong>데이터베이스가 손상되었을 때 손상되기 이전의 정상 상태로 복구하는 작업</strong>이다.</li>
<li>회복 기법의 종류: 연기 갱신 기법, 즉각 갱신 기법, 그림자 페이지 대체 기법, 검사점 기법</li>
</ul>
<br>

<h2 id="redo--undo">REDO / UNDO</h2>
<p><strong>REDO</strong>
데이터베이스가 비정상적으로 종료되었을 떄, 디스크에 저장된 로그를 분석하여 트랜잭션의 시작과 완료에 대한 기록이 있는 트랜잭션들의 작업을 재작업한다. 즉, 로그를 이용하여 해당 데이터 항목에 대해 이전 값을 이후 값으로 변경하는 연산이다.</p>
<p><strong>UNDO</strong>
데이터베이스가 비정상적으로 종료되었을 떄, 디스크에 저장된 로그를 분석하여 트랜잭션의 시작에 대한 기록은 있지만 완료 기록은 없는 트랜잭션들이 작업한 변경 내용들을 모두 취소한다. 즉 로그를 이용하여 해당 데이터 항목에 대해 이후 값을 이전 값으로 변경하는 연산이다.</p>
<br>

<h2 id="즉각-갱신-기법">즉각 갱신 기법</h2>
<ul>
<li>즉각 갱신 기법은 트랜잭션이 데이터를 갱신하면 <strong>트랜잭션이 부분 완료되기 전이라도 즉시 실제 데이터베이스에 반영하는 방법</strong>이다.</li>
<li>장애가 발생하여 회복 작업할 경우를 대비하여 갱신된 내용들을 Log에 보관시킨다.</li>
<li>Redo(재시도) Undo(취소) 모두 사용 가능하다.</li>
</ul>
<br>

<h2 id="로킹">로킹</h2>
<ul>
<li>로킹은 트랜잭션들이 어떤 로킹 단위를 <strong>액세스하기 전에 Lock을 요청해서 Lock이 허락되어야만 그 로킹 단위를 액세스할 수 있도록 하는 기법</strong>이다.</li>
<li>주요 데이터의 액세스를 상호 배타적으로 한다.</li>
</ul>
<br>

<h2 id="타임-스탬프-순서">타임 스탬프 순서</h2>
<ul>
<li>타임 스탬프 순서는 트랜잭션과 트랜잭션이 읽거나 갱신한 데이터에 대해 트랜잭션이 실행을 시작하기 전에 <strong>시간표를 부여하여 부여된 시간에 따라 트랜잭션 작업을 수행하는 기법</strong>이다.</li>
<li>직렬성 순서를 결정하기 위해 트랜잭션 간의 처리 순서를 미리 선택하는 기법들 중에서 가장 보편적인 방법이다.</li>
</ul>
<br>

<h2 id="로킹-단위">로킹 단위</h2>
<ul>
<li>로킹 단위는 병행제어에서 <strong>한꺼번에 로킹할 수 있는 객체의 크기</strong>를 의미한다.</li>
<li>데이터베이스, 파일, 레코드, 필드 등이 로킹 단위가 될 수 있다.</li>
<li>로킹 단위가 크면 로크 수가 작아 관리하기 쉽지만 병행성 수준이 낮아진다.</li>
<li>로킹 단위가 작으면 로크 수가 많아 관리하기 복잡해 오버헤드가 증가하지만 병행성 수준이 높아진다.</li>
</ul>
<br>

<h2 id="교착상태">교착상태</h2>
<ul>
<li>교착상태(DeadLock)는 상호 배제에 의해 나타나는 문제점으로, 둘 이상의 프로세스들이 자원을 점유한 상태에서 <strong>서로 다른 프로세스가 점유하고 있는 자원을 요구하며 무한정 기다리는 현상</strong>을 의미한다.</li>
<li>교착상태 발생의 필요 충분 조건</li>
</ul>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">상호배제(Mutual Exclusion)</td>
<td align="left">한 번에 한 개의 프로세스만이 공유 자원을 사용할 수 있어야 함</td>
</tr>
<tr>
<td align="center">점유와 대기(Hold and Wait)</td>
<td align="left">최소한 하나의 자원을 점유하고 있으면서 다른 프로세스에 할당되어 사용되고 있는 자원을 추가로 점유하기 위해 대기하는 프로세스가 있어야 함</td>
</tr>
<tr>
<td align="center">비선점(Non-preemption)</td>
<td align="left">다른 프로세스에 할당된 자원은 사용이 끝날 때까지 강제로 빼앗을 수 없어야 함</td>
</tr>
<tr>
<td align="center">환형 대기(Circular Wait)</td>
<td align="left">공유 자원과 공유 자원을 사용하기 위해 대기하는 프로세스들이 원형으로 구성되어 있어 자신에게 할당된 자원을 점유하면서 앞이나 뒤에 있는 프로세스의 자원을 요구해야 함</td>
</tr>
</tbody></table>
<br>

<h2 id="교착상태의-해결-방법">교착상태의 해결 방법</h2>
<p><strong>예방 기법(Prevention)</strong></p>
<ul>
<li>교착상태가 발생하지 않도록 사전에 시스템을 제어하는 방법</li>
<li>교착상테 발생의 네 가지 조건 중엣 어느 하나르 제거함으로써 수행됨</li>
</ul>
<p><strong>회피 기법(Avoidance)</strong></p>
<ul>
<li>교착상태가 발생할 가능성을 배제하지 않고 교착상태가 발생하면 적절히 피해 나가는 방법</li>
<li>주로 은행원 알고리즘이 사용됨</li>
</ul>
<p><strong>발견 기법(Detection)</strong>
시스템에 교착상태가 발생했는지 점검하여 교착상태에 있는 프로세스와 자원을 발견하는 것</p>
<p><strong>회복 기법(Recovery)</strong>
교착상태를 일으킨 프로세스를 종료하거나 교착상태의 프로세스에 할당된 자원을 선점하여 프로세스나 자원을 회복하는 것</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 기본 문법 - 1]]></title>
            <link>https://velog.io/@kid_an/%EC%9E%90%EB%B0%94%EC%9D%98-%EA%B8%B0%EB%B3%B8</link>
            <guid>https://velog.io/@kid_an/%EC%9E%90%EB%B0%94%EC%9D%98-%EA%B8%B0%EB%B3%B8</guid>
            <pubDate>Tue, 15 Apr 2025 01:45:10 GMT</pubDate>
            <description><![CDATA[<h2 id="변수와-출력에-대해">변수와 출력에 대해</h2>
<p>타입 변수명; -&gt; 변수가 생성됨. 변수를 선언한다.
자바는 변수에 들어갈 타입이 선언할 떄 결정된다.(정적타입핑)</p>
<p>타입 변수명 = 값;
변수는 선언 즉시 초기화하는 습관을 들이는 것이 좋다.</p>
<p>초기화되지 않은 변수는 쓰레기 값이 들어가 있다.</p>
<p>자바는 전역변수가 없다.
<strong>무조건 {} 안에 들어가야 한다.</strong></p>
<pre><code class="language-java">int a = 10; // 이렇게 밖에 나와 있으면 안 된다.
public class VariableTest {

}</code></pre>
<pre><code class="language-java">public class VariableTest {
    int a = 10; // 이렇게 내부에 들어와 있어야 한다.
}</code></pre>
<br>

<p>클래스가 독립적으로 실행되기 위해선 main 함수가 필요하다.
만약 함수가 여러개인 경우 무조건 main()을 호출한다.</p>
<pre><code class="language-java">public class VariableTest {
    // java에서의 메인함수.
    // 함수가 여러개인 경우 메인함수부터 호출한다.
    public static void main(String[] args) {
        ...
    }

    public static void function1 {
        ...
    }

    public static void function2 {
        ...
    }

    public static void function3 {
        ...
    }
}</code></pre>
<br>

<p>자바의 자료형 기본 4가지: 정수, 실수, 문자(단일), 논리</p>
<p><strong>정수 : byte(1byte), short(2byte), int(4byte), long(8byte)</strong>
<em>() 안의 숫자는 해당 자료형의 byte 크기이다.</em></p>
<pre><code class="language-java">public class VariableTest {
    byte age = 127; // 변수는 소문자로 시작해야 한다.
    short year = 2025;
    int hit = 21000000;
    long money = 2200000000L; // 마지막에 L을 붙이지 않으면 Int형으로 인식한다.    
}</code></pre>
<br>

<p><strong>실수 : float(소수점 7자리, 4byte), double(소수점 15자리, 8byte)</strong></p>
<pre><code class="language-java">public class VariableTest {
    float w = 70.5F; // float은 뒤에 F를 붙여야 한다.
    double h = 170.000000555;
}</code></pre>
<br>

<p><strong>문자(단일) : char</strong></p>
<pre><code class="language-java">public class VariableTest {
    char gender = &#39;여&#39; // 문자는 &#39;&#39; 홀따옴표로 감싼다.
}</code></pre>
<br>

<p><strong>논리형 : boolean</strong></p>
<pre><code class="language-java">public class VariableTest {
    boolean food = true;
    boolean eat = false;
}</code></pre>
<br>

<p><strong>문자열: String -&gt; 대문자로 시작하는 이유는 클래스이기 때문이다.</strong></p>
<pre><code class="language-java">public class VariableTest {
    String name = &quot;김국민&quot; // &quot;&quot;이중 따옴표로 감싸줘야 한다.

    // 여러줄을 입력할 때 사용한다.
    String plan = &quot;&quot;&quot;
            나는
            훌륭한
            자바 개발자가 되고 싶다.
            &quot;&quot;&quot;;
}</code></pre>
<br>

<p>System: 부품 -&gt; 컴퓨터
out: output 출력 장치, 기본은 모니터이다.
in: input 입력장치, 기본은 키보드이다.
print: 출력하라.</p>
<p><strong>System.out.print -&gt; 컴퓨터 모니터에 출력하라.</strong></p>
<pre><code class="language-java">public class VariableTest {
    byte age = 127; // 변수는 소문자로 시작해야 한다.

    // +연산자가 하나라도 문자열이면 결과는 String(결합연산자)가 된다.
    System.out.print(&quot;내 나이는 &quot; + age + &quot;세야.&quot;);  
}</code></pre>
<br>

<p>출력의 종류: print, println, printf</p>
<p>print -&gt; 출력후 개행이 실행되지 않는다.
println -&gt; 출력후 <strong>개행을 실행</strong>한다.
printf -&gt; 출력 <strong>포맷</strong>을 정한다.</p>
<pre><code class="language-java">public class VariableTest {
    byte age = 127; // 변수는 소문자로 시작해야 한다.

    // 이 때 변수의 값을 받아주는 서식문자를 변수의 타입에 맞게 지정해야 한다.
    System.out.printf(&quot;내 나이는 %d세야!&quot;, age);
}</code></pre>
<br>

<h2 id="타입-변환">타입 변환</h2>
<ol>
<li>기본형과 기본형이 아닌 것은 =(대입연산자로) 형변환이 불가능하다.</li>
<li>문자열 변수에 들어있는 것을 기본형 변수에 바로 넣을 수 없다.</li>
<li>기본형 변수에 들어있는 것을 문자열 변수에 바로 넣을 수 없다.</li>
</ol>
<p>이 때는 아래의 함수를 써야한다.</p>
<ul>
<li><p>문자를 숫자로 바꾸고 싶은 경우
<code>String.valueOf(변환할 변수);</code></p>
</li>
<li><p>숫자를 문자로 바꾸고 싶은 경우
<code>Integer.parsInt(변환 할 변수);</code></p>
</li>
</ul>
<pre><code class="language-java">public class VariableTest {
    // byte를 숫자로 바꾸고 싶은 경우
    byte age = 127;
    int age2 = age; // &lt;- 자동형변환

    byte age3 = (byte)age2; // 1byte &lt;- 강제형변환 4byte

    // 문자를 숫자로 바꾸고 싶은 경우
    String data = &quot;100&quot;;
    int num = data; // 기본형 &lt;- 기본형X
    // 부품을 수정해줘야한다.
    int num = Integer.parseInt(data);

    String data2 = &quot;11.11&quot;;
    double num2 = Double.parseDouble(data2);

    // 숫자를 문자열로 바꾸고 싶은 경우
    String data3 = String.valueOf(num2);
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[정보처리기사] 정보 보안 관련 용어]]></title>
            <link>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%A0%95%EB%B3%B4-%EB%B3%B4%EC%95%88-%EA%B4%80%EB%A0%A8-%EC%9A%A9%EC%96%B4</link>
            <guid>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%A0%95%EB%B3%B4-%EB%B3%B4%EC%95%88-%EA%B4%80%EB%A0%A8-%EC%9A%A9%EC%96%B4</guid>
            <pubDate>Sun, 13 Apr 2025 15:33:00 GMT</pubDate>
            <description><![CDATA[<h2 id="rootkit">Rootkit</h2>
<ul>
<li>시스템에 침입한 후 침입 사실을 숨긴 채 백도어, 트로이목마를 설치하고ㅡ 원격 접근, 내부 사용 흔적 삭제, 관리자 권한 획득 등 주로 불법적인 해킹에 사용되는 기능들을 제공하는 프로그램들의 모음이다.</li>
<li>컴퓨터의 운영체제에서 실행 파일과 실행 중인 프로세스를 숨김으로써 운영체제 검사 및 백신 프로그램의 탐지를 피할 수 있다.</li>
</ul>
<br>

<h2 id="aptadvanced-persistent-threats-지능형-지속-위협">APT(Advanced Persistent Threats, 지능형 지속 위협)</h2>
<p>다양한 IT 기술과 방식들을 이용해 조직적으로 특정 기업이나 조직 네트워크에 침투해 활동 거점을 마련한 뒤 때를 기다리면서 보안을 무력화시키고 정보를 수집한 다음 외부로 빼돌리는 형태의 공격이다.</p>
<br>

<h2 id="무작위-대입-공격brute-force-attack">무작위 대입 공격(Brute Force Attack)</h2>
<p>암호화된 문서의 암호키를 찾아내기 위해 적용 가능한 모든 값을 대입하여 공격하는 방식이다.</p>
<br>

<h2 id="큐싱qshing">큐싱(Qshing)</h2>
<p>QR코드를 통해 악성 앱의 다운로드를 유도하거나 악성 프로그램을 설치하도록 하는 금융사기 기법의 하나로, QR코드와 개인정보 및 금융정보를 낚는다는 의미의 합성 신조어이다.</p>
<br>

<h2 id="스미싱smishing">스미싱(Smishing)</h2>
<p>문자 메시지를 이용해 사용자의 개인 신용 정보를 뺴내는 수법이다.</p>
<br>

<h2 id="스피어-피싱spear-phishing">스피어 피싱(Spear Phishing)</h2>
<p>사회 공학의 한 기법으로, 특정 대상을 선정한 후 그 대상에게 일반적인 이메일로 위장한 메일을 지속적으로 발송하여, 발송 메일의 본문 링크나 첨부된 파일을 클릭하도록 유도해 사용자의 개인 정보를 탈취하는 공격이다.</p>
<br>

<h2 id="좀비pc">좀비PC</h2>
<p>악성코드에 감염되어 다른 프로그램이나 컴퓨터를 조종하도록 만들어진 컴퓨터로, C&amp;C(Command &amp; Control) 서버의 제어를 받아 주로 DDoS 공격 등에 이용된다.</p>
<br>

<h2 id="cc-서버">C&amp;C 서버</h2>
<p>해커가 원격지에서 감염된 좀비 PC에 명령을 내리고 악성코드를 제어하기 위한 용도로 사용하는 서버를 말한다.</p>
<br>

<h2 id="봇넷botnet">봇넷(Botnet)</h2>
<p>악성 프로그램에 감염되어 악의적인 의도로 사용될 수 있는 다수의 컴퓨터들이 네트워크로 연결된 형태를 말한다.</p>
<br>

<h2 id="제로-데이-공격">제로 데이 공격</h2>
<p>보안 취약점이 발견되었을 떄 발견된 취약점의 존재 자체가 널리 공표되기도 전에 해당 취약점을 통하여 이루어지는 보안 공격으로, 공격의 신속성을 의미한다.</p>
<br>

<h2 id="트로이-목마">트로이 목마</h2>
<p>정상적인 기능을 하는 프로그램으로 위장하여 프로그램 내에 숨어 있다가 해당 프로그램이 동작할 때 활성화되어 부작용을 일으키지만 자기 복제 능력은 없다.</p>
<br>

<h2 id="cccommon-criteria인증">CC(Common Criteria)인증</h2>
<p>국가마다 서로 다른 정보보호시스템 평가기준을 연동하고 평가결과를 상호 인증하기 위해 제정된 정보보안 평가기준으로, ISO/IEC 15408애 등록된 국제 표준이다.</p>
<br>

<h2 id="멀버타이징malvertising">멀버타이징(Malvertising)</h2>
<p>악성 소프트웨어를 뜻하는 멀웨어와 광고의 합성어로, 온라인 광고를 통해 악성코드를 유포시키는 행위를 말한다.</p>
<br>

<h2 id="정보공유분석센터isac-information-sharing--analysis-center">정보공유분석센터(ISAC; Information Sharing &amp; Analysis Center)</h2>
<p>취약점 및 침해요인과 그 대응방안에 관한 정보를 제공하며, 침해사고가 발생하는 경우 실시간 경보/분석체계를 운영하고, 금융/통신 등 분야별 정보통신기반시설을 보호하기 위한 업무를 수행하는 곳이다.</p>
<br>

<h2 id="업무연속성계획bcp-business-continuity-planning">업무연속성계획(BCP; Business Continuity Planning)</h2>
<p>각종 재해, 장애, 재난으로부터 위기관리를 기반으로 재해복구, 업무복구 및 재개, 비상계획 등의 비즈니스 연속성을 보장하기 위한 계획으로, RTP, RPO, 우선순위를 결정하기 위해 업무 영향 분석을 수행한다.</p>
<br>

<h2 id="데이터-디들링data-diddling">데이터 디들링(Data Diddling)</h2>
<p>처리할 자료를 다른 자료와 바꿔서 처리하는 것으로, 입력값이나 출력값을 부정한 의도로 수정하여 잘못된 결과가 나오도록 유도하는 방식이다.</p>
<br>

<h2 id="비트로커bitlocker">비트로커(BitLocker)</h2>
<p>Windows 7부터 지원되기 시작한 Windows 전용의 볼륨 암호화 기능으로, TPM(Trusted Platform Module)과 AES-128 알고리즘을 사용한다.</p>
<br>

<h2 id="공급망-공격supply-chain-attack">공급망 공격(Supply Chain Attack)</h2>
<p>소프트웨어 공급망에 침투하여 악성코드를 배포하는 공격으로, SW 빌드 및 배포 과정에 악성코드를 삽입하여 이용자들을 공격한다.</p>
<br>

<h2 id="바이러스virus">바이러스(Virus)</h2>
<p>컴퓨터의 정상적인 작동을 방해하기 위해 운영체제나 저장된 데이터에 손상을 입히는 프로그램으로, <strong>자신을 복제할 수 있고, 다른 프로그램을 감염시킬 수 있다.</strong></p>
<br>

<h2 id="웜worm">웜(Worm)</h2>
<p><strong>네트워크를 통해 연속적으로 자신을 복제</strong>하여 <strong>시스템의 부하를 높임</strong>으로써 결국 시스템을 다운시키는 바이러스의 일종으로, 분산 서비스 거부 공격, 버퍼 오버플로 공격, 슬래머 등이 웜 공격의 한 형태이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[정보처리기사] 소프트웨어 개발 보안 구축]]></title>
            <link>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%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/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%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>Sun, 13 Apr 2025 12:58:33 GMT</pubDate>
            <description><![CDATA[<h2 id="소프트웨어-개발-보안-요소">소프트웨어 개발 보안 요소</h2>
<p>소프트웨어 개발 보안 요소는 소프트웨어 개발에 있어 충족시켜야 할 요소 및 요건을 의미하며, 기밀성, 무결성, 가용성을 보안의 3대 요소라 한다.</p>
<p><strong>기밀성(Confidentiality)</strong></p>
<ul>
<li>시스템 내의 정보와 자원은 인가된 사용자에게만 접근이 허용된다.</li>
<li>정보가 전송 중에 노출되더라도 데이터를 읽을 수 없다.</li>
</ul>
<p><strong>무결성(Intergrity)</strong>
시스템 내의 정보는 오직 인가된 사용자만 수정할 수 있다.</p>
<p><strong>가용성(Availability)</strong>
인가받은 사용자는 시스템 내의 정보와 자원을 언제라도 사용할 수 있다.</p>
<p><strong>인증(Authentication)</strong></p>
<ul>
<li>시스템 내의 정보와 자원을 사용하려는 사용자가 합벚거인 사용자인지를 확인하는 모든 행위이다.</li>
<li><strong>대표적 방법</strong>: 패스워드, 인증용 카드, 지문 검사 등</li>
</ul>
<p><strong>부인 방지(NonRequdiation)</strong>
데이터를 송/수신한 자가 송/수신 사실을 부인할 수 없도록 송/수신 증거를 제공한다.</p>
<br>

<h2 id="sql-삽입">SQL 삽입</h2>
<ul>
<li>SQL 삽입(Injection)은 웹 응용 프로그램에 <strong>SQL을 삽입하여</strong> 내부 데이터베이스 서버의 <strong>데이터를 유출 및 변조하고, 관리자 인증을 우회하는 보안 약점</strong>이다.</li>
<li>동적 쿼리에 사용되는 입력 데이터에 예약어 및 특수문자가 입력되지 않게 필터링 되도록 설정하여 방지할 수 있다.</li>
</ul>
<br>

<h2 id="스택-가드">스택 가드</h2>
<ul>
<li>스택 가드(Stack Guard)는 널포인터 역참조와 같이 <strong>주소가 저장되는 스택에서 발생하는 보안 약점을 막는 기술</strong> 중 하나이다.</li>
<li>메모리상에서 프로그램의 복귀 주소와 변수 사이에 특정 값을 저장한 후 그 값이 변경되었을 경우 오버플로우 상태로 판단하여 프로그램 실행을 중단함으로써 잘못된 복귀 주소의 호출을 막는다.</li>
</ul>
<br>

<h2 id="접근-제어자">접근 제어자</h2>
<ul>
<li>접근 제어자는 프로그래밍 언어에서 특정 개체를 선언할 때 <strong>외부로부터의 접근을 제한하기 위해 사옹되는 예약어</strong>이다.</li>
<li>**접근 제어자의 종류(접근 가능: ○, 접근 불가능: Ⅹ)</li>
</ul>
<table>
<thead>
<tr>
<th align="center">접근 제어자</th>
<th align="center">클래스 내부</th>
<th align="center">패키지 내부</th>
<th align="center">하위 클래스</th>
<th align="center">패키지 외부</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Public</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">○</td>
</tr>
<tr>
<td align="center">Protected</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">Ⅹ</td>
</tr>
<tr>
<td align="center">Default</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">Ⅹ</td>
<td align="center">Ⅹ</td>
</tr>
<tr>
<td align="center">Private</td>
<td align="center">○</td>
<td align="center">Ⅹ</td>
<td align="center">Ⅹ</td>
<td align="center">Ⅹ</td>
</tr>
</tbody></table>
<br>

<h2 id="개인키-암호화-기법">개인키 암호화 기법</h2>
<ul>
<li>개인키 암호화(Private Key Encryption) 기법은 <strong>동일한 키로 데이터를 암호화하고 복호화하는 암호화 기법</strong>이다.</li>
<li>대칭 암호 기법 또는 단일키 암호화 기법이라고도 한다.</li>
<li>암호화와 복호화 속도가 빠르다.</li>
<li>관리해야 할 키의 수가 많다.</li>
<li>개인키 암호화 기법의 종류에는 스트림 암호화 방식과 블록 암호화 방식이 있다.</li>
</ul>
<p><strong>스트림 암호화 방식</strong></p>
<ul>
<li>평문과 동일한 길이의 스트림을 생성하여 비트 단위로 암호화 하는 방식.</li>
<li>종류: LFSR, RC4, TKIP</li>
</ul>
<p><strong>블록 암호화 방식</strong></p>
<ul>
<li>한 번에 하나의 데이터 블록을 암호화 하는 방식</li>
<li>종류: DES, SEED, AES, ARIA, IDEA, Skipjack</li>
</ul>
<br>

<h2 id="idea">IDEA</h2>
<ul>
<li>IDEA(International Data Encryption Algorithm)는 <strong>스위스의 라이(Lai)와 메시(Messey)가 1990년에 개발한 PES를 개선한 알고리즘</strong>이다.</li>
<li><strong>블록 크기는 64비트이고, 키 길이는 128비트</strong>이다.</li>
</ul>
<br>

<h2 id="skipjack">Skipjack</h2>
<ul>
<li>Skipjack은 <strong>국가 안전 보장국(NSA)에서 개발한 암호화 알고리즘</strong>이다.</li>
<li><strong>클리퍼 칩(Clipper Chip)</strong>이라는 IC칩에 내장되어 있다.</li>
<li><strong>블록 크기는 64비트이고, 키 길이는 80비트</strong>이다.</li>
<li>주로 음성 통신 장비에 삽입되어 <strong>음성 데이터를 암호화</strong>한다.</li>
</ul>
<br>

<h2 id="des">DES</h2>
<ul>
<li>DES(Data Encryption Standard)는 <strong>1975년 미국 NBS에서 발표한 개인키 암호화 알고리즘</strong>이다.</li>
<li><strong>블록 크기는 64비트, 키 길이는 56비트이며 16회의 라운드를 수행</strong>한다.</li>
<li>DES를 3번 적용하여 보안을 더욱 강화한 3DES(Triple DES)가 있다.</li>
</ul>
<br>

<h2 id="aes">AES</h2>
<ul>
<li>AES(Advanced Encryption Standard)는 <strong>2001년 미국 표준 기술 연구소(NIST)에서 바라표한 개인키 암호화 알고리즘</strong>이다.</li>
<li><strong>DES의 한계를 느낀 NIST에서 공모한 후 발표</strong>하였다.</li>
<li><strong>블록 크기는 128비트</strong>이며, 키 길이에 따라 AES-128, AES-192, AES-256으로 분류된다.</li>
</ul>
<br>

<h2 id="rsa">RSA</h2>
<ul>
<li>RSA(Rivest Shamir Adleman)는 <strong>1978년 MIT의 라이베스트(Rivest), 샤미르(Shamir), 애들먼(Adelman)에 의해 제안된 공개키 암호화 알고리즘</strong>이다.</li>
<li><strong>큰 숫자를 소인수분해 하기 어렵다</strong>는 것에 기반하여 만들어졌다.</li>
</ul>
<br>

<h2 id="tkip">TKIP</h2>
<ul>
<li>TKIP(Temporal Key Intergrity Protocol)는 기존의 무선 랜 보안 프로토콜이 <strong>WEP의 취약성을 보완한 데이터 보안 프로토콜</strong>이다.</li>
<li>암호 알고리즘의 입력 키 길이를 128비트로 늘리고 패킷당 키 할당, 키값 재설정 등의 키 관리 방식을 개선하였다.</li>
</ul>
<br>

<h2 id="해시">해시</h2>
<ul>
<li>해시(Hash)는 임의의 길이의 <strong>입력 데이터나 메시지를 고정된 길이의 값이나 키로 변환하는 것</strong>을 의미한다.</li>
<li>해시 알고리즘을 해시 함수라고 부르며, 해시 함수로 변환된 값이나 키를 해시값 또는 해시키라고 부른다.</li>
<li>종류: SHA 시리즈, HAVAL, MD4, MD5, N-NASH, SNEFRU 등</li>
</ul>
<br>

<h2 id="md5">MD5</h2>
<ul>
<li>MD5(Mseesage Digest algorithm 5)는 <strong>1991년 R.Rivest가 MD4를 대체하기 위해 고안한 암호화 해시 함수</strong>이다.</li>
<li><strong>블록 크기가 512비트</strong>이며, <strong>키 길이는 128비트</strong>이다.</li>
</ul>
<br>

<h2 id="인증">인증</h2>
<ul>
<li>인증(Authentication)은 다중 사용자 컴퓨터 시스템이나 네티워크 시스템에서 <strong>로그인을 요청한 사용자의 정보를 확인하고 접근 권하을 검증하는 보안 절차</strong>이다.</li>
<li><strong>인증의 종류</strong></li>
</ul>
<table>
<thead>
<tr>
<th align="center">종류</th>
<th align="left">유형</th>
</tr>
</thead>
<tbody><tr>
<td align="center">지식기반인증(Something You Know)</td>
<td align="left">고정된 패스워드, 패스 프레이즈, 아이핀 등</td>
</tr>
<tr>
<td align="center">소유 기반 인증(Something You Have)</td>
<td align="left">신분증, 메모리 카드, 스카트 카드, OTP 등</td>
</tr>
<tr>
<td align="center">생체 기반 인증(Something You Are)</td>
<td align="left">지문, 홍채/망막, 얼굴, 음성, 정맥 등</td>
</tr>
<tr>
<td align="center">위치 기반 인증(Something You Are)</td>
<td align="left">GPS, IP, 콜백 등</td>
</tr>
<tr>
<td align="center">행위 기반 인중(Somethin You Do)</td>
<td align="left">서명, 동작 등</td>
</tr>
</tbody></table>
<br>

<h2 id="침임-탐지-시스템">침임 탐지 시스템</h2>
<ul>
<li>침임 탐지 시스템(IDS; Intrusion Detection System)은 <strong>컴퓨터 시스템의 비정상적인 사용, 오용, 남용 등을 실시간으로 탐지하는 시스템</strong>이다.</li>
<li><strong>오용 탐지(Misuse Detection)</strong>: 미리 입력해 둔 공격 패턴이 감지되면 이를 알려줌</li>
<li><strong>이상 탐지(Anomaly Detection)</strong>: 평균적인 시스템의 상태를 기준으로 비정상적인 행위나 자원의 사용이 감지되면 이를 알려줌.</li>
</ul>
<br>

<h2 id="vpn">VPN</h2>
<ul>
<li>VPN(Virtual Private Network, 가상 사설 통신망)은 인터넷 등 통신 사업자의 <strong>공중 네트워크와 암호화 기술을 이용하여 사용자가 마치 자신의 전용 회선을 사용하는 것처럼 해주는 보안 솔루션</strong>이다.</li>
<li>SSL VPN: PC에 VPN Client 프로그램을 설치하여 VPN 서버에 접속하는 방식으로, 암호화를 위해 SSL 프로토콜을 사용함.</li>
<li>IPSec VPN: VPN 서버가 설치된 각각의 네트워크를 서로 연결하는 방식으로, 암호화를 위해 IPSec 프로토콜을 사용함.</li>
</ul>
<br>

<h2 id="siem">SIEM</h2>
<ul>
<li>SIEM(Security Information and Event Management)은 다양한 장비에서 발생하는 <strong>로그 및 보안 이벤트를 통합하여 관리하는</strong> 빅 데이터 기반의 <strong>보안 솔루션</strong>이다.</li>
<li>방화벽, IDS, IPS, 웹 방화벽, VPN 등에서 발생한 로그 및 보안 이벤트를 통합하여 관리함으로써 비용 및 자원을 절약할 수 있다.</li>
<li>장기간의 로그 및 보안 이벤트를 수집 및 검색할 수 있는 빅데이터 기반의 통합 로그 수집 시스템이다.</li>
</ul>
<br>

<h2 id="ssh">SSH</h2>
<ul>
<li>SSH(Secure SHell, 시큐어 셸)는 <strong>다른 컴퓨터에 원격으로 접속하여 작업을 수행할 수 있도록 다양한 기능을 지원하는 프로토콜</strong> 또는 이를 이용한 응용 프로그램이다.</li>
<li>데이터 암호화와 강력한 인증 방법으로 보안성이 낮은 네트워크에서도 안전하게 통신할 수 있다.</li>
<li>키를 통한 인증 방법을 사용하려면 사전에 클라이언트의 공개키를 서버에 등록해야 한다.</li>
<li>기본적으로는 <strong>22번 포트</strong>를 사용한다.</li>
</ul>
<br>

<h2 id="aaa3a">AAA(=3A)</h2>
<ul>
<li>AAA는 다음 3가지 기능을 기반으로 사용자의 컴퓨터 자원 접근에 대한 처리와 서비스를 제동하는 기반 구조 또는 규격을 의미한다.</li>
<li><strong>인증(Authentication)</strong>: 접근하는 사용자의 시원을 검증하는 기능</li>
<li><strong>인간(Authorization)</strong>: 신원이 검증된 사용자에게 특정된 권한과 서비스를 허용하는 기능</li>
<li><strong>과금(Accounting)</strong>: 사용자가 어떤 종류의 서비스를 이용했고, 얼마만큼의 지원을 사용했는지 기록 및 보관하는 기능</li>
</ul>
<br>

<h2 id="정보보호-관리-체계">정보보호 관리 체계</h2>
<ul>
<li>정보보호 관리 체계(ISMS; Information Security Management System)는 <strong>정보 자산을 안전하게 보호하기 위한 보호 절차와 대책</strong>을 의미한다.</li>
<li>조직에 맞는 정보보호 정책을 수립하고, 위험에 상시 대응하는 여러 보안 대책을 통합 관리/ 운용한다.</li>
<li>우리나라에서는 정보보호 관리 체계를 평가하고 인증하는 사업을 한국인터넷진흥원(KISA)에서 운영하고 있다.</li>
</ul>
<br>

<h2 id="ping-of-death">Ping of Death</h2>
<ul>
<li>Ping if Death(죽음의 핑)는 Ping 명령을 전송할 때 <strong>패킷의 크기를</strong> 인터넷 프로토콜 <strong>허용 범위 이상으로 전송</strong>하여 공격 대상의 <strong>네트워크를 마비시키는 서비스 거보 공격 방법</strong>이다.</li>
<li>공격에 사용되는 큰 패킷은 수백 개의 패킷으로 분할되어 전송되는데, 공격 대상은 분할된 대량의 패킷을 수신함으로써 분할되어 전송된 패킷을 재조립해야 하는 부담과 분할되어 전송된 각각의 패킷들의 ICMP Ping 메시지에 대한 응답을 처리하는라 시스템이 다운되게 된다.</li>
</ul>
<br>

<h2 id="smurfing">SMURFING</h2>
<ul>
<li>SMURFING(스머핑)은 <strong>IP나 ICMP의 특성을 악용하여 엄청난 양의 데이터를 한 사이트에 집중적으로 보냄으로써 네트워크를 불능 상태로 만드는 공격 방법</strong>이다.</li>
<li>SMURFING 공격을 무력화하는 방법 중 하나는 각 네트워크 라우터에서 브로드캐스트 주소를 사용할 수 없게 미리 설정해 놓는 것이다.</li>
</ul>
<br>

<h2 id="land-attack">LAND Attack</h2>
<p>LAND Attack(Local Area Network Denial Attack)은 <strong>패킷을 전송할 때 송신 IP 주소와 수신 IP 주소를 모두 공격 대상의 IP 주소로 하여</strong> 공격 대상에게 전송하는 것으로, 이 패킷을 받은 공격 대상은 송신 IP 주소가 자신이므로 자신에게 응답을 수행하게 되는데, 이러한 패킷이 계속해서 전송될 경우 <strong>자신에 대해 무한히 응답하게 하는 공격 방법</strong>이다.</p>
<br>

<h2 id="분산-서비스-공격용-툴">분산 서비스 공격용 툴</h2>
<p>에이전트의 역할을 수행하도록 설계된 프로그램으로 데몬이라고 부르며, 다음과 같은 종류가 있다.</p>
<ul>
<li><strong>Trin00</strong>
가장 초기 형태의 데몬으로, 주로 UDP Flooding 공격을 수행함</li>
<li><strong>TFN(Tribe Flood Network)</strong>
UDP Flooding 뿐만 아니라 TCP SYN Flood 공격, ICMP 응답 요청, 스머핑 공격 등을 수행함.</li>
<li><strong>TFN2K</strong>
TFN의 확장판임</li>
<li><strong>Stacheldraht</strong><ul>
<li>이전 툴들의 기능을 유지하면서, 공격자, 마스터, 에이전트가 쉽게 노출되지 않도록 암호화된 통신을 수행함</li>
<li>툴이 자동으로 업데이트됨</li>
</ul>
</li>
</ul>
<br>

<h2 id="세션-하이재킹">세션 하이재킹</h2>
<ul>
<li><p>세션 하이재킹은 <strong>상호 인증 과정을 거친 후 접속해 있는 서버와</strong> 서로 접속되어 <strong>클라이언트 사이의 세션 정보를 가로채는 공격 기법</strong>으로, 접속을 위한 인증 정보 없이도 가로챈 세션을 이용해 공격자가 원래의 클라이언트인 것처럼 위장하여 서버의 자원이나 데이터를 무단으로 사용한다.</p>
</li>
<li><p>TCP 3-Way-Handshake 과정에 끼어듦으로써 클라이언트와 서버 간의 동기화된 시퀀스 번호를 가로채 서버에 무단으로 접근하는 TCP 세션 하이재킹이 대표적인 예이다.</p>
</li>
</ul>
<br>

<h2 id="arp-스푸핑">ARP 스푸핑</h2>
<p>ARP 스푸핑은 ARP의 취약점을 이용한 공격 기법으로, <strong>자신의 물리적 주소(MAC)를 공격 대상의 것으로 변조하여</strong> 공격 대상에게 도달해야 하는 <strong>데이터 패킷을 가로패거나 방해하는 기법</strong>이다.</p>
<ul>
<li>**ARP(Address Resolution Protocol): 호ㅛㅡ트의 IP주소를 호스트와 연결된 네트워크 접속 장치의 물리적 주소(MAC Address)로 변환해주는 프로토콜</li>
</ul>
<br>

<h2 id="사회-공학">사회 공학</h2>
<p>사회 공학은 컴퓨터 보안에 있어서, <strong>인산 상호 작용의 깊은 신뢰를 바탕으로</strong> 사람들을 속여 정상 보안 절차를 깨트리기 위한 비기술적 <strong>시스템 침입 수단</strong>이다.</p>
<br>

<h2 id="다크-데이터">다크 데이터</h2>
<p>다크 데이터는 특정 목적을 가지고 데이터를 수집하였으나, 이후 <strong>활용되지 않고 저장만 되어 있는 대량의 데이터</strong>를 의미한다.</p>
<br>

<h2 id="타이포스쿼팅">타이포스쿼팅</h2>
<ul>
<li>타이포스쿼팅은 네티즌들이 사이트에 접속할 때 <strong>주소를 잘못 입력</strong>하거나 철자를 빠뜨리는 <strong>실수를 이용하기 위해 이와 유서한 유명 도메인을 미리 등록하는 것</strong>이다.</li>
<li>URL 하이재킹이라고도 한다.</li>
</ul>
<br>

<h2 id="스니핑">스니핑</h2>
<p>스니핑은 <strong>네트워크의 중간에서 남의 패킷 정보를 도청</strong>하는 해킹 유형의 하나로, 수동적 공격에 해당한다.</p>
<br>

<h2 id="워터링-홀">워터링 홀</h2>
<ul>
<li>워터링 홀은 목표 대상이 자주 방문하는 <strong>웹 사이트를 사전에 감염시켜</strong> 대상이 해당 <strong>사이트에 방문했을 떄 악성 코드에 감염되게 하는</strong> 웹 기반 <strong>공격</strong>이다.</li>
<li>감염된 PC를 기반으로 대상이 속한 조직의 중요 시스템에 접근하거나 불능으로 만드는 등의 영향력을 행사할 수 있다.</li>
</ul>
<br>

<h2 id="키로거-공격">키로거 공격</h2>
<p>키로거 공격은 <strong>컴퓨터 사용자의 키보드 움직임을 탐지해</strong> ID, 패스워드, 꼐좌번호, 카드번호 등과 같은 개인의 중요한 <strong>정보를 몰래 빼가는 해킹 공격</strong>이다.</p>
<br>

<h2 id="랜섬웨어">랜섬웨어</h2>
<p>랜섬웨어는 인터넷 사용자의 컴퓨터에 잠입해 <strong>내부 문서나 파일 등을 암호화해 사용자가 열지 못하게 하는 프로그램</strong>으로, 암호 해독용 프로그램의 전달을 조건으로 사용자에게 돈을 요구하기도 한다.</p>
<br>

<h2 id="백도어">백도어</h2>
<ul>
<li>백도어는 <strong>시스템 설계자가</strong> 서비스 기술자나 유지 보수 프로그램 작성자의 <strong>액세스 편의를 위해 시스템 보안을 제거하여 만들어 놓은 비밀 통로</strong>로, 컴퓨터 범죄에 악용되기도 한다.</li>
<li><strong>백도어 탐지 방법</strong>: 무결서 ㅇ검사, 열린 포트 확인, 로그 분석, SetUID 파일 검사 등</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[정보처리기사] SQL 응용]]></title>
            <link>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-SQL-%EC%9D%91%EC%9A%A9</link>
            <guid>https://velog.io/@kid_an/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-SQL-%EC%9D%91%EC%9A%A9</guid>
            <pubDate>Tue, 01 Apr 2025 07:06:00 GMT</pubDate>
            <description><![CDATA[<h2 id="ddl">DDL</h2>
<ul>
<li>DDL(Data Define Language, 데이터 정의어)은 DB 구조, 데이터 형식, 접근 방식 등 <strong>DB를 구축하거나 수정할 목적으로 사용하는 언어</strong>이다.</li>
<li>DDL의 3가지 유형
CREATE, ALTER, DROP</li>
</ul>
<br>

<h2 id="create-index">CREATE INDEX</h2>
<p>CREATE INDEX는 <strong>인덱스를 정의하는 명령문</strong>이다.
<strong>CREATE</strong> [UNIQUE] <strong>INDEX</strong> 인덱스명
<strong>ON</strong> 테이블명(속성명[ASC|DESC][, 속성명[ASC|DESC]])
[CLUSTER];</p>
<ul>
<li>UNIQUE
사용된 경우: 중복 값이 없는 속성으로 인덱스를 생성함
생략된 경우: 중복 값을 허용하는 속성으로 인덱스를 생성함</li>
<li>정렬 여부 지정
ASC: 오름차순 정렬
DESC: 내림차순 정렬
생략된 경우: 오름차순으로 정렬됨</li>
<li>CLUSTER: 사용하면 인덱스가 클러스터드 인덱스로 설정됨</li>
</ul>
<br>

<h2 id="alter-table">ALTER TABLE</h2>
<p>ALTER TABLE은 <strong>테이블에 대한 정의를 변경하는 명령문</strong>이다.</p>
<p><strong>표기 형식</strong>
<strong>ALTER TABLE</strong> 테이블명 <strong>ADD</strong> 속성명 데이터_타입[DEFAULT &#39;기본값&#39;];
<strong>ALTER TABLE</strong> 테이블명 <strong>ALTER</strong> 속성명[SET DEFAULT &#39;기본값&#39;];
<strong>ALTER TABLE</strong> 테이블명 <strong>DROP COLUMN</strong> 속성명[CASCADE];</p>
<ul>
<li>ADD: 세로운 속성(열)을 추가할 때 사용함.</li>
<li>ALTER: 특정 속성의 Default 값을 변경할 때 사용함.</li>
<li>DROP COLUMN: 특정 속성을 삭제할 때 사용함.</li>
</ul>
<br>

<h2 id="drop">DROP</h2>
<p>DROP은 <strong>스키마, 도메인, 기본 테이블, 뷰 테이블, 인덱스, 제약 조건 등을 제거하는 명령문</strong>이다.</p>
<p><strong>표기 형식</strong>
<strong>DROP SCHEMA</strong> 스키마명[CASCADE|RESTRICT];
<strong>DROP DOMAIN</strong> 도메인명[CASCADE|RESTRICT];
<strong>DROP TABLE</strong> 테이블명[CASCADE|RESTRICT];
<strong>DROP VIEW</strong> 뷰명[CASCADE|RESTRICT];
<strong>DROP INDEX</strong> 인덱스명[CASCADE|RESTRICT];
<strong>DROP CONSTRAINT</strong> 제약조건명;</p>
<ul>
<li>CASCADE: 제거할 요소를 참조하는 다른 모든 개체를 함께 제거함.</li>
<li>RESTRICT: 다른 개체가 제거할 요소를 참조중일 때는 제거를 취소함.</li>
</ul>
<br>

<h2 id="dcl">DCL</h2>
<ul>
<li>DCL(Data Control Language, 데이터 제어어)은 <strong>데이터의 보안, 무결성, 회복, 병행 제어 등을 정의하는 데 사용하는 언어</strong>이다.</li>
<li>DCL은 데이터베이스 관리자가 데이터 관리를 목적으로 사용한다.
COMMIT, ROLLBACK, GRANT, REVOKE</li>
</ul>
<br>

<h2 id="geant--revoke">GEANT / REVOKE</h2>
<ul>
<li>데이터베이스 관리자가 데이터베이스 사용자에게 권한을 부여하거나 취소하기 위한 명령어이다.</li>
<li><em>표기 형식*</em></li>
<li><em>GRANT*</em> 권한_리스트 <strong>ON</strong> 개체 <strong>TO</strong> 사용자[WITH GRANT OPTION];</li>
<li><em>REVOKE*</em> [GRANT OPTION FOR] 권한_리스트 <strong>ON</strong> 개체 <strong>FROM</strong> 사용자[CASCADE];</li>
<li>권한 종류: ALL, SELECT, INSERT, DELETE, UPDATE 등</li>
<li>WITH GRANT OPTION: 부여받은 권한을 다른 사용자에게 다시 부여할 수 있는 권한을 부여함</li>
<li>GRANT OPTION FOR: 다른 사용자에게 권한을 부여할 수 있는 권한을 취소함</li>
<li>CASCADE: 권한 취소 시 권한을 부여받았던 사용자가 다른 사용자에게 부여한 권한도 연쇄적으로 취소함</li>
</ul>
<br>

<h2 id="dml">DML</h2>
<ul>
<li>DML(Data Maniplation Language, 데이터 조작어)은 데이터베이스 사용자가 <strong>저장된 데이터를 실질적으로 관리하는데 사용되는 언어</strong>이다.</li>
<li>DML은 데이터베이스 사용자와 데이터베이스 관리 시스템 간의 인터페이스를 제공한다.
SELECT, INSERT, DELETE, UPDATE</li>
</ul>
<br>

<h2 id="삽입문insert-into-">삽입문(INSERT INTO ~)</h2>
<p><strong>INSERT INTO</strong> 테이블명(속성명1, 속성명2, ...]) <strong>VALUES</strong>(데이터1, 데이터2, ...);</p>
<br>

<h2 id="삭제문delete-from-">삭제문(DELETE FROM ~)</h2>
<p><strong>DELETE FROM</strong> 테이블명[WHERE 조건];</p>
<br>

<h2 id="갱신문update--set-">갱신문(UPDATE ~ SET ~)</h2>
<p><strong>UPDATE</strong> 테이블명 <strong>SET</strong> 속성명1 = 데이터1, [속성명2 = 데이터2, ...] [WHERE 조건];</p>
<br>

<h2 id="select">SELECT</h2>
<p><strong>SELECT</strong> [PREDICATE][테이블명.]속성명[AS 별칭][, [테이블명.]속성명, ...]
<strong>FROM</strong> 테이블명[, 테이블명, ...]
[WHERE 조건]
[GROUP BY 속성명, 속성명, ...]
[HAVING 조건]
[ORDER BY 속성명 [ASC | DESC]];</p>
<ul>
<li>SELECT절<ul>
<li>PREDICATE: 검색할 튜플 수를 제한하는 명령어를 기술함</li>
<li>DISTINCT: 중복된 튜플이 있으면 그 중 첫 번째 한 개만 표시함</li>
</ul>
</li>
</ul>
<br>

<h2 id="하위-질의">하위 질의</h2>
<p>하위 질의는 조건절에 주어진 질의를 먼저 수행하여 그 검색 결과를 조건절의 피연산자로 사용한다.</p>
<br>

<h2 id="그룹-함수">그룹 함수</h2>
<p>그룹 함수는 GROUP BY절에 지정된 그룹별로 속성의 값을 집계할 때 사용된다.</p>
<table>
<thead>
<tr>
<th align="left"><strong>명령어</strong></th>
<th align="left"><strong>기능</strong></th>
</tr>
</thead>
<tbody><tr>
<td align="left">COUNT(속성명)</td>
<td align="left">그룹별 튜플 수를 구하는 함수</td>
</tr>
<tr>
<td align="left">SUM(속성명)</td>
<td align="left">그룹별 합계를 구하는 함수</td>
</tr>
<tr>
<td align="left">AVG(속성명)</td>
<td align="left">그룹별 평균을 구하는 함수</td>
</tr>
<tr>
<td align="left">MAX(속성명)</td>
<td align="left">그룹별 최대값을 구하는 함수</td>
</tr>
<tr>
<td align="left">MIN(속성명)</td>
<td align="left">그룹별 최소값을 구하는 함수</td>
</tr>
<tr>
<td align="left">STDDEV(속성명)</td>
<td align="left">그룹별 표준편차를 구하는 함수</td>
</tr>
<tr>
<td align="left">VARIANCE(속성명)</td>
<td align="left">그룹별 분산을 구하는 함수</td>
</tr>
</tbody></table>
<br>

<h2 id="집합-연산자를-이용한-통합-질의">집합 연산자를 이용한 통합 질의</h2>
<p>집합 연산자를 사용하여 2개 이상의 테이블의 데이터를 하나로 통합한다.</p>
<p><strong>표기 형식</strong>
<strong>SELECT</strong> 속성명1, 속성명2, ...
<strong>FROM</strong> 테이블명
<strong>UNION | UNION ALL | INTERSECT | EXCEPT</strong>
<strong>SELECT</strong> 속성명1, 속성명2, ...
<strong>FROM</strong> 테이블명
[<strong>ORDER BY</strong> 속성명 [ASC | DESC]];</p>
<ul>
<li>두 개의 SELECT문에 기술한 속성들은 개수와 데이터 유형이 서로 동일해야 한다.</li>
<li><strong>집합 연산자의 종류</strong></li>
</ul>
<table>
<thead>
<tr>
<th align="center">집합 연산자</th>
<th align="center">설명</th>
<th align="center">집합 종류</th>
</tr>
</thead>
<tbody><tr>
<td align="center">UNION</td>
<td align="center">- 두 SELECT문의 조회 결과를 통합하여 모두 출력함<br>- 중복된 행은 한 번만 출력함</td>
<td align="center">합집합</td>
</tr>
<tr>
<td align="center">UNION ALL</td>
<td align="center">- 두 SELECT문의 조회 결과를 통합하여 모두 출력함<br>- 중복된 행도 그대로 출력함</td>
<td align="center">합집합</td>
</tr>
<tr>
<td align="center">INTERSECT</td>
<td align="center">두 SELECT문의 조회 결과 중 공통된 행만 출력함</td>
<td align="center">교집합</td>
</tr>
<tr>
<td align="center">EXCEPT</td>
<td align="center">첫 번째 SELECT문의 조회 결과에서 두 번째 SELECT문의 조회 결과를 제외한 행을 출력함</td>
<td align="center">차집합</td>
</tr>
</tbody></table>
<br>

<h2 id="join">JOIN</h2>
<ul>
<li>JOIN은 2개의 릴레이션에서 <strong>연관된 튜플들을 결합하여, 하나의 새로운 릴레이션을 반환</strong>한다.</li>
<li>JOIN은 일반적으로 FROM절에 기술하지만, 릴레이션이 사용되는 곳 어디에나 사용할 수 있다.</li>
<li>JOIN은 크게 INNER JOIN과 OUTER JOIN으로 구분된다.<ul>
<li>INNER JOIN: THETA JOIN, EQUI JOIN, NATURAL JOIN, NON-EQUI JOIN</li>
<li>OUTER JOIN: LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN</li>
</ul>
</li>
</ul>
<br>

<h2 id="equi-join동등-조인">EQUI JOIN(동등 조인)</h2>
<ul>
<li><p>JOIN에 참여하는 두 릴레이션의 속성 값을 비교하여 조건을 만족하는 튜플만 반환하는 조인을 THEA JOIN(세타 조인)이라고 하며, 조인에 사용되는 조건에는 =, ≠, &lt;, ≤, &gt;, ≥가 있다.</p>
</li>
<li><p>EQUI JOIN(동등조인)은 조인에 사용되는 조건 중 =(equal) 비교에 의해 같은 값을 가지는 행을 연결하여 결과를 생성하는 방법이다.</p>
</li>
<li><p>EQUI JOIN에서 JOIN 조건이 &#39;=&#39;일 때 동일한 속성이 두 번 나타나게 되는데, 이 중 중복된 속성을 제거하여 같은 속성을 한 번만 표기하는 방법을 NATURAL JOIN(자연 조인)이라고 한다.</p>
</li>
<li><p>EQUI JOIN에서 연결 고리가 되는 공통 속성을 JOIN 속성이라고 한다.</p>
</li>
<li><p><strong>WHERE절을 이용한 EQUI JOIN의 표기 형식</strong></p>
</li>
<li><p><em>SELECT*</em> [테이블명1.]속성명, [테이블명.]속성명2, ...</p>
</li>
<li><p><em>FROM*</em> 테이블명1, 테이블명2, ...</p>
</li>
<li><p><em>WHERE*</em> 테이블명1.속성명 = 테이블명2.속성명;</p>
</li>
<li><p><strong>NATURAL JOIN절을 이용한 EQUI JOIN의 표기 형식</strong></p>
</li>
<li><p><em>SELECT*</em> [테이블명1.]속성명, [테이블명.]속성명2, ...</p>
</li>
<li><p><em>FROM*</em> 테이블명1 <strong>NATURAL JOIN</strong> 테이블명2</p>
</li>
<li><p><strong>JOIN ~ USING절을 이용한 EQUI JOIN의 표기 형식</strong></p>
</li>
<li><p><em>SELECT*</em> [테이블명1.]속성명, [테이블명.]속성명2, ...</p>
</li>
<li><p><em>FROM*</em> 테이블명1 <strong>JOIN</strong> 테이블명2 <strong>USING</strong>(속성명);</p>
</li>
</ul>
<br>

<h2 id="outer-join">OUTER JOIN</h2>
<ul>
<li><p>LEFT OUTER JOIN: INNER JOIN의 결과를 구한 후, 우측 항 릴레이션의 어떤 튜플과도 맞지 않는 좌측 항의 릴레이션에 있는 튜플들에 NULL 값을 붙여서 INNER JOIN의 결과에 추가함</p>
</li>
<li><p><strong>표기 형식</strong></p>
</li>
<li><p><em>SELECT*</em> [테이블명1.]속성명, [테이블명.]속성명2, ...</p>
</li>
<li><p><em>FROM*</em> 테이블명1 <strong>LEFT OUTER JOIN</strong> 테이블명2</p>
</li>
<li><p><em>ON*</em> 테이블명1.속성명 = 테이블명2.속성명;</p>
</li>
<li><p>RIGHT OUTER JOIN: INNER JOIN의 결과를 구한 후, 좌측 항 릴레이션의 어떤 튜플과도 맞지 않는 우측 항의 릴레이션에 있는 튜플들에 NULL 값을 붙여서 INNER JOIN의 결과에 추가함</p>
</li>
<li><p><strong>표기 형식</strong></p>
</li>
<li><p><em>SELECT*</em> [테이블명1.]속성명, [테이블명.]속성명2, ...</p>
</li>
<li><p><em>FROM*</em> 테이블명1 <strong>RIGHT OUTER JOIN</strong> 테이블명2</p>
</li>
<li><p><em>ON*</em> 테이블명1.속성명 = 테이블명2.속성명;</p>
</li>
</ul>
<br>

<h2 id="트리거">트리거</h2>
<ul>
<li>트리거(Trigger)는 데이터베이스 시스템에서 데이터의 삽입, 갱신, 삭제 등의 <strong>이벤트가 발생할 때 관련 작업이 자동으로 수행되게 하는 절차형 SQL</strong>이다.</li>
<li>트리거는 데이터베이스에 저장되며, 데이터 변경 및 무결성 유지, 로그 메시지 출력 등의 목적으로 사용된다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>