<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jhdai_ly.log</title>
        <link>https://velog.io/</link>
        <description>사회 과학과 딥 러닝에 관심이 있는 학부생(CS&amp;E)입니다. 기술과 사회에 대한 이해를 바탕으로, 비즈니스 감각과 기술적 역량을 함께 갖춘 인공지능 프로그래머•데이터 과학자로 성장하고 싶습니다.</description>
        <lastBuildDate>Mon, 03 Aug 2026 08:52:28 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jhdai_ly.log</title>
            <url>https://velog.velcdn.com/images/jhdai_ly/profile/97969a1a-bf9e-4acc-8f89-8eecf07a1725/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jhdai_ly.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jhdai_ly" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2026 하계 모각코 - 6회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Mon, 03 Aug 2026 08:52:28 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득-준비">1. 정보처리기사 취득 준비</h2>
<p>데이터베이스 구축 과목에서는 논리 데이터베이스 설계와 물리 데이터베이스 설계에 관한 내용을 학습하였다. 사용자의 요구사항을 데이터 구조로 변환하고, 이를 실제 데이터베이스에 구현하는 전체 과정을 이해하는 데 중점을 두었다. 논리 설계에서는 데이터 간 관계와 구조를 명확하게 정의하고, 물리 설계에서는 저장 공간과 조회 성능, 무결성 등을 고려하여 실제 운영 환경에 적합한 데이터베이스를 구성하는 방법을 학습하였다.</p>
<p>관계 데이터베이스 모델에서는 데이터를 행과 열로 구성된 릴레이션 형태로 표현하는 방법을 학습하였다. 릴레이션은 테이블, 튜플은 행, 속성은 열에 해당하며, 각 속성이 가질 수 있는 값의 범위를 도메인이라고 한다는 점을 이해하였다. 또한 하나의 릴레이션에는 동일한 튜플이 중복될 수 없고, 튜플과 속성의 순서는 데이터의 의미에 영향을 주지 않는다는 관계형 데이터베이스의 특징을 정리하였다.</p>
<p>관계 데이터베이스에서 필요한 데이터를 추출하기 위해 관계 대수의 기본 연산도 학습하였다. 조건에 맞는 행을 선택하는 셀렉션, 필요한 열만 추출하는 프로젝션, 여러 릴레이션을 연결하는 조인 연산의 특징을 이해하였다. 합집합, 교집합, 차집합과 같은 집합 연산을 적용할 때는 두 릴레이션의 속성 수와 도메인이 서로 대응되어야 한다는 점도 배웠다.</p>
<p>데이터 모델링 및 설계에서는 현실 세계의 업무와 데이터를 개체, 속성, 관계로 분석하여 데이터베이스 구조로 표현하는 과정을 학습하였다. 요구사항 분석 결과를 바탕으로 주요 개체와 속성을 정의하고, 개체 간 관계를 ER 다이어그램으로 표현하는 개념적 데이터 모델링의 과정을 이해하였다. 이후 개념적 모델을 테이블 구조로 변환하고 기본키와 외래키를 정의하는 논리적 데이터 모델링 과정도 함께 학습하였다.</p>
<p>정규화에서는 데이터의 중복을 줄이고 삽입, 삭제, 갱신 이상 현상을 방지하기 위해 테이블을 분해하는 방법을 학습하였다. 제1정규형에서는 속성값의 원자성을 확보하고, 제2정규형에서는 부분 함수 종속을 제거하며, 제3정규형에서는 이행 함수 종속을 제거한다는 점을 이해하였다. 정규화는 단순히 테이블을 나누는 작업이 아니라 데이터의 일관성과 유지보수성을 높이기 위한 설계 과정이라는 점을 알 수 있었다.</p>
<p>물리 요소 조사 및 분석에서는 실제 데이터베이스를 구축하기 전에 데이터의 양, 증가 속도, 조회 빈도, 갱신 빈도, 응답 시간, 저장 공간 등의 운영 조건을 분석하는 방법을 학습하였다. 동일한 논리적 데이터 모델이라도 사용 환경과 처리량에 따라 물리적 설계가 달라질 수 있으며, 자주 조회되는 데이터와 자주 변경되는 데이터를 구분하여 저장 구조를 설계해야 한다는 점을 이해하였다.</p>
<p>DB 물리 속성 설계에서는 논리 데이터 모델에서 정의한 속성을 실제 데이터베이스의 컬럼으로 구현하는 방법을 학습하였다. 각 컬럼에 적절한 데이터 타입과 길이를 지정하고, 기본값과 NULL 허용 여부, 제약조건을 설정하는 과정을 정리하였다. 데이터 타입을 지나치게 크게 설정하면 저장 공간이 낭비될 수 있고, 반대로 너무 작게 설정하면 정상적인 데이터가 저장되지 않을 수 있으므로 실제 데이터의 범위와 사용 목적을 고려해야 한다는 점을 배웠다.</p>
<p>인덱스 설계에서는 특정 데이터의 검색 속도를 높이기 위해 별도의 접근 경로를 구성하는 방법을 학습하였다. 조회 조건이나 조인 조건에 자주 사용되는 컬럼에 인덱스를 적용하면 검색 성능을 높일 수 있지만, 데이터가 추가되거나 변경될 때 인덱스도 함께 갱신되므로 삽입과 수정 성능에는 부담이 될 수 있다는 점을 이해하였다. 따라서 모든 컬럼에 인덱스를 생성하는 것이 아니라 조회 빈도와 선택도, 데이터 변경 빈도를 고려하여 설계해야 한다는 점을 알 수 있었다.</p>
<p>데이터베이스 무결성과 키에서는 데이터의 정확성과 일관성을 유지하기 위한 제약조건을 학습하였다. 기본키는 각 튜플을 유일하게 식별하며 중복값과 NULL을 허용하지 않고, 외래키는 다른 테이블의 기본키를 참조하여 테이블 간 관계를 표현한다는 점을 정리하였다. 후보키, 기본키, 대체키, 슈퍼키의 차이를 구분하고, 외래키를 통해 참조 무결성을 유지해야 한다는 점을 이해하였다.</p>
<p>개체 무결성은 기본키에 NULL이나 중복값이 입력되지 않도록 하는 규칙이며, 참조 무결성은 외래키가 참조하는 값이 부모 테이블에 존재하도록 하는 규칙이라는 점을 학습하였다. 도메인 무결성은 속성에 정의된 데이터 타입과 범위에 맞는 값만 입력되도록 제한하는 방식으로, 각 무결성 제약조건이 데이터 오류를 예방하는 역할을 한다는 점을 이해하였다.</p>
<p>DB 반정규화에서는 정규화된 데이터 구조의 조회 성능을 높이기 위해 의도적으로 데이터 중복을 허용하는 방법을 학습하였다. 자주 조인되는 테이블을 통합하거나, 반복적으로 계산되는 값을 별도의 컬럼에 저장하고, 필요한 테이블을 중복 생성하여 조회 경로를 단축할 수 있다는 점을 이해하였다.</p>
<p>반정규화를 적용하면 조회 속도와 시스템 응답 시간을 개선할 수 있지만, 같은 데이터가 여러 위치에 저장되므로 데이터 수정 시 모든 값을 일관되게 변경해야 한다는 부담이 발생한다. 따라서 반정규화는 단순히 테이블을 합치는 작업이 아니라 정규화된 구조에서 실제 성능 문제가 확인되었을 때 적용해야 하며, 데이터 정합성을 유지할 수 있는 관리 방안도 함께 마련해야 한다는 점을 배웠다.</p>
<p>이번 학습을 통해 논리 데이터베이스 설계는 데이터의 관계와 구조를 정확하게 표현하는 과정이고, 물리 데이터베이스 설계는 이를 실제 시스템 환경에 맞게 구현하고 최적화하는 과정이라는 점을 이해하였다. 또한 정규화, 인덱스, 무결성, 반정규화는 각각 독립된 개념이 아니라 데이터의 일관성과 성능 사이에서 적절한 균형을 찾기 위해 함께 고려해야 하는 요소라는 점을 알 수 있었다.</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<pre><code class="language-python"># =========================================================
# 1. 연산자 끼워 넣기
# 주어진 수의 순서는 유지하고 연산자의 배치를 완전탐색하여
# 계산 결과의 최댓값과 최솟값을 구하는 문제
# =========================================================
def operator_insertion(numbers, operators):
    maximum = -float(&quot;inf&quot;)
    minimum = float(&quot;inf&quot;)

    def calculate(left, right, operator):
        if operator == 0:
            return left + right
        if operator == 1:
            return left - right
        if operator == 2:
            return left * right

        # 음수 나눗셈은 0을 향해 버림
        if left &lt; 0:
            return -((-left) // right)
        return left // right

    def backtrack(index, current_value):
        nonlocal maximum, minimum

        if index == len(numbers):
            maximum = max(maximum, current_value)
            minimum = min(minimum, current_value)
            return

        for operator in range(4):
            if operators[operator] == 0:
                continue

            operators[operator] -= 1

            next_value = calculate(
                current_value,
                numbers[index],
                operator
            )

            backtrack(index + 1, next_value)
            operators[operator] += 1

    backtrack(1, numbers[0])

    return maximum, minimum


numbers = [3, 4, 5]
operators = [1, 0, 1, 0]

maximum, minimum = operator_insertion(numbers, operators)

print(&quot;연산 결과의 최댓값:&quot;, maximum)
print(&quot;연산 결과의 최솟값:&quot;, minimum)


# =========================================================
# 2. N-Queen
# 같은 열과 대각선에 퀸이 배치되지 않도록 가지치기하며
# N개의 퀸을 배치하는 모든 경우의 수를 계산
# =========================================================
def count_n_queens(n):
    columns = [False] * n
    diagonal_down = [False] * (2 * n - 1)
    diagonal_up = [False] * (2 * n - 1)

    count = 0

    def backtrack(row):
        nonlocal count

        if row == n:
            count += 1
            return

        for col in range(n):
            down_index = row - col + n - 1
            up_index = row + col

            if columns[col]:
                continue

            if diagonal_down[down_index]:
                continue

            if diagonal_up[up_index]:
                continue

            columns[col] = True
            diagonal_down[down_index] = True
            diagonal_up[up_index] = True

            backtrack(row + 1)

            columns[col] = False
            diagonal_down[down_index] = False
            diagonal_up[up_index] = False

    backtrack(0)

    return count


print(&quot;8-Queen 배치 경우의 수:&quot;, count_n_queens(8))


# =========================================================
# 3. 부분 수열의 합
# 각 숫자를 선택하거나 선택하지 않는 모든 경우를 탐색하여
# 목표값을 만드는 부분 수열의 개수를 계산
# =========================================================
def count_subsequence_sum(numbers, target):
    count = 0

    def backtrack(index, current_sum, selected_count):
        nonlocal count

        if index == len(numbers):
            if selected_count &gt; 0 and current_sum == target:
                count += 1
            return

        # 현재 숫자를 선택
        backtrack(
            index + 1,
            current_sum + numbers[index],
            selected_count + 1
        )

        # 현재 숫자를 선택하지 않음
        backtrack(
            index + 1,
            current_sum,
            selected_count
        )

    backtrack(0, 0, 0)

    return count


numbers = [-7, -3, -2, 5, 8]
target = 0

print(
    &quot;목표 합을 만드는 부분 수열의 개수:&quot;,
    count_subsequence_sum(numbers, target)
)


# =========================================================
# 4. 연구소 안전 영역
# 빈칸 중 세 곳에 벽을 설치하는 모든 조합을 확인하고,
# 바이러스가 퍼진 뒤 남는 안전 영역의 최댓값 계산
# =========================================================
from collections import deque
from itertools import combinations


def maximum_safe_area(lab):
    rows = len(lab)
    cols = len(lab[0])

    empty_cells = []
    virus_cells = []

    for row in range(rows):
        for col in range(cols):
            if lab[row][col] == 0:
                empty_cells.append((row, col))
            elif lab[row][col] == 2:
                virus_cells.append((row, col))

    directions = [
        (-1, 0),
        (1, 0),
        (0, -1),
        (0, 1)
    ]

    maximum = 0

    for walls in combinations(empty_cells, 3):
        copied = [row[:] for row in lab]

        for row, col in walls:
            copied[row][col] = 1

        queue = deque(virus_cells)

        while queue:
            row, col = queue.popleft()

            for dr, dc in directions:
                next_row = row + dr
                next_col = col + dc

                if not (
                    0 &lt;= next_row &lt; rows
                    and 0 &lt;= next_col &lt; cols
                ):
                    continue

                if copied[next_row][next_col] != 0:
                    continue

                copied[next_row][next_col] = 2
                queue.append((next_row, next_col))

        safe_area = sum(
            copied[row][col] == 0
            for row in range(rows)
            for col in range(cols)
        )

        maximum = max(maximum, safe_area)

    return maximum


lab = [
    [2, 0, 0, 0, 1, 1, 0],
    [0, 0, 1, 0, 1, 2, 0],
    [0, 1, 1, 0, 1, 0, 0],
    [0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1],
    [0, 1, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 0, 0]
]

print(&quot;최대 안전 영역:&quot;, maximum_safe_area(lab))


# =========================================================
# 5. 스도쿠 풀이
# 빈칸에 가능한 숫자를 넣고 조건을 만족하지 않으면
# 이전 상태로 돌아가 다른 숫자를 선택
# =========================================================
def solve_sudoku(board):
    empty_cells = []

    rows = [set() for _ in range(9)]
    columns = [set() for _ in range(9)]
    boxes = [set() for _ in range(9)]

    for row in range(9):
        for col in range(9):
            value = board[row][col]

            if value == 0:
                empty_cells.append((row, col))
                continue

            rows[row].add(value)
            columns[col].add(value)
            boxes[(row // 3) * 3 + col // 3].add(value)

    def backtrack(index):
        if index == len(empty_cells):
            return True

        row, col = empty_cells[index]
        box_index = (row // 3) * 3 + col // 3

        for number in range(1, 10):
            if number in rows[row]:
                continue

            if number in columns[col]:
                continue

            if number in boxes[box_index]:
                continue

            board[row][col] = number
            rows[row].add(number)
            columns[col].add(number)
            boxes[box_index].add(number)

            if backtrack(index + 1):
                return True

            board[row][col] = 0
            rows[row].remove(number)
            columns[col].remove(number)
            boxes[box_index].remove(number)

        return False

    backtrack(0)

    return board


sudoku = [
    [0, 3, 5, 4, 6, 9, 2, 7, 8],
    [7, 8, 2, 1, 0, 5, 6, 0, 9],
    [0, 6, 0, 2, 7, 8, 1, 3, 5],
    [3, 2, 1, 0, 4, 6, 8, 9, 7],
    [8, 0, 4, 9, 1, 3, 5, 0, 6],
    [5, 9, 6, 8, 2, 0, 4, 1, 3],
    [9, 1, 7, 6, 5, 2, 0, 8, 0],
    [6, 0, 3, 7, 0, 1, 9, 5, 2],
    [2, 5, 8, 3, 9, 4, 7, 6, 0]
]

solved_sudoku = solve_sudoku(sudoku)

print(&quot;스도쿠 풀이 결과:&quot;)
for row in solved_sudoku:
    print(*row)


# =========================================================
# 6. 외판원 순회
# 한 도시에서 출발해 모든 도시를 한 번씩 방문하고
# 출발점으로 돌아오는 최소 비용을 백트래킹으로 탐색
# =========================================================
def travelling_salesman(costs):
    n = len(costs)
    visited = [False] * n
    minimum_cost = float(&quot;inf&quot;)

    visited[0] = True

    def backtrack(current, visited_count, total_cost):
        nonlocal minimum_cost

        # 현재 비용이 이미 최적값 이상이면 탐색 중단
        if total_cost &gt;= minimum_cost:
            return

        if visited_count == n:
            return_cost = costs[current][0]

            if return_cost != 0:
                minimum_cost = min(
                    minimum_cost,
                    total_cost + return_cost
                )
            return

        for next_city in range(1, n):
            if visited[next_city]:
                continue

            if costs[current][next_city] == 0:
                continue

            visited[next_city] = True

            backtrack(
                next_city,
                visited_count + 1,
                total_cost + costs[current][next_city]
            )

            visited[next_city] = False

    backtrack(0, 1, 0)

    return minimum_cost


costs = [
    [0, 10, 15, 20],
    [5, 0, 9, 10],
    [6, 13, 0, 12],
    [8, 8, 9, 0]
]

print(
    &quot;모든 도시를 순회하는 최소 비용:&quot;,
    travelling_salesman(costs)
)</code></pre>
<p>이번 주에는 코딩테스트 대비를 위해 완전탐색과 백트래킹 유형의 문제 풀이를 진행하였다. 완전탐색은 가능한 모든 경우를 빠짐없이 확인하여 정답을 구하는 방식이며, 백트래킹은 탐색 도중 현재 선택이 조건을 만족할 수 없다고 판단되면 이전 단계로 돌아가 다른 선택을 시도하는 방식이라는 점을 이해하였다.</p>
<p>완전탐색 문제를 해결할 때는 먼저 전체 경우의 수가 입력 범위 안에서 실제로 탐색 가능한 크기인지 판단해야 한다. 반복문, 순열, 조합, 부분집합, 비트마스크, 재귀 함수 등을 활용하여 모든 후보를 생성할 수 있지만, 입력의 크기가 커지면 경우의 수가 급격하게 증가하므로 시간 복잡도를 먼저 계산하는 것이 중요하다는 점을 학습하였다.</p>
<p>연산자 끼워 넣기 유형에서는 숫자의 순서는 유지하면서 주어진 연산자를 배치하는 모든 경우를 재귀적으로 탐색하였다. 각 단계에서 사용할 수 있는 연산자의 개수를 하나씩 줄이고, 탐색이 끝난 뒤 다시 복구하는 방식으로 같은 연산자 개수 정보를 재사용하였다. 이를 통해 별도의 연산자 순열을 모두 저장하지 않고도 모든 계산 결과를 확인할 수 있었다.</p>
<p>N-Queen 유형에서는 각 행마다 하나의 퀸을 배치하되, 같은 열과 대각선에 이미 퀸이 존재하는 경우 해당 선택을 즉시 제외하였다. 모든 칸에 퀸을 놓아본 뒤 마지막에 조건을 검사하는 것보다, 퀸을 배치하는 순간 열과 대각선 조건을 확인하는 것이 탐색 범위를 크게 줄일 수 있다는 점을 이해하였다.</p>
<p>부분 수열의 합 유형에서는 각 숫자를 선택하는 경우와 선택하지 않는 경우로 나누어 모든 부분집합을 탐색하였다. 원소가 N개라면 가능한 선택 상태가 2의 N제곱개가 되며, 재귀 함수의 각 단계가 하나의 원소에 대한 선택 여부를 의미한다는 점을 학습하였다. 또한 아무 원소도 선택하지 않은 공집합을 정답에서 제외해야 하는 경우 선택한 원소의 개수를 별도로 관리해야 한다는 점도 배웠다.</p>
<p>연구소 안전 영역 유형에서는 빈칸 가운데 세 곳을 선택하여 벽을 세우는 모든 조합을 생성하고, 각 조합마다 BFS를 실행하여 바이러스의 확산 결과를 확인하였다. 이 문제를 통해 완전탐색은 다른 알고리즘과 결합하여 사용할 수 있으며, 후보 상태는 조합으로 생성하고 각 상태의 결과는 그래프 탐색으로 평가할 수 있다는 점을 이해하였다.</p>
<p>스도쿠 유형에서는 빈칸에 들어갈 수 있는 숫자를 하나씩 넣고, 행과 열, 3×3 구역의 조건을 만족하지 못하면 이전 선택을 취소하였다. 숫자를 넣은 뒤 다음 빈칸으로 이동하고, 정답을 찾지 못하면 해당 숫자를 제거하여 상태를 원래대로 복구하는 백트래킹의 기본 구조를 연습하였다.</p>
<p>스도쿠의 각 빈칸에서 1부터 9까지 모든 숫자를 단순하게 시도할 수도 있지만, 이미 행과 열, 구역에 존재하는 숫자를 집합으로 관리하면 불가능한 후보를 빠르게 제외할 수 있었다. 이를 통해 가지치기의 효율은 조건 검사에 필요한 정보를 어떤 자료구조로 관리하는지에 따라서도 달라질 수 있다는 점을 알 수 있었다.</p>
<p>외판원 순회 유형에서는 현재 도시에서 아직 방문하지 않은 도시로 이동하는 모든 순서를 탐색하고, 모든 도시를 방문한 뒤 출발 도시로 돌아오는 비용을 계산하였다. 방문 배열을 통해 같은 도시의 중복 방문을 방지하고, 현재까지의 비용이 이미 구한 최솟값보다 크거나 같으면 이후 탐색을 중단하는 방식으로 가지치기를 적용하였다.</p>
<p>순열 유형에서는 선택 순서에 따라 결과가 달라지므로 방문 배열을 이용하여 아직 선택하지 않은 원소를 하나씩 추가해야 한다는 점을 학습하였다. 조합 유형에서는 선택 순서가 결과에 영향을 주지 않으므로 다음 탐색을 현재 인덱스 이후부터 시작하여 동일한 원소 집합이 다른 순서로 중복 생성되는 것을 방지해야 한다는 차이를 이해하였다.</p>
<p>백트래킹에서는 선택, 재귀 호출, 상태 복구의 세 단계가 정확하게 이루어져야 한다는 점을 학습하였다. 선택 과정에서 방문 배열이나 개수, 합계 등을 변경했다면 재귀 호출이 끝난 뒤 반드시 이전 상태로 돌려놓아야 다른 탐색 경로가 영향을 받지 않는다. 상태를 제대로 복구하지 않으면 아직 선택하지 않은 후보가 이미 사용된 것으로 처리되는 오류가 발생할 수 있다는 점을 알 수 있었다.</p>
<p>가지치기에서는 현재 상태가 이미 문제의 조건을 위반했거나, 이후 어떤 선택을 하더라도 기존의 최적 결과보다 좋아질 수 없는 경우 탐색을 중단하였다. N-Queen에서는 열과 대각선의 충돌 여부를 검사했고, 외판원 순회에서는 현재 누적 비용과 기존 최솟값을 비교하였다. 문제마다 가지치기의 기준은 다르지만, 현재 상태만으로 이후 탐색의 필요성을 판단한다는 공통점을 이해하였다.</p>
<p>완전탐색과 백트래킹은 입력 크기가 작은 문제에서 강력하게 활용할 수 있지만, 모든 경우를 무조건 탐색하면 시간 제한을 초과할 수 있다는 점도 학습하였다. 원소가 N개인 순열은 N팩토리얼, 부분집합은 2의 N제곱, 중복 선택은 선택지 수의 깊이제곱만큼 경우의 수가 증가하므로 문제의 제한을 보고 탐색 가능 여부를 먼저 판단해야 한다.</p>
<p>이번 학습을 통해 완전탐색은 정답 후보를 빠짐없이 만드는 것이 핵심이고, 백트래킹은 후보를 만드는 과정에서 불필요한 탐색을 줄이는 것이 핵심이라는 점을 이해하였다. 두 방식은 서로 완전히 다른 알고리즘이라기보다, 완전탐색의 구조에 조건 검사와 가지치기를 추가하여 효율을 높인 관계라는 점을 알 수 있었다.</p>
<p>또한 문제를 해결할 때 단순히 재귀 함수를 작성하는 것보다 현재 단계에서 무엇을 선택하는지, 종료 조건은 무엇인지, 어떤 상태를 저장하고 복구해야 하는지, 어느 시점에서 가지치기를 할 수 있는지를 먼저 정의해야 한다는 점을 배웠다. 완전탐색과 백트래킹 문제는 코드의 형태를 암기하기보다 탐색 트리의 각 깊이와 선택 상태를 명확하게 설계하는 것이 중요하다는 점을 이해하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 6회차 (계획)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D-qu3gfo52</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D-qu3gfo52</guid>
            <pubDate>Mon, 03 Aug 2026 08:49:02 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득">1. 정보처리기사 취득</h2>
<p>   데이터베이스 구축 과목에서 논리 데이터베이스 설계와 물리 데이터베이스 설계에 대한 학습 진행</p>
<p>관계 데이터베이스 모델
데이터를 행과 열로 구성된 테이블 형태로 표현하고, 릴레이션·튜플·속성·도메인 등 관계 데이터베이스의 기본 구성 요소 이해</p>
<p>관계 데이터베이스 제약조건
데이터의 정확성과 일관성을 유지하기 위해 개체 무결성, 참조 무결성, 도메인 무결성 등의 제약조건 적용</p>
<p>관계 대수
셀렉션, 프로젝션, 조인, 합집합, 교집합, 차집합 등의 연산을 활용하여 관계형 데이터에서 필요한 정보 추출</p>
<p>데이터 모델링
현실 세계의 업무와 데이터를 개체, 속성, 관계로 분석하여 데이터베이스 구조로 표현</p>
<p>개념적 데이터 모델링
사용자의 요구사항을 바탕으로 주요 개체와 관계를 정의하고 ER 다이어그램을 통해 전체 데이터 구조 표현</p>
<p>논리적 데이터 모델링
개념적 데이터 모델을 관계형 데이터베이스 구조로 변환하고 테이블, 속성, 기본키 및 외래키 설계</p>
<p>정규화
데이터의 중복을 줄이고 삽입·삭제·갱신 이상 현상을 방지하기 위해 테이블을 적절한 구조로 분해</p>
<p>물리 요소 조사 및 분석
데이터의 양, 처리 빈도, 조회 조건, 저장 공간, 응답 시간 등 실제 데이터베이스 운영 환경과 성능 요구사항 분석</p>
<p>데이터 저장 구조 설계
테이블과 인덱스가 저장될 공간을 구성하고 데이터의 특성에 따라 적절한 저장 방식과 접근 경로 결정</p>
<p>DB 물리 속성 설계
컬럼의 데이터 타입과 길이, 기본값, NULL 허용 여부 등 실제 데이터베이스에 적용할 세부 속성 정의</p>
<p>인덱스 설계
검색과 정렬 속도를 향상하기 위해 조회 빈도와 선택도가 높은 컬럼을 기준으로 인덱스 구성</p>
<p>파티션 설계
대용량 테이블을 범위, 목록, 해시 등의 기준으로 분할하여 데이터 관리와 조회 성능 개선</p>
<p>데이터베이스 무결성
데이터가 정해진 규칙과 관계를 유지하도록 제약조건을 설정하여 잘못된 데이터의 입력과 변경 방지</p>
<p>후보키와 기본키
튜플을 유일하게 식별할 수 있는 후보키 중 대표 키를 기본키로 선정하고 중복값과 NULL 입력 제한</p>
<p>대체키와 슈퍼키
기본키로 선택되지 않은 후보키를 대체키로 구분하고, 튜플을 식별할 수 있는 속성의 집합을 슈퍼키로 이해</p>
<p>외래키
다른 테이블의 기본키를 참조하여 테이블 사이의 관계를 표현하고 참조 무결성 유지</p>
<p>DB 반정규화
조회 성능을 향상하기 위해 정규화된 테이블을 의도적으로 통합하거나 중복 데이터를 추가하는 방법 학습</p>
<p>테이블 반정규화
빈번한 조인으로 성능이 저하되는 경우 테이블 병합, 분할 또는 중복 테이블 추가를 통해 조회 과정 단순화</p>
<p>컬럼 반정규화
자주 계산하거나 조회하는 값을 중복 컬럼 또는 파생 컬럼으로 저장하여 반복 연산과 조인 횟수 감소</p>
<p>관계 반정규화
테이블 간 접근 경로를 단축하기 위해 중복 관계를 추가하거나 필요한 외래키를 여러 위치에 배치</p>
<p>반정규화 적용 시 고려사항
조회 성능은 높일 수 있지만 데이터 중복과 갱신 비용이 증가하므로 정합성 유지 방안과 적용 효과를 함께 검토</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<p>   코딩테스트 문제 풀이를 진행 &lt;완전탐색·백트래킹&gt; 유형</p>
<p>완전탐색 기본 구조
가능한 모든 경우를 빠짐없이 확인하여 문제의 조건을 만족하는 정답 탐색</p>
<p>반복문 완전탐색
탐색 범위가 작고 선택 단계가 정해진 문제에서 중첩 반복문을 활용하여 모든 조합 확인</p>
<p>재귀 완전탐색
선택 과정을 재귀 함수로 표현하고 현재 단계에서 가능한 모든 선택지를 차례대로 탐색</p>
<p>순열 탐색
서로 다른 원소의 배치 순서를 모두 생성하여 순서에 따라 결과가 달라지는 문제 해결</p>
<p>조합 탐색
원소의 순서를 고려하지 않고 정해진 개수만큼 선택하는 모든 경우 확인</p>
<p>부분집합 탐색
각 원소를 선택하는 경우와 선택하지 않는 경우로 나누어 가능한 모든 부분집합 생성</p>
<p>비트마스크 완전탐색
각 원소의 선택 여부를 이진수의 비트로 표현하여 부분집합과 상태 조합을 효율적으로 순회</p>
<p>백트래킹 기본 구조
가능한 선택을 진행하다가 조건을 만족할 수 없는 상태가 되면 이전 단계로 돌아가 다른 선택 탐색</p>
<p>가지치기
현재까지의 선택만으로 정답이 될 가능성이 없거나 기존 최적값보다 불리한 경우 이후 탐색 중단</p>
<p>방문 배열 활용
순열, 경로, 그래프 문제에서 이미 선택하거나 방문한 원소를 표시하여 중복 선택 방지</p>
<p>N과 M 유형
숫자의 선택 순서와 중복 허용 여부에 따라 순열·조합·중복 순열·중복 조합 생성</p>
<p>N-Queen 유형
같은 행, 열, 대각선에 퀸을 배치할 수 없다는 조건을 검사하며 가능한 배치 탐색</p>
<p>스도쿠 유형
빈칸에 들어갈 수 있는 숫자를 행, 열, 구역 조건에 따라 확인하고 불가능한 경우 이전 선택으로 복귀</p>
<p>연산자 끼워 넣기
주어진 숫자 사이에 연산자를 배치하는 모든 경우를 탐색하여 결과의 최댓값과 최솟값 계산</p>
<p>부분 수열의 합
각 숫자의 선택 여부를 결정하며 목표값을 만드는 부분 수열의 개수나 존재 여부 확인</p>
<p>경로 탐색
현재 위치에서 이동 가능한 모든 방향을 확인하고 방문 처리와 복구를 반복하며 목적지까지의 경로 탐색</p>
<p>최적해 탐색
모든 후보를 비교하되 현재 결과와 남은 선택을 이용하여 더 나은 결과가 나올 수 없는 경우 탐색 중단</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 5회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Mon, 27 Jul 2026 08:15:26 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득-준비">1. 정보처리기사 취득 준비</h2>
<p>정보시스템 구축 관리 과목에서는 소프트웨어 개발 방법론 활용, IT 프로젝트 정보 시스템 구축 관리, 소프트웨어 개발 보안 구축, 시스템 보안 구축에 관한 내용을 학습하였다. 소프트웨어를 개발하고 운영하는 과정에서 필요한 관리 절차와 보안 기술을 단순히 암기하는 것이 아니라, 실제 프로젝트에서 각 기술이 어떤 역할을 하는지를 중심으로 정리하였다.</p>
<p>소프트웨어 개발 방법론 활용에서는 소프트웨어 생명주기와 주요 개발 방법론의 특징을 학습하였다. 폭포수 모형은 각 개발 단계를 순차적으로 진행하기 때문에 요구사항이 명확한 프로젝트에 적합하며, 프로토타이핑 모형은 시제품을 먼저 제작하여 사용자의 요구사항을 구체화하는 데 활용된다는 점을 이해하였다. 나선형 모형은 개발 과정을 반복하면서 위험을 분석하고, 애자일 방법론은 짧은 개발 주기를 반복하며 변화하는 요구사항에 유연하게 대응하는 방식이라는 점을 배웠다.</p>
<p>개발 방법론 테일러링에서는 조직의 표준 개발 절차를 모든 프로젝트에 동일하게 적용하는 것이 아니라, 프로젝트의 규모, 복잡도, 기술 환경, 참여 인력에 맞게 조정해야 한다는 점을 학습하였다. 불필요한 절차는 줄이되 품질과 관리에 필요한 핵심 활동은 유지해야 하며, 테일러링 기준과 결과를 문서화해야 한다는 점을 이해하였다.</p>
<p>소프트웨어 비용과 일정 산정에서는 LOC, 기능점수, COCOMO 등의 기법을 활용하여 개발 규모와 비용을 예측하는 방법을 학습하였다. 또한 WBS를 통해 전체 작업을 세부 단위로 분해하고, PERT와 CPM을 활용하여 작업 간 선후 관계와 임계 경로를 파악하는 방법을 정리하였다. 프로젝트 일정이 지연되지 않도록 하려면 임계 경로에 포함된 작업을 우선적으로 관리해야 한다는 점을 알 수 있었다.</p>
<p>IT 프로젝트 정보 시스템 구축 관리에서는 프로젝트의 범위, 일정, 비용, 품질, 인력, 의사소통, 위험 요소를 종합적으로 관리하는 방법을 학습하였다. 프로젝트 목표를 명확하게 설정한 뒤 세부 작업과 담당자, 완료 기한을 정하고 실제 진행 상황을 계획과 비교해야 한다는 점을 이해하였다.</p>
<p>프로젝트 범위 관리에서는 요구사항을 기준으로 수행해야 할 작업과 제외할 작업을 구분하는 방법을 학습하였다. 프로젝트 도중 요구사항이 무분별하게 추가되면 일정과 비용이 증가할 수 있으므로, 변경 요청의 필요성과 영향도를 검토한 뒤 승인 절차에 따라 반영해야 한다는 점을 배웠다.</p>
<p>프로젝트 위험 관리에서는 발생할 가능성이 있는 기술적·일정적·비용적 위험을 사전에 식별하고, 발생 가능성과 영향도를 기준으로 우선순위를 정하는 방법을 학습하였다. 위험을 회피하거나 줄이는 대응 방안뿐만 아니라, 위험이 실제로 발생했을 때 적용할 비상 계획도 준비해야 한다는 점을 이해하였다.</p>
<p>소프트웨어 개발 보안 구축에서는 소프트웨어의 설계와 구현 단계부터 보안 취약점을 예방하는 방법을 학습하였다. 개발이 완료된 뒤 보안 문제를 수정하는 것보다 초기 단계부터 보안 요구사항을 반영하는 것이 비용과 위험을 줄이는 데 효과적이라는 점을 이해하였다.</p>
<p>시큐어 코딩에서는 SQL 삽입, 크로스사이트 스크립팅, 경로 조작, 버퍼 오버플로 등 주요 취약점의 발생 원인을 학습하였다. 외부에서 입력되는 값은 신뢰하지 않고 형식과 범위를 검사해야 하며, 데이터베이스 질의에는 문자열을 직접 연결하기보다 매개변수화된 질의를 사용해야 한다는 점을 배웠다.</p>
<p>인증과 접근 통제에서는 사용자가 누구인지 확인하는 인증과, 인증된 사용자에게 허용된 기능만 제공하는 인가의 차이를 학습하였다. 사용자에게 필요 이상의 권한을 부여하지 않는 최소 권한 원칙과 역할에 따라 권한을 부여하는 역할 기반 접근 통제의 중요성을 이해하였다.</p>
<p>시스템 보안 구축에서는 운영체제, 서버, 네트워크, 데이터베이스를 외부 공격과 내부 위협으로부터 보호하는 방법을 학습하였다. 방화벽은 허용된 통신과 차단할 통신을 구분하고, 침입 탐지 시스템은 공격 징후를 탐지하며, 침입 방지 시스템은 탐지한 공격을 능동적으로 차단한다는 차이를 정리하였다.</p>
<p>악성코드와 네트워크 공격 유형에서는 바이러스, 웜, 트로이 목마, 랜섬웨어의 특징과 서비스 거부 공격, 스니핑, 스푸핑 등의 공격 방식을 학습하였다. 각 공격의 명칭만 암기하기보다 공격자가 어떤 방식으로 시스템이나 통신을 방해하고 정보를 탈취하는지를 중심으로 이해하였다.</p>
<p>보안 취약점 점검과 사고 대응에서는 불필요한 계정과 서비스를 제거하고, 보안 패치를 적용하며, 시스템 로그를 정기적으로 분석하는 방법을 학습하였다. 보안 사고가 발생하면 탐지, 피해 범위 분석, 격리, 복구, 원인 분석, 재발 방지의 순서로 대응해야 한다는 점을 배웠다.</p>
<p>이번 학습을 통해 정보 시스템 구축 관리는 개발 기술만을 다루는 과목이 아니라 프로젝트의 계획, 비용, 일정, 품질, 보안을 함께 관리하는 과목이라는 점을 이해하였다. 또한 개발 방법론과 프로젝트 관리, 소프트웨어 보안, 시스템 보안은 각각 독립된 내용이 아니라 안전하고 안정적인 시스템을 구축하기 위해 서로 연결되어 있다는 점을 알 수 있었다.</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<pre><code class="language-python"># =========================================================
# 1. 0/1 배낭 문제
# 각 물건을 한 번만 선택할 수 있을 때,
# 제한된 무게 안에서 얻을 수 있는 최대 가치를 계산
# =========================================================
def knapsack(capacity, items):
    # dp[w] = 무게 한도가 w일 때 얻을 수 있는 최대 가치
    dp = [0] * (capacity + 1)

    for weight, value in items:
        # 같은 물건을 중복 선택하지 않도록 뒤에서부터 갱신
        for current_weight in range(capacity, weight - 1, -1):
            dp[current_weight] = max(
                dp[current_weight],
                dp[current_weight - weight] + value
            )

    return dp[capacity]


items = [
    (3, 6),
    (4, 8),
    (5, 12),
    (6, 13)
]

print(&quot;배낭에 담을 수 있는 최대 가치:&quot;, knapsack(10, items))


# =========================================================
# 2. 최장 증가 부분 수열
# 수열의 순서를 유지하면서 값이 계속 증가하는
# 가장 긴 부분 수열의 길이를 계산
# =========================================================
def longest_increasing_subsequence(numbers):
    # dp[i] = i번째 숫자를 마지막으로 하는 LIS의 최대 길이
    dp = [1] * len(numbers)

    for current in range(len(numbers)):
        for previous in range(current):
            if numbers[previous] &lt; numbers[current]:
                dp[current] = max(
                    dp[current],
                    dp[previous] + 1
                )

    return max(dp)


numbers = [10, 20, 10, 30, 20, 50]
print(
    &quot;최장 증가 부분 수열의 길이:&quot;,
    longest_increasing_subsequence(numbers)
)


# =========================================================
# 3. 최장 공통 부분 수열
# 두 문자열의 순서를 유지하면서 공통으로 나타나는
# 가장 긴 부분 수열의 길이를 계산
# =========================================================
def longest_common_subsequence(first, second):
    rows = len(first) + 1
    cols = len(second) + 1

    # dp[i][j] = first의 i개 문자와 second의 j개 문자를
    # 비교했을 때의 최장 공통 부분 수열 길이
    dp = [[0] * cols for _ in range(rows)]

    for i in range(1, rows):
        for j in range(1, cols):
            if first[i - 1] == second[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
                dp[i][j] = max(
                    dp[i - 1][j],
                    dp[i][j - 1]
                )

    return dp[-1][-1]


first = &quot;ACAYKP&quot;
second = &quot;CAPCAK&quot;

print(
    &quot;최장 공통 부분 수열의 길이:&quot;,
    longest_common_subsequence(first, second)
)


# =========================================================
# 4. 동전 교환
# 주어진 동전을 반복해서 사용할 수 있을 때,
# 목표 금액을 만드는 데 필요한 최소 동전 수를 계산
# =========================================================
def minimum_coins(coins, target):
    infinity = target + 1

    # dp[amount] = amount를 만드는 최소 동전 수
    dp = [infinity] * (target + 1)
    dp[0] = 0

    for amount in range(1, target + 1):
        for coin in coins:
            if coin &lt;= amount:
                dp[amount] = min(
                    dp[amount],
                    dp[amount - coin] + 1
                )

    if dp[target] == infinity:
        return -1

    return dp[target]


coins = [1, 3, 4]
target = 6

print(
    &quot;목표 금액을 만드는 최소 동전 수:&quot;,
    minimum_coins(coins, target)
)


# =========================================================
# 5. 격자 최소 비용 경로
# 왼쪽 위에서 오른쪽 아래까지 이동하면서
# 방문한 칸의 비용 합이 최소가 되는 경로 계산
# 이동 방향: 오른쪽 또는 아래
# =========================================================
def minimum_grid_cost(grid):
    rows = len(grid)
    cols = len(grid[0])

    # dp[row][col] = 해당 칸까지 이동하는 최소 누적 비용
    dp = [[0] * cols for _ in range(rows)]
    dp[0][0] = grid[0][0]

    for col in range(1, cols):
        dp[0][col] = dp[0][col - 1] + grid[0][col]

    for row in range(1, rows):
        dp[row][0] = dp[row - 1][0] + grid[row][0]

    for row in range(1, rows):
        for col in range(1, cols):
            dp[row][col] = min(
                dp[row - 1][col],
                dp[row][col - 1]
            ) + grid[row][col]

    return dp[-1][-1]


grid = [
    [5, 3, 2, 1],
    [1, 9, 1, 3],
    [2, 1, 4, 2],
    [3, 2, 1, 1]
]

print(
    &quot;격자에서의 최소 이동 비용:&quot;,
    minimum_grid_cost(grid)
)


# =========================================================
# 6. 파일 합치기 - 구간 DP
# 연속된 파일들을 하나로 합칠 때 발생하는
# 전체 비용의 최솟값을 계산
# =========================================================
def minimum_merge_cost(files):
    n = len(files)

    # prefix[i] = 0번부터 i-1번까지 파일 크기의 누적합
    prefix = [0] * (n + 1)

    for index in range(n):
        prefix[index + 1] = prefix[index] + files[index]

    # dp[start][end] = start부터 end까지 파일을 합치는 최소 비용
    dp = [[0] * n for _ in range(n)]

    for length in range(2, n + 1):
        for start in range(n - length + 1):
            end = start + length - 1
            dp[start][end] = float(&quot;inf&quot;)

            total_size = prefix[end + 1] - prefix[start]

            for middle in range(start, end):
                merge_cost = (
                    dp[start][middle]
                    + dp[middle + 1][end]
                    + total_size
                )

                dp[start][end] = min(
                    dp[start][end],
                    merge_cost
                )

    return dp[0][n - 1]


files = [40, 30, 30, 50]
print(
    &quot;파일을 모두 합치는 최소 비용:&quot;,
    minimum_merge_cost(files)
)


# =========================================================
# 7. 연속된 수의 최대 합
# 현재 위치에서 새로운 부분 수열을 시작할지,
# 이전 수열을 이어갈지 판단하여 최대 합 계산
# =========================================================
def maximum_subarray_sum(numbers):
    # current_sum = 현재 위치에서 끝나는 연속 부분 수열의 최대 합
    current_sum = numbers[0]
    maximum_sum = numbers[0]

    for number in numbers[1:]:
        current_sum = max(
            number,
            current_sum + number
        )

        maximum_sum = max(
            maximum_sum,
            current_sum
        )

    return maximum_sum


numbers = [-2, 1, -3, 4, -1, 2, 1, -5, 4]

print(
    &quot;연속된 부분 수열의 최대 합:&quot;,
    maximum_subarray_sum(numbers)
)</code></pre>
<p>이번 주에는 코딩테스트 대비를 위해 다이나믹 프로그래밍 유형의 문제 풀이를 진행하였다. 다이나믹 프로그래밍은 하나의 큰 문제를 여러 개의 작은 문제로 나누고, 작은 문제의 계산 결과를 저장하여 같은 계산이 반복되는 것을 줄이는 방식이라는 점을 이해하였다.</p>
<p>다이나믹 프로그래밍 문제를 해결할 때는 먼저 어떤 값을 하나의 상태로 정의할 것인지 결정해야 한다. 그다음 현재 상태의 정답이 이전 상태의 결과와 어떤 관계를 가지는지 점화식으로 표현하고, 가장 작은 문제에 해당하는 초기값을 설정해야 한다는 점을 학습하였다.</p>
<p>0/1 배낭 문제에서는 제한된 무게 안에서 선택한 물건의 가치 합을 최대로 만드는 방법을 학습하였다. 각 물건을 한 번만 선택할 수 있으므로 1차원 DP 배열을 뒤에서부터 갱신해야 같은 물건이 한 번의 반복에서 여러 차례 사용되는 것을 방지할 수 있다는 점을 이해하였다.</p>
<p>최장 증가 부분 수열 유형에서는 각 원소를 마지막 값으로 하는 증가 부분 수열의 최대 길이를 저장하였다. 현재 원소보다 앞에 있으면서 값이 작은 원소들을 확인하고, 해당 원소까지의 최장 길이에 1을 더하는 방식으로 점화식을 구성하였다.</p>
<p>최장 공통 부분 수열 유형에서는 두 문자열의 각 위치까지 비교했을 때 만들 수 있는 공통 부분 수열의 최대 길이를 2차원 배열에 저장하였다. 두 문자가 같으면 대각선 위의 결과에 1을 더하고, 다르면 위쪽과 왼쪽 결과 중 큰 값을 선택하는 방식으로 문제를 해결하였다.</p>
<p>동전 교환 유형에서는 특정 금액을 만드는 데 필요한 최소 동전 수를 상태로 정의하였다. 현재 금액에서 각 동전의 금액을 뺀 이전 상태를 확인하고, 해당 상태에 동전 하나를 추가하는 방식으로 최소값을 갱신하였다. 만들 수 없는 금액을 구분하기 위해 충분히 큰 초기값을 설정해야 한다는 점도 학습하였다.</p>
<p>격자 경로 유형에서는 각 칸까지 이동하는 데 필요한 최소 누적 비용을 저장하였다. 현재 칸에 도달하려면 위쪽 칸이나 왼쪽 칸에서 이동해야 하므로 두 상태 중 비용이 더 작은 값을 선택한 뒤 현재 칸의 비용을 더하는 방식으로 점화식을 구성하였다.</p>
<p>파일 합치기 유형에서는 연속된 구간을 나누어 계산하는 구간 DP를 학습하였다. 하나의 구간을 여러 위치에서 두 부분으로 나누고, 왼쪽 구간의 최소 비용과 오른쪽 구간의 최소 비용에 전체 파일 크기를 더한 값 중 최솟값을 선택하였다. 구간의 길이가 짧은 경우부터 계산해야 더 긴 구간을 구할 때 이전 결과를 활용할 수 있다는 점을 이해하였다.</p>
<p>연속 부분 수열의 최대 합 유형에서는 현재 숫자부터 새로운 수열을 시작하는 경우와 이전 연속 수열에 현재 숫자를 추가하는 경우를 비교하였다. 이전 결과가 오히려 현재 합을 감소시키면 현재 숫자부터 다시 시작해야 한다는 점을 이용하여 별도의 2차원 배열 없이도 문제를 해결하였다.</p>
<p>다이나믹 프로그래밍은 메모이제이션을 사용하는 하향식 방식과 반복문으로 작은 문제부터 계산하는 상향식 방식으로 구현할 수 있다는 점도 학습하였다. 하향식 방식은 점화식을 코드로 옮기기 쉽지만 재귀 호출이 많아질 수 있고, 상향식 방식은 계산 순서를 명확하게 설계해야 하지만 함수 호출에 따른 부담을 줄일 수 있다는 차이가 있었다.</p>
<p>이번 학습을 통해 다이나믹 프로그래밍 문제에서는 단순히 DP 배열을 만드는 것이 중요한 것이 아니라, 배열의 각 칸이 어떤 의미를 가지는지 정확하게 정의하는 것이 가장 중요하다는 점을 알 수 있었다. 상태의 의미가 명확해야 초기값과 점화식, 계산 순서를 올바르게 설정할 수 있었다.</p>
<p>또한 입력값만 보고 바로 점화식을 작성하기보다 완전 탐색으로 모든 경우를 계산한다면 어떤 부분 문제가 반복되는지 먼저 확인하는 과정이 필요하다는 점을 이해하였다. 반복되는 문제의 결과를 저장하고 재사용할 수 있으며, 현재 문제의 최적해가 이전 문제의 최적해로 구성된다면 다이나믹 프로그래밍을 적용할 수 있다는 점을 배웠다.</p>
<p>같은 다이나믹 프로그래밍 유형이라도 문제에 따라 1차원 배열, 2차원 배열, 구간 배열 등 상태를 저장하는 구조가 달라질 수 있다는 점도 알 수 있었다. 따라서 풀이 코드를 암기하기보다 상태 정의, 초기값 설정, 점화식 구성, 계산 순서 결정의 네 단계를 기준으로 문제를 분석하는 연습이 필요하다는 점을 이해하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 5회차 (계획)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Mon, 27 Jul 2026 08:13:39 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득">1. 정보처리기사 취득</h2>
<p>   정보시스템 구축 관리 과목에서 소프트웨어 개발 방법론, IT 프로젝트 관리, 소프트웨어 개발 보안 및 시스템 보안에 대한 학습 진행</p>
<p>소프트웨어 개발 방법론 활용
소프트웨어 생명주기의 단계와 폭포수·프로토타이핑·나선형·애자일 방법론의 특징을 비교하고, 프로젝트의 규모와 요구사항 변화 가능성에 따라 적절한 개발 방법론을 선택</p>
<p>소프트웨어 개발 표준 및 테일러링
조직에서 사용하는 개발 표준과 절차를 프로젝트의 특성에 맞게 조정하고, 불필요한 절차는 줄이면서 품질과 일관성을 유지하는 방법 학습</p>
<p>소프트웨어 비용 산정
LOC, 기능점수, COCOMO 등의 산정 기법을 활용하여 소프트웨어의 개발 규모, 투입 인력, 개발 기간 및 비용을 예측</p>
<p>소프트웨어 개발 일정 관리
작업 간 선후 관계를 파악하고 WBS, PERT, CPM 등을 활용하여 프로젝트 일정과 임계 경로를 관리</p>
<p>IT 프로젝트 통합 관리
프로젝트의 목표, 범위, 일정, 비용, 품질, 인력 등을 종합적으로 관리하고 각 관리 영역의 변경 사항을 통제</p>
<p>프로젝트 범위 및 일정 관리
요구사항을 기준으로 프로젝트의 작업 범위를 정의하고, 세부 작업을 분해하여 담당자와 완료 기한을 설정</p>
<p>프로젝트 비용 및 품질 관리
예산과 실제 지출을 비교하여 비용을 통제하고, 품질 기준을 수립하여 결과물이 요구사항을 충족하는지 점검</p>
<p>프로젝트 위험 관리
발생 가능한 기술적·일정적·인적 위험을 사전에 식별하고, 발생 가능성과 영향도를 분석하여 대응 계획 수립</p>
<p>소프트웨어 개발 보안 설계
개발 초기 단계부터 보안 요구사항을 반영하고, 사용자 인증·권한 관리·데이터 보호·입력값 검증 등 보안 기능 설계</p>
<p>시큐어 코딩
SQL 삽입, 경로 조작, 크로스사이트 스크립팅, 버퍼 오버플로 등의 취약점이 발생하는 원인을 이해하고 안전한 코딩 방법 적용</p>
<p>입력 데이터 검증 및 표현
외부에서 전달되는 데이터의 형식과 범위를 검사하고, 비정상적인 입력값이 명령어나 프로그램 코드로 실행되지 않도록 처리</p>
<p>인증 및 접근 통제
사용자의 신원을 확인한 후 역할과 권한에 따라 시스템 자원에 대한 접근을 허용하거나 제한</p>
<p>암호화 기술 활용
평문 데이터를 암호문으로 변환하여 보호하고, 대칭키·비대칭키·해시 함수 및 전자서명의 특징과 활용 방법 학습</p>
<p>네트워크 보안 구축
방화벽, 침입 탐지 시스템, 침입 방지 시스템, 가상 사설망 등을 활용하여 외부 공격과 비인가 접근 차단</p>
<p>시스템 접근 통제
사용자 계정과 권한을 관리하고 식별·인증·인가·감사 과정을 통해 시스템 자원에 대한 접근 통제</p>
<p>악성코드 및 공격 대응
바이러스, 웜, 트로이 목마, 랜섬웨어 등 악성코드의 특징과 서비스 거부 공격, 스니핑, 스푸핑 등의 공격 기법 이해</p>
<p>보안 취약점 점검
운영체제, 서버, 네트워크 장비의 설정 상태를 점검하고 불필요한 서비스 제거, 보안 패치 적용 및 로그 분석 수행</p>
<p>보안 사고 대응
보안 사고 발생 시 사고 탐지, 피해 범위 분석, 시스템 복구, 원인 제거 및 재발 방지 대책 수립</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<p>   코딩테스트 문제 풀이를 진행 <Dynamic Programming> 유형</p>
<p>다이나믹 프로그래밍 기본 구조
큰 문제를 여러 개의 작은 문제로 나누고, 이미 계산한 결과를 저장하여 중복 연산 제거</p>
<p>점화식 설계
현재 상태의 정답을 이전 상태의 결과로 표현하고, 초기값과 상태 전이 조건 설정</p>
<p>메모이제이션
재귀 함수의 계산 결과를 저장한 뒤 같은 상태가 다시 호출되면 저장된 결과를 반환하는 하향식 풀이</p>
<p>보텀업 방식
가장 작은 문제부터 순서대로 계산하여 최종 문제의 답을 구하는 상향식 풀이</p>
<p>1차원 DP
하나의 상태값을 기준으로 최소 비용, 최대 점수, 경우의 수 등을 배열에 저장</p>
<p>2차원 DP
두 개의 상태 조건을 함께 관리하며 문자열 비교, 격자 이동, 배낭 문제 등의 정답 계산</p>
<p>피보나치·계단 오르기
이전 단계의 결과를 조합하여 현재 단계까지 도달하는 방법의 수 또는 최적값 계산</p>
<p>동전 교환
주어진 동전을 조합하여 목표 금액을 만드는 최소 동전 수 또는 전체 경우의 수 계산</p>
<p>배낭 문제
제한된 무게 안에서 물건을 선택하여 얻을 수 있는 가치의 최댓값 계산</p>
<p>최장 증가 부분 수열
수열의 순서를 유지하면서 값이 증가하는 가장 긴 부분 수열의 길이 탐색</p>
<p>최장 공통 부분 수열
두 문자열의 순서를 유지하며 공통으로 나타나는 가장 긴 부분 수열 계산</p>
<p>격자 경로 탐색
이전 위치에서 현재 위치로 이동하는 경우를 누적하여 목적지까지의 경로 수나 최소 비용 계산</p>
<p>구간 DP
연속된 구간을 여러 부분으로 나누고 구간의 길이를 늘려가며 최적의 결합 순서 계산</p>
<p>트리 DP
부모·자식 관계를 기준으로 각 노드의 선택 여부와 하위 트리의 결과를 결합</p>
<p>비트마스크 DP
집합의 선택 상태를 비트로 표현하여 방문한 항목과 남은 항목에 따른 최적값 계산</p>
<p>최적화 DP
모든 경우를 단순히 탐색하지 않고 이전 상태 중 최솟값이나 최댓값만 유지하여 시간과 메모리 사용량 개선</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 4회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-4%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-4%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Mon, 20 Jul 2026 09:52:15 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득-준비">1. 정보처리기사 취득 준비</h2>
<p>프로그래밍 언어 활용 과목에서는 서버 프로그램 구현, 프로그래밍 언어 활용, 응용 소프트웨어 기초 기술 활용에 관한 내용을 학습하였다. 단순히 프로그래밍 문법을 암기하는 것에 그치지 않고, 프로그램이 서버와 운영체제에서 실행되고 데이터를 처리하는 전체적인 원리를 이해하는 데 중점을 두었다.</p>
<p>서버 프로그램 구현에서는 사용자의 요청을 전달받아 필요한 작업을 수행하고 그 결과를 반환하는 서버 프로그램의 기본 구조를 학습하였다. 서버 프로그램은 입력된 요청을 분석한 뒤 데이터베이스 조회, 비즈니스 로직 처리, 결과 반환의 과정을 거쳐 동작한다는 점을 이해하였다. 또한 여러 기능에서 공통으로 사용되는 코드를 별도의 모듈로 분리하면 코드의 중복을 줄이고 유지보수성을 높일 수 있다는 점을 배웠다. 정해진 시간이나 조건에 따라 자동으로 작업을 처리하는 배치 프로그램의 특징과 오류 발생 시 예외를 처리하고 실행 결과를 기록하는 방법도 함께 학습하였다.</p>
<p>프로그래밍 언어 활용에서는 변수, 자료형, 연산자, 조건문, 반복문, 함수 등 프로그램을 구성하는 기본 문법을 정리하였다. 배열, 리스트, 스택, 큐와 같은 자료구조를 이용하여 데이터를 저장하고 처리하는 방법을 학습하고, 문제의 조건에 따라 적절한 자료구조를 선택해야 한다는 점을 이해하였다. 또한 클래스와 객체, 캡슐화, 상속, 다형성과 같은 객체지향 프로그래밍의 주요 개념을 학습하였다. 이를 통해 프로그램을 기능별 객체로 분리하면 코드의 재사용성과 확장성을 높일 수 있다는 점을 알 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/8652ab2c-69d0-46ed-8f1d-da83592d5eac/image.png" alt=""></p>
<p>응용 소프트웨어 기초 기술 활용에서는 운영체제, 데이터베이스, 네트워크와 관련된 기본 개념을 학습하였다. 운영체제 부분에서는 프로세스와 스레드의 차이, CPU 스케줄링, 기억장치 관리, 교착상태의 발생 조건과 해결 방법을 살펴보았다. 데이터베이스 부분에서는 트랜잭션의 특성, 데이터 무결성, 병행 제어, 회복 기법을 학습하였다. 네트워크 부분에서는 OSI 7계층과 TCP/IP 구조, IP 주소, 포트 번호, 주요 프로토콜의 역할을 정리하였다.</p>
<p>이번 학습을 통해 프로그램은 작성된 코드만으로 동작하는 것이 아니라 운영체제, 데이터베이스, 네트워크, 서버 환경과 상호작용하며 실행된다는 점을 이해하였다. 또한 정보처리기사 문제를 풀 때 개별 용어만 암기하기보다 각 기술이 실제 시스템에서 어떤 역할을 수행하는지를 연결하여 학습하는 것이 중요하다는 점을 알 수 있었다.</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<pre><code class="language-python">from collections import deque


# =========================================================
# 1. DFS - 연결 요소의 개수 구하기
# 서로 연결된 정점들을 하나의 그룹으로 보고,
# 그래프에 몇 개의 독립된 그룹이 존재하는지 계산
# =========================================================
def count_connected_components(n, edges):
    graph = [[] for _ in range(n + 1)]

    for start, end in edges:
        graph[start].append(end)
        graph[end].append(start)

    visited = [False] * (n + 1)

    def dfs(start):
        stack = [start]
        visited[start] = True

        while stack:
            current = stack.pop()

            for next_node in graph[current]:
                if not visited[next_node]:
                    visited[next_node] = True
                    stack.append(next_node)

    component_count = 0

    for node in range(1, n + 1):
        if not visited[node]:
            dfs(node)
            component_count += 1

    return component_count


n = 7
edges = [
    (1, 2),
    (2, 3),
    (4, 5),
    (6, 7)
]

print(
    &quot;연결 요소의 개수:&quot;,
    count_connected_components(n, edges)
)


# =========================================================
# 2. BFS - 미로의 최단 거리 구하기
# 1은 이동 가능한 칸, 0은 이동할 수 없는 칸
# 시작점에서 도착점까지 이동하는 최소 칸 수 계산
# =========================================================
def shortest_maze_path(maze):
    rows = len(maze)
    cols = len(maze[0])

    queue = deque([(0, 0)])
    distance = [[-1] * cols for _ in range(rows)]
    distance[0][0] = 1

    directions = [
        (-1, 0),
        (1, 0),
        (0, -1),
        (0, 1)
    ]

    while queue:
        row, col = queue.popleft()

        for dr, dc in directions:
            next_row = row + dr
            next_col = col + dc

            if not (0 &lt;= next_row &lt; rows and 0 &lt;= next_col &lt; cols):
                continue

            if maze[next_row][next_col] == 0:
                continue

            if distance[next_row][next_col] != -1:
                continue

            distance[next_row][next_col] = distance[row][col] + 1
            queue.append((next_row, next_col))

    return distance[rows - 1][cols - 1]


maze = [
    [1, 1, 0, 1, 1],
    [0, 1, 0, 1, 0],
    [1, 1, 1, 1, 0],
    [1, 0, 0, 1, 1],
    [1, 1, 1, 0, 1]
]

print(
    &quot;미로의 최단 이동 거리:&quot;,
    shortest_maze_path(maze)
)


# =========================================================
# 3. DFS - 경로 존재 여부 확인
# 출발 정점에서 목표 정점까지 이동할 수 있는지 확인
# 방향성이 있는 그래프를 인접 리스트로 표현
# =========================================================
def has_path(graph, start, target):
    visited = set()
    stack = [start]

    while stack:
        current = stack.pop()

        if current == target:
            return True

        if current in visited:
            continue

        visited.add(current)

        for next_node in graph.get(current, []):
            if next_node not in visited:
                stack.append(next_node)

    return False


directed_graph = {
    1: [2, 3],
    2: [4],
    3: [5],
    4: [6],
    5: [],
    6: []
}

print(
    &quot;1번에서 6번까지 경로 존재 여부:&quot;,
    has_path(directed_graph, 1, 6)
)


# =========================================================
# 4. BFS - 특정 거리의 도시 찾기
# 시작 정점에서 정확히 K개의 간선을 지나 도착하는 정점 탐색
# =========================================================
def find_nodes_at_distance(n, edges, start, target_distance):
    graph = [[] for _ in range(n + 1)]

    for from_node, to_node in edges:
        graph[from_node].append(to_node)

    distance = [-1] * (n + 1)
    distance[start] = 0

    queue = deque([start])

    while queue:
        current = queue.popleft()

        for next_node in graph[current]:
            if distance[next_node] == -1:
                distance[next_node] = distance[current] + 1
                queue.append(next_node)

    result = []

    for node in range(1, n + 1):
        if distance[node] == target_distance:
            result.append(node)

    return result


n = 6
edges = [
    (1, 2),
    (1, 3),
    (2, 4),
    (3, 4),
    (3, 5),
    (4, 6)
]

print(
    &quot;1번 정점에서 거리가 2인 정점:&quot;,
    find_nodes_at_distance(n, edges, 1, 2)
)


# =========================================================
# 5. BFS - 이분 그래프 판별
# 인접한 두 정점이 서로 다른 그룹에 속하도록
# 그래프를 두 가지 색으로 구분할 수 있는지 확인
# =========================================================
def is_bipartite_graph(n, edges):
    graph = [[] for _ in range(n + 1)]

    for start, end in edges:
        graph[start].append(end)
        graph[end].append(start)

    color = [0] * (n + 1)

    for start in range(1, n + 1):
        if color[start] != 0:
            continue

        queue = deque([start])
        color[start] = 1

        while queue:
            current = queue.popleft()

            for next_node in graph[current]:
                if color[next_node] == 0:
                    color[next_node] = -color[current]
                    queue.append(next_node)

                elif color[next_node] == color[current]:
                    return False

    return True


n = 5
edges = [
    (1, 2),
    (2, 3),
    (3, 4),
    (4, 5),
    (5, 1)
]

print(
    &quot;이분 그래프 여부:&quot;,
    is_bipartite_graph(n, edges)
)


# =========================================================
# 6. DFS - 섬의 개수와 크기 구하기
# 2차원 지도에서 상하좌우로 연결된 땅을 하나의 섬으로 판단
# =========================================================
def find_islands(grid):
    rows = len(grid)
    cols = len(grid[0])
    visited = [[False] * cols for _ in range(rows)]

    directions = [
        (-1, 0),
        (1, 0),
        (0, -1),
        (0, 1)
    ]

    def dfs(start_row, start_col):
        stack = [(start_row, start_col)]
        visited[start_row][start_col] = True
        size = 0

        while stack:
            row, col = stack.pop()
            size += 1

            for dr, dc in directions:
                next_row = row + dr
                next_col = col + dc

                if not (0 &lt;= next_row &lt; rows and 0 &lt;= next_col &lt; cols):
                    continue

                if grid[next_row][next_col] == 0:
                    continue

                if visited[next_row][next_col]:
                    continue

                visited[next_row][next_col] = True
                stack.append((next_row, next_col))

        return size

    island_sizes = []

    for row in range(rows):
        for col in range(cols):
            if grid[row][col] == 1 and not visited[row][col]:
                island_sizes.append(dfs(row, col))

    island_sizes.sort()

    return len(island_sizes), island_sizes


grid = [
    [1, 1, 0, 0, 1],
    [1, 0, 0, 1, 1],
    [0, 0, 1, 0, 0],
    [1, 1, 1, 0, 1],
    [0, 1, 0, 0, 1]
]

island_count, island_sizes = find_islands(grid)

print(&quot;섬의 개수:&quot;, island_count)
print(&quot;각 섬의 크기:&quot;, island_sizes)</code></pre>
<p>이번 주에는 코딩테스트 대비를 위해 그래프의 기본 표현 방법과 DFS, BFS를 활용한 다양한 유형의 문제 풀이를 진행하였다. 단순히 정점을 정해진 순서로 방문하는 문제뿐만 아니라 연결 요소의 개수, 경로 존재 여부, 최단 거리, 특정 거리의 정점 탐색, 이분 그래프 판별, 2차원 영역 탐색 문제를 함께 학습하였다.</p>
<p>그래프 기본 유형에서는 정점과 간선으로 대상 간의 연결 관계를 표현하고, 주어진 간선 정보를 인접 리스트로 변환하는 방법을 연습하였다. 인접 리스트는 각 정점과 직접 연결된 정점만 저장하기 때문에 간선의 수가 상대적으로 적은 그래프를 효율적으로 표현할 수 있다는 점을 이해하였다.</p>
<p>연결 요소 탐색 유형에서는 아직 방문하지 않은 정점을 발견할 때마다 DFS를 새롭게 실행하였다. 한 번의 DFS에서 방문되는 모든 정점은 서로 연결된 하나의 그룹에 해당하며, 탐색을 시작한 횟수를 세면 그래프 전체의 연결 요소 개수를 구할 수 있다는 원리를 학습하였다.</p>
<p>경로 존재 여부 유형에서는 출발 정점부터 DFS를 수행하면서 목표 정점에 도달할 수 있는지 확인하였다. 모든 경로를 직접 저장하지 않더라도 방문 가능한 정점을 탐색하는 과정에서 목표 정점이 발견되는지를 검사하면 경로의 존재 여부를 판단할 수 있다는 점을 이해하였다.</p>
<p>격자와 영역 탐색 유형에서는 2차원 배열의 각 칸을 하나의 정점으로 보고, 상하좌우로 이동할 수 있는 관계를 간선으로 해석하였다. 이동할 좌표가 배열의 범위 안에 있는지, 이동 가능한 칸인지, 이미 방문한 칸인지 차례대로 검사하는 방식으로 섬의 개수와 각 섬의 크기를 계산하였다.</p>
<p>BFS 최단 거리 유형에서는 시작점에서 가까운 위치부터 단계적으로 탐색하였다. 가중치가 없는 그래프에서는 BFS를 통해 어떤 정점에 처음 도착했을 때의 거리가 최단 거리가 되므로, 미로의 최소 이동 횟수나 도시 간 최소 이동 횟수를 구하는 문제에 활용할 수 있다는 점을 학습하였다.</p>
<p>특정 거리 탐색 유형에서는 각 정점의 방문 여부만 저장하는 대신 시작점으로부터의 거리를 배열에 기록하였다. 현재 정점의 거리보다 1만큼 큰 값을 다음 정점에 저장하여, 탐색이 끝난 뒤 정확히 지정된 거리에 있는 정점만 찾는 방법을 연습하였다.</p>
<p>이분 그래프 판별 유형에서는 서로 연결된 정점들이 같은 그룹에 속하지 않도록 두 가지 색을 번갈아 지정하였다. 아직 색이 정해지지 않은 정점에는 현재 정점과 반대되는 색을 지정하고, 이미 같은 색으로 지정된 두 정점이 연결되어 있다면 이분 그래프가 아니라는 방식으로 판별하였다.</p>
<p>DFS는 하나의 경로를 가능한 깊게 탐색하기 때문에 연결된 영역의 크기, 경로 존재 여부, 연결 요소의 개수 등을 확인하는 문제에 활용하였다. 재귀 함수로도 구현할 수 있지만, 실습에서는 스택을 직접 사용하여 탐색 순서를 명확하게 확인하고 입력 규모가 큰 경우 발생할 수 있는 재귀 깊이 문제를 줄였다.</p>
<p>BFS는 큐를 사용하여 시작점에서 가까운 정점부터 순서대로 탐색하였다. 정점을 큐에서 꺼낼 때가 아니라 큐에 추가하는 시점에 방문 처리해야 같은 정점이 중복으로 들어가는 것을 방지할 수 있다는 점도 함께 학습하였다.</p>
<p>이번 학습을 통해 그래프 문제에서는 먼저 문제의 대상을 정점과 간선으로 어떻게 표현할 것인지 판단하는 과정이 중요하다는 점을 이해하였다. 또한 단순한 방문이 목적인지, 연결된 영역을 찾아야 하는지, 최단 거리를 구해야 하는지에 따라 DFS와 BFS 중 적절한 탐색 방법을 선택해야 한다는 점을 알 수 있었다.</p>
<p>같은 그래프 탐색 알고리즘을 사용하더라도 문제에서 요구하는 결과에 따라 방문 여부, 거리, 색상, 영역의 크기 등 추가로 저장해야 하는 정보가 달라진다는 점도 이해하였다. 이를 통해 DFS와 BFS의 구현 코드를 단순히 암기하기보다, 문제의 조건에 맞게 탐색 과정과 저장 정보를 변형하는 연습이 필요하다는 점을 배웠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 4회차 (계획)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-4%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-4%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Mon, 20 Jul 2026 06:46:10 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득">1. 정보처리기사 취득</h2>
<p>프로그래밍 언어 활용 과목에서 아래 주제들에 대한 학습 진행</p>
<ul>
<li><p>서버 프로그램 구현
사용자의 요청을 받아 데이터를 처리하고 결과를 반환하는 서버 프로그램의 기본 동작 과정 학습</p>
</li>
<li><p>공통 모듈 구현
여러 기능에서 반복적으로 사용하는 코드를 모듈로 분리하여 재사용성과 유지보수성 향상</p>
</li>
<li><p>서버 프로그램 테스트
구현된 기능이 요구사항에 맞게 동작하는지 확인하고 입력값, 예외 상황, 실행 결과 점검</p>
</li>
<li><p>배치 프로그램 구현
사용자의 직접적인 요청 없이 정해진 시간이나 조건에 따라 작업을 일괄적으로 처리하는 프로그램의 구조 이해</p>
</li>
<li><p>프로그래밍 언어 기본 문법
변수, 자료형, 연산자, 조건문, 반복문을 활용하여 프로그램의 기본 실행 흐름 구성</p>
</li>
<li><p>함수와 모듈 활용
반복되는 기능을 함수로 분리하고 모듈을 활용하여 프로그램을 체계적으로 구성</p>
</li>
<li><p>객체지향 프로그래밍
클래스와 객체, 상속, 캡슐화, 다형성의 개념을 이해하고 객체 간 관계를 활용한 프로그램 설계</p>
</li>
<li><p>프로그래밍 언어별 특징
C, Java, Python 등 주요 프로그래밍 언어의 실행 방식과 문법적 특징 비교</p>
</li>
</ul>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<p>코딩테스트 문제 풀이를 진행 &lt;그래프·DFS·BFS&gt; 유형</p>
<ul>
<li><p>그래프 기본 구조
정점과 간선의 연결 관계를 인접 행렬 또는 인접 리스트로 표현</p>
</li>
<li><p>그래프 탐색
시작 정점에서 연결된 정점들을 순서대로 방문</p>
</li>
<li><p>DFS
스택 또는 재귀 함수를 활용하여 한 경로를 끝까지 탐색</p>
</li>
<li><p>BFS
큐를 활용하여 시작점과 가까운 정점부터 차례대로 탐색</p>
</li>
<li><p>방문 처리
이미 탐색한 정점을 표시하여 중복 방문과 무한 반복 방지</p>
</li>
<li><p>연결 요소 탐색
서로 연결된 정점들의 그룹 개수를 DFS 또는 BFS로 확인</p>
</li>
<li><p>경로 탐색
출발점에서 도착점까지 이동할 수 있는 경로가 존재하는지 판단</p>
</li>
<li><p>최단 거리 탐색
가중치가 없는 그래프에서 BFS를 활용하여 최소 이동 횟수 계산</p>
</li>
<li><p>격자 그래프
상하좌우 또는 대각선 방향으로 이동하며 2차원 배열 탐색</p>
</li>
<li><p>영역 탐색
지도나 배열에서 서로 연결된 같은 값의 영역 크기와 개수 확인</p>
</li>
<li><p>그래프 시뮬레이션
문제에서 제시된 이동 및 방문 조건을 적용하여 탐색 과정 구현</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 3회차 (결과)
]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-3%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-3%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Mon, 13 Jul 2026 10:04:47 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득-준비">1. 정보처리기사 취득 준비</h2>
<p>소프트웨어 개발 방법론 활용에서는 소프트웨어를 체계적으로 개발하기 위해 적용하는 개발 절차와 방법론을 학습하였다. 구조적 방법론, 정보공학 방법론, 객체지향 방법론, 애자일 방법론 등 다양한 개발 방법론의 특징을 살펴보고, 프로젝트의 목적과 환경에 따라 적절한 방법론을 선택해야 한다는 점을 이해하였다. 또한 소프트웨어 생명주기와 개발 단계별 산출물, 비용 산정 및 일정 관리 방법에 대해서도 학습하였다.</p>
<p>IT 프로젝트 정보 시스템 구축 관리에서는 정보 시스템 구축 프로젝트를 계획하고 수행하는 데 필요한 관리 방법을 학습하였다. 프로젝트의 범위, 일정, 비용, 품질, 인력 등을 체계적으로 관리해야 하며, 각 단계에서 발생할 수 있는 위험 요소를 사전에 파악하고 대응하는 것이 중요하다는 점을 이해하였다. 또한 요구사항 분석부터 시스템 구축, 테스트, 운영에 이르기까지 전체 프로젝트 과정을 관리하는 방법을 학습하였다.</p>
<p>소프트웨어 개발 보안 구축에서는 소프트웨어 개발 과정에서 발생할 수 있는 보안 취약점을 예방하고 안전한 프로그램을 구현하는 방법을 학습하였다. 입력값 검증, 인증과 권한 관리, 암호화, 오류 처리 등 보안 기능을 설계하고 구현하는 방법을 살펴보았다. 특히 개발 초기 단계부터 보안을 고려해야 취약점 발생 가능성을 줄일 수 있으며, 시큐어 코딩을 통해 안전한 소프트웨어를 구축하는 것이 중요하다는 점을 배웠다.</p>
<p>시스템 보안 구축에서는 서버, 네트워크, 데이터베이스 등 정보 시스템을 외부의 공격과 내부의 위협으로부터 보호하는 방법을 학습하였다. 접근 통제, 사용자 인증, 방화벽, 침입 탐지 및 방지 시스템, 악성코드 대응 등 주요 보안 기술을 이해하였다. 또한 시스템의 보안 상태를 지속적으로 점검하고, 보안 사고 발생 시 신속하게 대응할 수 있는 관리 체계를 구축해야 한다는 점을 알 수 있었다.</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<pre><code class="language-python">import heapq
from collections import deque


# 1. 기본 스택
# 후입선출 구조를 활용하여 데이터를 삽입하고 삭제하는 문제
def stack_operation(commands):
    stack = []
    result = []

    for command in commands:
        if command[0] == &quot;push&quot;:
            stack.append(command[1])

        elif command[0] == &quot;pop&quot;:
            if stack:
                result.append(stack.pop())
            else:
                result.append(-1)

        elif command[0] == &quot;top&quot;:
            if stack:
                result.append(stack[-1])
            else:
                result.append(-1)

    return result


commands = [
    (&quot;push&quot;, 10),
    (&quot;push&quot;, 20),
    (&quot;top&quot;,),
    (&quot;pop&quot;,),
    (&quot;pop&quot;,)
]

print(&quot;스택 연산 결과:&quot;, stack_operation(commands))


# 2. 괄호 검사
# 여는 괄호를 스택에 저장하고 닫는 괄호와 짝이 맞는지 확인하는 문제
def check_parentheses(expression):
    stack = []
    pairs = {
        &quot;)&quot;: &quot;(&quot;,
        &quot;]&quot;: &quot;[&quot;,
        &quot;}&quot;: &quot;{&quot;
    }

    for char in expression:
        if char in &quot;([{&quot;:
            stack.append(char)

        elif char in &quot;)]}&quot;:
            if not stack or stack[-1] != pairs[char]:
                return False

            stack.pop()

    return len(stack) == 0


expression = &quot;({[]})&quot;
print(&quot;올바른 괄호인지 확인:&quot;, check_parentheses(expression))


# 3. 문자열 및 수식 처리
# 후위 표기식의 숫자를 순서대로 확인하며 스택을 이용해 계산하는 문제
def calculate_postfix(expression):
    stack = []

    for token in expression.split():
        if token.isdigit():
            stack.append(int(token))

        else:
            second = stack.pop()
            first = stack.pop()

            if token == &quot;+&quot;:
                stack.append(first + second)
            elif token == &quot;-&quot;:
                stack.append(first - second)
            elif token == &quot;*&quot;:
                stack.append(first * second)
            elif token == &quot;/&quot;:
                stack.append(first // second)

    return stack.pop()


postfix = &quot;3 4 + 2 *&quot;
print(&quot;후위 표기식 계산 결과:&quot;, calculate_postfix(postfix))


# 4. 단조 스택
# 현재 원소보다 큰 다음 원소를 탐색하는 문제
def next_greater_number(numbers):
    result = [-1] * len(numbers)
    stack = []

    for index, number in enumerate(numbers):
        while stack and numbers[stack[-1]] &lt; number:
            previous_index = stack.pop()
            result[previous_index] = number

        stack.append(index)

    return result


numbers = [2, 3, 1, 5]
print(&quot;오큰수 결과:&quot;, next_greater_number(numbers))


# 5. 기본 큐
# 선입선출 구조를 활용하여 데이터를 삽입하고 삭제하는 문제
def queue_operation(commands):
    queue = deque()
    result = []

    for command in commands:
        if command[0] == &quot;push&quot;:
            queue.append(command[1])

        elif command[0] == &quot;pop&quot;:
            if queue:
                result.append(queue.popleft())
            else:
                result.append(-1)

        elif command[0] == &quot;front&quot;:
            if queue:
                result.append(queue[0])
            else:
                result.append(-1)

    return result


commands = [
    (&quot;push&quot;, 10),
    (&quot;push&quot;, 20),
    (&quot;front&quot;,),
    (&quot;pop&quot;,),
    (&quot;pop&quot;,)
]

print(&quot;큐 연산 결과:&quot;, queue_operation(commands))


# 6. 작업 순서 처리
# 입력된 순서대로 작업을 저장하고 앞에서부터 처리하는 문제
def process_tasks(tasks):
    queue = deque(tasks)
    completed = []

    while queue:
        task = queue.popleft()
        completed.append(task)

    return completed


tasks = [&quot;로그인 처리&quot;, &quot;데이터 조회&quot;, &quot;결과 출력&quot;]
print(&quot;작업 처리 순서:&quot;, process_tasks(tasks))


# 7. 우선순위 큐
# 현재 후보 중 우선순위가 가장 높은 작업부터 처리하는 문제
def priority_task(tasks):
    heap = []

    for priority, task in tasks:
        heapq.heappush(heap, (-priority, task))

    result = []

    while heap:
        priority, task = heapq.heappop(heap)
        result.append(task)

    return result


tasks = [
    (2, &quot;일반 작업&quot;),
    (5, &quot;긴급 작업&quot;),
    (3, &quot;중요 작업&quot;)
]

print(&quot;우선순위 작업 처리 결과:&quot;, priority_task(tasks))


# 8. 덱
# 앞과 뒤에서 데이터를 삽입하고 삭제하는 문제
def deque_operation():
    data = deque()

    data.append(10)
    data.append(20)
    data.appendleft(5)

    left_value = data.popleft()
    right_value = data.pop()

    return left_value, right_value, list(data)


print(&quot;덱 연산 결과:&quot;, deque_operation())


# 9. 시뮬레이션
# 큐에 주어진 조건을 적용하며 문서의 출력 순서를 계산하는 문제
def printer_queue(priorities, location):
    queue = deque(
        (index, priority)
        for index, priority in enumerate(priorities)
    )

    count = 0

    while queue:
        current = queue.popleft()

        if any(current[1] &lt; other[1] for other in queue):
            queue.append(current)

        else:
            count += 1

            if current[0] == location:
                return count


priorities = [2, 1, 3, 2]
location = 2
print(&quot;해당 문서의 출력 순서:&quot;, printer_queue(priorities, location))</code></pre>
<p>이번 주에는 코딩테스트 대비를 위해 Queue와 Stack 유형의 문제 풀이를 진행하였다. 스택과 큐는 데이터를 저장하고 꺼내는 순서에 차이가 있으며, 문제에서 요구하는 처리 순서를 파악한 뒤 적절한 자료구조를 선택하는 것이 중요하다는 점을 이해하였다.</p>
<p>기본 스택 유형에서는 가장 나중에 삽입된 데이터가 가장 먼저 삭제되는 후입선출 구조를 학습하였다. 데이터를 삽입할 때는 push 연산을 사용하고, 가장 위에 있는 데이터를 삭제하거나 확인할 때는 pop과 top 연산을 활용하는 방법을 익혔다.</p>
<p>괄호 검사 유형에서는 여는 괄호를 스택에 저장한 뒤 닫는 괄호가 등장했을 때 가장 최근에 저장된 여는 괄호와 짝이 맞는지 확인하는 문제를 풀이하였다. 괄호의 순서가 올바르지 않거나 모든 괄호가 정상적으로 제거되지 않은 경우에는 잘못된 문자열로 판단해야 한다는 점을 학습하였다.</p>
<p>문자열 및 수식 처리 유형에서는 문자열이나 수식을 왼쪽부터 순서대로 확인하면서 필요한 값을 스택에 저장하는 방법을 연습하였다. 특히 후위 표기식을 계산할 때 숫자는 스택에 저장하고, 연산자가 등장하면 스택에서 두 값을 꺼내 계산한 뒤 결과를 다시 저장하는 방식을 이해하였다.</p>
<p>단조 스택 유형에서는 스택 내부의 값이 증가하거나 감소하는 형태를 유지하도록 관리하면서 이전 또는 다음 원소를 효율적으로 찾는 방법을 학습하였다. 현재 값보다 작은 이전 원소를 제거하는 과정을 통해 각 원소의 다음 큰 수를 구할 수 있으며, 모든 값을 반복해서 비교하는 방식보다 효율적으로 문제를 해결할 수 있다는 점을 알 수 있었다.</p>
<p>기본 큐 유형에서는 가장 먼저 삽입된 데이터가 가장 먼저 삭제되는 선입선출 구조를 학습하였다. 큐의 뒤쪽에 데이터를 삽입하고 앞쪽에서 데이터를 꺼내는 방식을 활용하여, 입력된 순서대로 데이터를 처리하는 문제를 풀이하였다.</p>
<p>작업 순서 처리 유형에서는 여러 작업을 큐에 저장한 뒤 입력된 순서대로 하나씩 꺼내 처리하는 방법을 연습하였다. 대기열, 요청 처리, 메시지 전달처럼 먼저 들어온 작업을 우선적으로 처리해야 하는 상황에서 큐가 적절하게 활용될 수 있다는 점을 이해하였다.</p>
<p>우선순위 큐 유형에서는 단순히 입력된 순서대로 데이터를 처리하는 것이 아니라, 현재 후보 중 우선순위가 가장 높은 값을 먼저 선택하는 방법을 학습하였다. 파이썬의 heapq를 활용하여 최솟값이나 최댓값을 효율적으로 관리하고, 우선순위에 따라 작업을 처리하는 방법을 익혔다.</p>
<p>덱 유형에서는 데이터의 앞과 뒤에서 모두 삽입과 삭제가 가능한 자료구조의 특징을 학습하였다. 일반적인 큐보다 다양한 방향에서 데이터를 처리할 수 있기 때문에 슬라이딩 윈도우, 회전 큐, 양방향 탐색과 같은 문제에서 활용할 수 있다는 점을 이해하였다.</p>
<p>시뮬레이션 유형에서는 큐와 스택에 문제에서 제시한 조건을 차례대로 적용하며 처리 과정을 구현하는 연습을 하였다. 프린터 대기열 문제처럼 현재 작업보다 우선순위가 높은 작업이 존재하면 뒤로 이동시키고, 그렇지 않으면 바로 처리하는 과정을 직접 구현하였다.</p>
<p>이를 통해 Queue와 Stack 문제는 단순히 자료구조의 사용법을 아는 것뿐만 아니라, 데이터가 어떤 순서로 들어오고 나가야 하는지를 정확하게 파악하는 것이 중요하다는 점을 알 수 있었다. 또한 문제의 조건에 따라 일반 스택, 큐, 우선순위 큐, 덱 중 가장 적절한 자료구조를 선택하는 연습이 필요하다는 점을 이해하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 3회차 (계획)
]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-3%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-3%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Mon, 13 Jul 2026 09:58:26 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득">1. 정보처리기사 취득</h2>
<p>정보시스템 구축 관리 과목에서 아래 주제들에 대한 학습 진행</p>
<p>1장 소프트웨어 개발 방법론 활용
2장 IT 프로젝트 정보 시스템 구축 관리
3장 소프트웨어 개발 보안 구축
4장 시스템 보안 구축</p>
<h2 id="2-취업-코딩테스트-공부">2. 취업 코딩테스트 공부</h2>
<p>코딩테스트 문제 풀이를 진행 &lt;Queue·Stack&gt; 유형</p>
<p>기본 스택
후입선출 구조를 활용한 데이터 삽입·삭제</p>
<p>괄호 검사
여는 괄호를 저장하고 닫는 괄호와 짝이 맞는지 확인</p>
<p>문자열·수식 처리
문자를 순서대로 확인하며 필요한 값을 스택에 저장</p>
<p>단조 스택
스택을 오름차순 또는 내림차순으로 유지하며 이전·다음 원소 탐색</p>
<p>기본 큐
선입선출 구조를 활용한 데이터 삽입·삭제</p>
<p>작업 순서 처리
입력된 순서대로 작업을 저장하고 앞에서부터 처리</p>
<p>우선순위 큐
현재 후보 중 우선순위가 가장 높은 값부터 선택</p>
<p>덱
앞과 뒤에서 데이터의 삽입·삭제를 수행</p>
<p>시뮬레이션
큐와 스택에 주어진 조건을 적용하며 처리 과정을 구현</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 2회차 (결과)
]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-2%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-2%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Mon, 06 Jul 2026 11:06:48 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보처리기사-취득-준비">1. 정보처리기사 취득 준비</h2>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/7b5bcbe7-ea89-406e-9fd5-5666f687aa96/image.png" alt=""></p>
<p>제품 소프트웨어 패키징에서는 개발이 완료된 소프트웨어를 사용자가 설치하고 사용할 수 있도록 구성하는 과정을 학습하였다. 특히 배포 파일 구성, 설치 절차, 패키징 시 고려해야 할 보안 및 호환성 요소를 이해하였다.</p>
<p>애플리케이션 테스트 케이스 설계에서는 프로그램이 요구사항에 맞게 동작하는지 확인하기 위한 테스트 케이스 작성 방법을 학습하였다. 입력값, 실행 조건, 예상 결과를 기준으로 테스트 항목을 구성하고, 오류를 사전에 발견하기 위해 체계적인 테스트 설계가 필요하다는 점을 배웠다.</p>
<p>애플리케이션 통합 테스트에서는 개별 모듈을 결합한 뒤 전체 시스템이 정상적으로 동작하는지 확인하는 과정을 학습하였다. 단위 테스트 이후 모듈 간 인터페이스와 데이터 흐름을 점검해야 하며, 통합 과정에서 발생할 수 있는 오류를 확인하는 것이 중요하다는 점을 알 수 있었다.</p>
<p>애플리케이션 성능 개선에서는 프로그램의 실행 속도, 자원 사용량, 응답 시간 등을 분석하고 개선하는 방법을 학습하였다. 성능 저하의 원인을 파악한 뒤 알고리즘 개선, 불필요한 연산 제거, 자원 사용 최적화 등을 통해 애플리케이션의 효율성을 높일 수 있다는 점을 이해하였다.</p>
<h2 id="2-코딩테스트-공부">2. 코딩테스트 공부</h2>
<pre><code class="language-python">import heapq

# 1. 정렬 후 선택 Greedy
# 회의 시작 시간과 종료 시간이 주어졌을 때, 최대한 많은 회의를 선택하는 문제
def meeting_room(meetings):
    # 종료 시간이 빠른 순서로 정렬
    meetings.sort(key=lambda x: (x[1], x[0]))

    count = 0
    end_time = 0

    for start, end in meetings:
        if start &gt;= end_time:
            count += 1
            end_time = end

    return count


meetings = [(1, 4), (3, 5), (0, 6), (5, 7), (8, 9), (5, 9)]
print(&quot;선택 가능한 최대 회의 수:&quot;, meeting_room(meetings))


# 2. Heap Greedy
# 현재 선택 가능한 후보 중 가장 큰 값을 선택하는 문제
def max_profit(jobs):
    # jobs = (마감일, 보상)
    jobs.sort()

    heap = []

    for deadline, profit in jobs:
        heapq.heappush(heap, profit)

        # 마감일보다 선택한 작업 수가 많으면 보상이 가장 작은 작업 제거
        if len(heap) &gt; deadline:
            heapq.heappop(heap)

    return sum(heap)


jobs = [(1, 50), (2, 10), (2, 20), (1, 30)]
print(&quot;얻을 수 있는 최대 보상:&quot;, max_profit(jobs))


# 3. 비용 최소화 Greedy
# 여러 단위의 가격이 주어졌을 때, 가장 저렴한 비용부터 처리
def min_cost_purchase(prices, amount):
    # prices = (가격, 구매 가능 수량)
    prices.sort()

    total_cost = 0

    for price, count in prices:
        buy = min(amount, count)
        total_cost += price * buy
        amount -= buy

        if amount == 0:
            break

    return total_cost


prices = [(300, 3), (100, 2), (200, 4)]
amount = 5
print(&quot;최소 구매 비용:&quot;, min_cost_purchase(prices, amount))


# 4. 문자열 및 스택 Greedy
# 숫자 문자열에서 k개의 숫자를 제거하여 가장 큰 수 만들기
def make_big_number(number, k):
    stack = []

    for num in number:
        while stack and k &gt; 0 and stack[-1] &lt; num:
            stack.pop()
            k -= 1

        stack.append(num)

    # 제거 횟수가 남아 있다면 뒤에서 제거
    if k &gt; 0:
        stack = stack[:-k]

    return &#39;&#39;.join(stack)


number = &quot;1924&quot;
k = 2
print(&quot;만들 수 있는 가장 큰 수:&quot;, make_big_number(number, k))</code></pre>
<p>이번 주에는 코딩테스트 대비를 위해 Greedy 유형 문제 풀이를 진행하였다. Greedy 알고리즘은 매 순간 가장 유리해 보이는 선택을 통해 전체 최적해를 구하는 방식이라는 점을 이해하고, 문제 조건에 따라 어떤 기준으로 선택해야 하는지 판단하는 연습을 하였다.</p>
<p>정렬 후 선택 유형에서는 주어진 데이터를 특정 기준으로 정렬한 뒤 앞에서부터 조건에 맞는 값을 선택하는 문제를 풀이하였다. 구간 그리디에서는 끝점이나 진출 지점을 기준으로 선택하여 최소 횟수나 최대 개수를 구하는 방식을 익혔다.</p>
<p>커버 그리디에서는 현재 위치를 기준으로 가장 멀리 덮을 수 있는 선택을 하는 방식의 문제를 학습하였다. Heap 그리디에서는 현재 선택 가능한 후보 중 최댓값이나 최솟값을 우선순위 큐를 활용해 고르는 방법을 연습하였다.</p>
<p>마감일 스케줄링 유형에서는 마감일을 기준으로 정렬한 뒤, 조건을 초과하는 경우 가치가 낮은 항목을 제거하는 방식의 문제를 풀이하였다. 비용 최소화 유형에서는 작은 비용부터 처리하거나, 더 저렴한 조건에서 최대한 많이 처리하는 방식으로 최적해를 구하는 연습을 하였다.</p>
<p>누적 최적 유형에서는 현재까지의 최솟값이나 최댓값을 유지하면서 이후 선택을 판단하는 방법을 학습하였다. 문자열 및 스택 그리디에서는 앞자리 값이나 사전순을 고려하여 불리한 이전 선택을 제거하는 방식의 문제를 풀이하였다.</p>
<p>또한 수학적 그리디 유형에서는 수의 성질과 연산 규칙을 이용하여 최소 연산 횟수나 최적의 값을 구하는 문제를 학습하였다. 이를 통해 Greedy 문제는 단순히 큰 값이나 작은 값을 고르는 것이 아니라, 선택 기준이 전체 최적해로 이어지는지 판단하는 과정이 중요하다는 점을 알 수 있었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 2회차 (계획)
]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-2%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-2%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Mon, 06 Jul 2026 11:01:47 GMT</pubDate>
            <description><![CDATA[<h3 id="1-정보처리기사-취득">1. 정보처리기사 취득</h3>
<p>소프트웨어 설계 과목에서 아래 주제들에 대한 학습 진행</p>
<ul>
<li>Section 01 제품 소프트웨어 패키징</li>
<li>Section 02 제품 소프트웨어 매뉴얼 작성</li>
<li>Section 03 제품 소프트웨어 버전 관리</li>
<li>Section 01 애플리케이션 테스트 케이스 설계</li>
<li>Section 02 애플리케이션 통합 테스트</li>
<li>Section 03 애플리케이션 성능 개선</li>
</ul>
<h3 id="2-코딩테스트-공부">2. 코딩테스트 공부</h3>
<p>코딩테스트 문제 풀이를 진행 &lt;Greedy&gt; 유형</p>
<ol>
<li>정렬 후 선택</li>
</ol>
<ul>
<li>기준 정렬 → 앞에서부터 선택</li>
</ul>
<ol start="2">
<li>구간 그리디</li>
</ol>
<ul>
<li>끝점/진출 지점 기준으로 선택</li>
</ul>
<ol start="3">
<li>커버 그리디</li>
</ol>
<ul>
<li>현재 위치에서 가장 멀리 덮는 선택</li>
</ul>
<ol start="4">
<li>Heap 그리디</li>
</ol>
<ul>
<li>현재 가능한 후보 중 최댓값/최솟값 선택</li>
</ul>
<ol start="5">
<li>마감일 스케줄링</li>
</ol>
<ul>
<li>마감일 순 정렬, 초과하면 가치 낮은 것 제거</li>
</ul>
<ol start="6">
<li>비용 최소화</li>
</ol>
<ul>
<li>작은 비용부터 처리하거나 싼 곳에서 최대한 처리</li>
</ul>
<ol start="7">
<li>누적 최적</li>
</ol>
<ul>
<li>현재까지의 min/max 유지하며 판단</li>
</ul>
<ol start="8">
<li>문자열/스택 그리디</li>
</ol>
<ul>
<li>앞자리·사전순 우선, 불리한 이전 선택 제거</li>
</ul>
<ol start="9">
<li>수학적 그리디</li>
</ol>
<ul>
<li>수의 성질과 연산 규칙 이용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 1회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-1%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-1%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Mon, 29 Jun 2026 13:03:06 GMT</pubDate>
            <description><![CDATA[<h3 id="1-정보처리기사-취득-준비">1. 정보처리기사 취득 준비</h3>
<p>요구사항 개발에서는 사용자의 요구사항을 수집, 분석, 명세, 확인하는 절차를 학습하였다. 특히 기능 요구사항과 비기능 요구사항의 차이를 이해하고, 요구사항이 명확하게 정의되어야 이후 설계와 구현 과정에서 오류를 줄일 수 있다는 점을 배웠다.</p>
<p>UML에서는 시스템의 구조와 동작을 시각적으로 표현하는 방법을 학습하였다. 유스케이스 다이어그램을 통해 사용자와 시스템 간의 상호작용을 표현하고, 클래스 다이어그램을 통해 클래스 간의 관계를 나타내는 방법을 익혔다.
<img src="https://velog.velcdn.com/images/jhdai_ly/post/745f5a7d-7d5c-4a09-a079-b37af284b74c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/f966583f-6528-485d-a37f-a5affa7e06b9/image.png" alt=""></p>
<p>UI 환경 분석과 UI 표준 및 지침에서는 사용자의 사용 환경을 고려하여 화면을 설계해야 한다는 점을 배웠다. 또한 일관성, 가독성, 접근성 등을 고려한 UI 설계가 사용자 편의성과 직결된다는 것을 알 수 있었다.</p>
<h3 id="2-코딩테스트-공부">2. 코딩테스트 공부</h3>
<p>이번 주에는 코딩테스트 대비를 위해 필요한 학습 내용들을 선별하는 시간을 가졌다. 또한 이후 기본 알고리즘 문제 풀이를 진행하고, 문제 해결 과정을 소스코드로 구현하는 연습을 하였다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/5c4f8c92-7182-4ba8-a893-6270536e9b0a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 1회차 (계획)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-1%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-1%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Mon, 29 Jun 2026 12:57:22 GMT</pubDate>
            <description><![CDATA[<h3 id="1-정보처리기사-취득">1. 정보처리기사 취득</h3>
<p>소프트웨어 설계 과목에서 아래 주제들에 대한 학습 진행</p>
<ul>
<li>요구사항 개발</li>
<li>UML</li>
<li>UI  환경 분석</li>
<li>UI 표준 및 지침</li>
</ul>
<h3 id="2-코딩테스트-공부">2. 코딩테스트 공부</h3>
<p>코딩테스트 문제 풀이를 진행</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 하계 모각코 - 전체 목표]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-%EC%A0%84%EC%B2%B4-%EB%AA%A9%ED%91%9C</link>
            <guid>https://velog.io/@jhdai_ly/2026-%ED%95%98%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-%EC%A0%84%EC%B2%B4-%EB%AA%A9%ED%91%9C</guid>
            <pubDate>Mon, 29 Jun 2026 10:58:05 GMT</pubDate>
            <description><![CDATA[<p>2026 하계 모각코 목표는 다음과 같다.</p>
<h2 id="1-취업-코딩테스트-학습">1. 취업 코딩테스트 학습</h2>
<p>일부 전산직 및 금융공기업 입사 과정에서 코딩테스트를 필요로 하는 경우가 있다. 요구되는 수준의 코딩 테스트 학습을 진행할 것이다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/20904c23-c8c5-4311-a1c7-ad29752089e0/image.png" alt=""></p>
<h2 id="2-정보처리기사-취득">2. 정보처리기사 취득</h2>
<p>방학 기간을 활용하여 정보처리기사를 취득하고, 전공 공부 내용을 정리할 예정이다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/755a6f17-6cca-46d6-85aa-1fd3a4896a1e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 동계 모각코 - 6회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Tue, 10 Feb 2026 03:45:30 GMT</pubDate>
            <description><![CDATA[<p>부제 : 2026 동계 모각코를 마무리하며</p>
<ol>
<li>ADsP 자격증 취득</li>
</ol>
<p>모각코 활동 지원비로 교재를 구매할 수 있다고 하여, 자격증 취득을 위한 이론서를 구매했고, 공부를 어느정도 마무리 하고 있다. 학습을 위한 지원금이 제공되어 좋았다고 생각한다.
시험은 지난주 토요일, 2/7일날 응시했다. 채점은 2월 말까지 마무리 된다고 하여, 조금 기다려 봐야겠다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/1c37793d-d4f4-424e-9929-b57e1ccae8ad/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/ccfb3953-79ec-4a06-b770-3af840efe78c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/1eeba8b0-edbc-4862-b46a-c6ce78e18e26/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/ea439259-1a06-4a57-a18b-fba6f60804a4/image.png" alt=""></p>
<ol start="2">
<li>그래프 기계학습 (스탠포드 강의 활용)
한달 정도 되는 시간 동안 그래프 기계학습 전반을 훑어보는 프로젝트가 알차게 마무리된 것 같아 기쁘다.
<img src="https://velog.velcdn.com/images/jhdai_ly/post/ed0c241c-0826-4c9f-9c63-c7605093ac40/image.png" alt=""></li>
</ol>
<p>세상이 너무 좋아져서 물어보고 싶은 것들을 바로바로 해결할 수 있어 좋았다. 앞으로는 학부연구생으로서 연구 아이디어를 실현시킬 수 있도록 공부해야할 것 같다. 우선 라인그래프 기반 그래프 신경망에 관심이 있어, 해당 논문을 읽어봤다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/0b3dc864-9b26-45ea-9f24-fcdd29471952/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/0b2ba55e-d93d-4750-9521-ed2c7b298e09/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 동계 모각코 - 6회차 (계획)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-6%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Tue, 10 Feb 2026 03:08:11 GMT</pubDate>
            <description><![CDATA[<p>모각코의 마지막 회차 계획은 우선 아래 활동들에 대한 매듭을 짓겠다. 
또 6주동안의 모각코 활동을 되돌아 보며 그동안 내가 공부했던 것들에 대해 정리해볼 것이다.</p>
<ul>
<li><p>ADsP 자격증 취득 (2/7 시험을 응시했다)
<img src="https://velog.velcdn.com/images/jhdai_ly/post/cd3a1619-afb3-4dec-8e25-ab380fe4e2c3/image.png" alt=""></p>
</li>
<li><p>CS224 Machine Learning with Graph 강의 수강을 마무리 한다.
<img src="https://velog.velcdn.com/images/jhdai_ly/post/38a42fcb-53e4-4148-9d9b-21f2ec23b0a3/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[도서리뷰] 2026 이기적 SQLD 이론 + 기출문제 구매 후기]]></title>
            <link>https://velog.io/@jhdai_ly/%EB%8F%84%EC%84%9C%EB%A6%AC%EB%B7%B0-2026-%EC%9D%B4%EA%B8%B0%EC%A0%81-SQLD-%EC%9D%B4%EB%A1%A0-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-%EA%B5%AC%EB%A7%A4-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@jhdai_ly/%EB%8F%84%EC%84%9C%EB%A6%AC%EB%B7%B0-2026-%EC%9D%B4%EA%B8%B0%EC%A0%81-SQLD-%EC%9D%B4%EB%A1%A0-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-%EA%B5%AC%EB%A7%A4-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Wed, 04 Feb 2026 11:56:42 GMT</pubDate>
            <description><![CDATA[<p>최근 영진닷컴 이기적 교재로 ADsP를 공부하며, SQLD 자격증도 취득해볼까 생각을 했고 마찬가지로 영진닷컴 교재로 선택했다. 여러 이유가 있겠지만, ADsP 교재를 구매했던 기준과 같이 적절한 분량과 충분한 연습문제를 풀 수 있다는 점이 마음에 들었다.</p>
<p>학습하기에 너무 좋은 구성으로 되어있어 SQLD 자격증 취득을 고려하고 있는 분들께 적극 권해주고 싶은 마음으로 후기를 남긴다.</p>
<p>특히 SQLD 교재를 살펴보면서 가장 인상 깊었던 점은 비전공자도 충분히 이해할 수 있도록 단계적으로 설명되어 있다는 점이었다. SQL이라는 과목 자체가 처음 접하면 낯설고, 문법 하나하나가 암기처럼 느껴질 수 있는데, 이기적 SQLD 교재는 단순히 문법 나열에 그치지 않고 “왜 이런 쿼리가 필요한지”, “실무에서는 어떤 식으로 활용되는지”를 함께 설명해 주어 학습 부담이 훨씬 덜했다. 만약 어렵게 느껴진다면 저자 직강 동영상 강의도 무료로 제공된다고 하니 참고해보면 도움이 될 듯 하다. </p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/2ebc2de4-bbb7-45b5-9fdf-adbb9ef9051a/image.png" alt=""></p>
<p>또 책을 살펴보면서 알게 된 점은 이기적 스터디 카페에서 도서 구매 인증을 하면 SQL 구문을 연습할 수 있는 실습 문제와 데이터를 제공해준다고 해서 참고하여 공부해보면 좋을 듯 싶다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/a620e9e9-de35-44a8-99d3-40d1fc2f6872/image.png" alt=""></p>
<p>ADsP를 공부할 때도 느꼈지만, 영진닷컴 이기적 시리즈의 가장 큰 장점은 과하지 않은 분량과 명확한 학습 포인트라고 생각한다. 자격증 서적이 분량이 다 천차만별인건 좀 이상한 일이지만, 너무 두껍고 방대한 교재는 처음엔 든든해 보여도, 진도가 나가지 않아 중도 포기하게 되는 경우가 많다. 반면 이기적 SQLD 교재는 시험에 꼭 필요한 내용 위주로 정리되어 있어 반복적으로 학습하기 좋은 구성이다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/f275d8d9-2e62-4abb-b569-65a7fc069d2d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/665bdd7d-c6c5-480a-98ad-e81826f75a98/image.png" alt=""></p>
<p>교재 구성 또한 학습 흐름에 최적화되어 있다. 이론 파트를 먼저 꼼꼼히 읽고 나면, 바로 해당 내용과 연계된 연습문제와 기출 유형 문제를 풀 수 있도록 구성되어 있어 자연스럽게 복습이 된다. 
<img src="https://velog.velcdn.com/images/jhdai_ly/post/fd507bed-7ed4-4740-b2ed-26e2da0b2581/image.png" alt=""></p>
<p>또 하나 마음에 들었던 부분은 실제 시험을 염두에 둔 문제 구성이다. SQLD 시험은 단순 암기보다는 개념 이해와 응용이 중요한 시험인데, 교재에 수록된 문제들이 최신 출제 경향을 잘 반영하고 있어 실전 감각을 키우는 데 도움이 된다. 특히 후반부에 있는 모의고사는 시간 제한을 두고 풀어보면 실제 시험장에서의 긴장감도 미리 경험할 수 있어 매우 유용했다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/bd436d2d-37df-4cf3-982b-2e0d7d429692/image.png" alt=""></p>
<p>개인적으로는 SQL이 데이터 분석, 개발, 기획 등 다양한 분야에서 활용도가 높다는 점에서 SQLD 자격증의 메리트도 크게 느끼고 있다. 단순히 자격증 취득을 넘어서, 실무에서 바로 활용할 수 있는 기본기를 다질 수 있다는 점이 이 교재를 선택하게 만든 또 하나의 이유다. 쿼리를 직접 작성해보며 데이터를 다루는 연습을 하다 보니, 데이터에 대한 이해도도 자연스럽게 높아지는 느낌을 받았다.</p>
<p>ADsP에 이어 SQLD까지 이기적 교재로 학습을 이어가면서 느낀 점은, ‘공부하는 사람의 입장을 정말 많이 고민한 교재’라는 것이다. 자격증 공부가 부담스럽고 막막하게 느껴지는 분들, 특히 혼자서 계획을 세워 공부해야 하는 독학러라면 이기적 SQLD 교재는 충분히 만족스러운 선택이 될 것 같다.</p>
<p>SQLD 자격증 취득을 고민 중이거나, 어떤 교재로 시작해야 할지 망설이고 있다면, 나처럼 적절한 분량과 풍부한 연습문제, 그리고 신뢰할 수 있는 구성을 갖춘 이기적 SQLD 교재로 시작해보는 것을 추천하며 후기를 마치고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 동계 모각코 - 5회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Tue, 03 Feb 2026 06:04:57 GMT</pubDate>
            <description><![CDATA[<ol>
<li>GNN의 표현력을 수학적으로 증명해보며 WL-Test, GIN 신경망의 필요성에 대해 알아봤다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/e985fb0a-52a5-4576-9c06-a2546d7077f6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/d255f4f8-42d3-411a-80a7-a80d871d4046/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/afa9e400-3779-4cd6-96c3-a2b0437102d3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 동계 모각코 - 5회차 (계획)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-5%ED%9A%8C%EC%B0%A8-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Tue, 03 Feb 2026 02:53:42 GMT</pubDate>
            <description><![CDATA[<ol>
<li>Stanford CS224W 강의 수강
GNN의 표현력에 대해서 공부해볼 계획이다.</li>
</ol>
<ul>
<li>How Expressive are Graph Neural Networks 논문을 위주로 학습해보면 좋을 듯 하다.
<img src="https://velog.velcdn.com/images/jhdai_ly/post/468bb8af-ab35-46e4-81b8-c396f5eb785b/image.png" alt=""></li>
</ul>
<p>세부 학습 소주제는 다음과 같이 계획하였다.</p>
<ul>
<li>Local Neighborhood Structures</li>
<li>Rooted subtree</li>
<li>Injective Function</li>
<li>GIN</li>
<li>MLP</li>
<li>Universal Approximation Theorem</li>
<li>Multi-set Fuction</li>
</ul>
<ol start="2">
<li>Adsp 데이터 모델링 파트 학습
3과목에 해당하는 부분이다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[서평] 관성끊기 (빌 오한론)]]></title>
            <link>https://velog.io/@jhdai_ly/%EC%84%9C%ED%8F%89-%EA%B4%80%EC%84%B1%EB%81%8A%EA%B8%B0-%EB%B9%8C-%EC%98%A4%ED%95%9C%EB%A1%A0</link>
            <guid>https://velog.io/@jhdai_ly/%EC%84%9C%ED%8F%89-%EA%B4%80%EC%84%B1%EB%81%8A%EA%B8%B0-%EB%B9%8C-%EC%98%A4%ED%95%9C%EB%A1%A0</guid>
            <pubDate>Sat, 31 Jan 2026 08:48:28 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/1584c02c-e764-4d41-969c-e1b7b889e724/image.png" alt=""></p>
<p><strong>#서평단 
#관성끊기
#행동변화</strong></p>
<p>빌 오한론, 『관성 끊기 - <strong>반복된 문제를 부수는 최소한의 행동 설계법</strong>』</p>
<hr>
<p>우리는 살아가면서 수많은 문제를 마주친다. 물론 그리 중요하지 않거나 쉽게 해결되는 문제도 있지만, 일부 문제는 지속적으로 삶에 등장하여 우리를 괴롭게 만들기도 한다.</p>
<p>그런 문제는 보통, 우리의 행동 흐름이 이미 굳어져 있기 때문에 더욱 접근하기 어려운 것 같다. 예를 들면 내가 더 나은 선택 A와 더 나쁜 선택 B 중, 꾸준히 B를 선택해왔다면 이미 습관이 되어버린 그 선택을 바꾸는 것은 무척 어려울 것이다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/4ff300d2-8615-41eb-addb-7106aab7e970/image.png" alt=""></p>
<p>나는 &#39;관성 끊기&#39;라는 책 제목을 보고, 늘 하던 방식대로 살아가는 삶에 작은 변화를 만들어낼 수 있는 이야기가 담겨 있을 것 같아 이 책을 집어 들었다.</p>
<hr>
<p>우리는 문제가 반복될수록 “왜 이런 일이 생겼지?”라는 질문을 더 자주 던지게 되는 것 같다. 그 원인을 해결하기 위해 더욱 정교하게 해석하려고 노력하는 것이다. 하지만 그렇게 쉽게 문제가 해결되지는 않음을 우리는 매번 느끼고 있다. 즉, &#39;문제가 반복&#39;되고 있는 것이다.</p>
<p>이 책은 총 3부에 걸쳐 반복된 문제를 극복하는 방법을 제시한다. 1부 &#39;문제 대응 방식 바꾸기&#39;에서는 패턴 깨기, 효과 있는 것 시도하기, 2부 &#39;문제를 바라보는 관점 바꾸기&#39;에서는 과거와 감정에서 벗어나기, 주의 전환하기, 문제 해결을 위해 미래 이용하기, 문제적 신념을 해결 지향적 생각으로 바꾸기, 3부 &#39;해결 지향적 접근법 구체적으로 이용하기&#39;에서는 해결 지향적 관계를 포함한 4가지의 방법이 그것이다.</p>
<p>우선 나에게 인상깊었던 부분 중 하나는 &#39;문제를 과도하게 분석하는 습관&#39;이 문제 해결에 악영향을 미칠 수 있다는 인사이트였다. 덧붙여 이러한 분석하는 습관을 &#39;해결 지향적 접근&#39;으로 전환하라는 메시지를 던진다.</p>
<blockquote>
<p> 소크라테스는 성찰하지 않는 삶은 살 가치가 없다고 말했다. 그러나 지나친 자기 성찰적 삶은 당신을 죽은 사람처럼 만든다. 《관성 끊기 中》</p>
</blockquote>
<blockquote>
<p> 해결 지향적 접근법은 다르다. 이것은 사람들이 다양한 문제를 가지고 있다는 점을 참작한다. (중략) 해결 지향적 접근법은 문제의 원인보다 그 사람이 지금 하고 있는 행동 중에서 변화의 도움이 될 만한 요소를 찾는 데 집중한다. 《관성 끊기 中》</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/6cc0f62f-484d-4e95-b486-5a2d61ec7ee9/image.png" alt=""></p>
<p>책에서 반복적으로 강조하는 해결 지향적인 행동에 대해, 저자는 몇가지 해결 열쇠를 제공한다. 그 중 두번째는 해결 패턴을 찾아서 활용하는 것이다. 문제를 없애려 애쓰기보다, 문제가 잠시나마 약해졌던 순간에 주목하라는 제안이다. 언제는 분명 같은 문제였는데 덜 힘들었고, 더 버틸 만했고, 어쩌면 생각보다 잘 넘어갔던 때가 있다. 저자는 바로 그때를 그냥 지나치지 말라고 말한다.</p>
<p>우리는 보통 문제가 가장 심각해졌을 때만 그것을 분석한다. 왜 이렇게까지 되었는지, 무엇이 잘못되었는지를 집요하게 되짚는다. 하지만 해결 지향적 관점은 질문의 방향을 바꾼다. “왜 망가졌는가”가 아니라 “언제는 괜찮았는가”를 묻는다. 그리고 그 차이를 만들어낸 행동, 선택, 태도를 찾아내어 다시 써먹는다. 해결은 완전히 새로운 해답에서 나오기보다, 이미 한 번 효과를 냈던 행동의 반복에서 비롯된다는 것이다.</p>
<p>이 접근이 흥미로운 이유는, 문제 해결의 실마리가 이미 내 안에 있다고 전제하기 때문인 것 같다. 해결되지 않았다는 사실이 곧 무능함은 아닐 것이고, 오히려 문제 속에서도 균열을 만들었던 작은 성공들이 있었을것이다. 저자는 그 패턴을 의식적으로 끌어올리는 것을 해결로 가는 현실적인 방법으로 제시한다.</p>
<p>나는 이 부분을 읽고 문제가 지속되고 있다고 느끼긴 하지만, &#39;항상&#39;인 것은 아니라는 생각을 해보게 됐다.</p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/d5efd19f-d419-430b-80bb-aaca13bd8421/image.png" alt=""></p>
<p>독서를 마무리하며 해결지향적으로 살겠다는 결심을 해본다. 책에서 구체적으로 조언되는 문제에 다르게 대응하는, 해결 지향적인 삶은 꽤 즐거운 일이 될 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026 동계 모각코 - 4회차 (결과)]]></title>
            <link>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-4%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@jhdai_ly/2026-%EB%8F%99%EA%B3%84-%EB%AA%A8%EA%B0%81%EC%BD%94-4%ED%9A%8C%EC%B0%A8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Fri, 30 Jan 2026 04:21:13 GMT</pubDate>
            <description><![CDATA[<ol>
<li>아래 주제들에 대한 학습을 진행하였습니다</li>
</ol>
<ul>
<li>GNN Augumentation and Training</li>
<li>Prediction with GNNs</li>
<li>Virtual nodes/edges</li>
<li>constant vs one-hot 방식 비교 (Augmentation)</li>
<li>Prediction Heads (Node/Edge/Graph-Level)</li>
<li>Hierarchical Global Pooling</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/d261e138-c6e2-496f-bb37-8c3610283163/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/c5a3096f-b911-495e-ba0a-c7987e8453a2/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/ddc18902-8715-47ea-bed0-648dd83f5585/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/8e7d9a69-d3d9-4b1c-8dbd-7355ff6e9727/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/a95b1537-73e9-43f2-8501-7075f4de3ddc/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/456c38a7-8842-4374-beb9-81ca77bdb30b/image.png" alt="">
<img src="https://velog.velcdn.com/images/jhdai_ly/post/74e79f3d-99d2-4b77-8652-890cdb669a57/image.png" alt=""></p>
<ol start="2">
<li>ADSP 3과목 데이터 분석 파트 학습</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jhdai_ly/post/10631ad3-e0b2-445e-a3d3-25cbb597dcfa/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>